ongoing x11 experiment
This commit is contained in:
		| @ -2,6 +2,9 @@ | ||||
|  | ||||
| class X11(Object) from 'x11' | ||||
| { | ||||
| 	var display_base := nil. | ||||
| 	var shell_container := nil. | ||||
|  | ||||
| 	var windows. ## all windows registered | ||||
|  | ||||
| 	var event_loop_sem, event_loop_proc. | ||||
| @ -12,15 +15,13 @@ class X11(Object) from 'x11' | ||||
| 	var mouse_event. | ||||
| 	var mouse_wheel_event. | ||||
|  | ||||
| 	method(#primitive,#liberal) _connect(name). | ||||
| 	method(#primitive) _disconnect. | ||||
| 	method(#primitive) _get_base. | ||||
| 	method(#primitive) _get_fd. | ||||
| 	method(#primitive) _get_event. | ||||
| 	method(#class,#primitive,#liberal) _open_display(name). | ||||
| 	method(#class,#primitive) _close_display(display). | ||||
| 	method(#class,#primitive) _get_fd(display). | ||||
| 	method(#class,#primitive) _get_event(display, event). | ||||
| 	method(#class,#primitive) _create_window(display, window, x, y, width, height, fgcolor, bgcolor). | ||||
|  | ||||
| 	method server { ^self } | ||||
| 	method serverBase { ^self _get_base } | ||||
| 	method windowBase { ^nil } | ||||
| 	method(#primitive) _get_evtbuf. | ||||
| } | ||||
|  | ||||
| class X11.Exception(System.Exception) | ||||
| @ -107,99 +108,147 @@ class X11.ExposeEvent(X11.Event) | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| ## --------------------------------------------------------------------------- | ||||
| ## Window | ||||
| ## X11 Widgets | ||||
| ## --------------------------------------------------------------------------- | ||||
|  | ||||
| class X11.Widget(Object) | ||||
| { | ||||
| 	var(#get,#set) parent. | ||||
| 	var(#get,#set) | ||||
| 		parent   := nil, | ||||
| 		x        := 0, | ||||
| 		y        := 0, | ||||
| 		width    := 0, | ||||
| 		height   := 0, | ||||
| 		fgcolor  := 0, | ||||
| 		bgcolor  := 0, | ||||
| 		realized := false. | ||||
|  | ||||
| 	method server | ||||
| 	method displayOn: grctx | ||||
| 	{ | ||||
| 		| p pp | | ||||
| 		p := self. | ||||
| 		while ((pp := p parent) notNil) { p := pp }. | ||||
| 		^p server. | ||||
| 	} | ||||
|  | ||||
| 	method serverBase { ^self server serverBase } | ||||
| 	method windowBase { ^nil} | ||||
|  | ||||
|  | ||||
| 	##method displayOn: gc { } | ||||
| } | ||||
|  | ||||
| class X11.Window(selfns.Widget) from 'x11.win' | ||||
| { | ||||
| 	var bounds. | ||||
|  | ||||
| 	method(#primitive) _make_window(server, x, y, width, height, parent). | ||||
| 	method(#primitive) _kill_window. | ||||
| 	method(#primitive) _get_base. | ||||
| 	method(#primitive) _get_bounds(rect). | ||||
| 	method(#primitive) _set_bounds(rect). | ||||
|  | ||||
| 	method(#class) new: parent | ||||
| 	method displayBase | ||||
| 	{ | ||||
| 		^(super new) __open_on: parent. | ||||
| 		if (self.parent isNil) { ^nil }. | ||||
| 		^self.parent displayBase. | ||||
| 	} | ||||
|  | ||||
| 	method initialize | ||||
| 	method realize | ||||
| 	{ | ||||
| 		self.bounds := selfns.Rectangle new. | ||||
| 	} | ||||
|  | ||||
| 	method __open_on: parent | ||||
| 	{ | ||||
| 		| server winbase | | ||||
|  | ||||
| 		server := parent server. | ||||
| 		winbase := self _make_window (server serverBase, 5, 5, 400, 400, parent windowBase). | ||||
|  | ||||
| 		(* | ||||
| 		if (server _make_window (5, 5, 400, 400, parent, self) isError) | ||||
| 		{ | ||||
| 			X11.Exception signal: 'cannot make a window' | ||||
| 		}. | ||||
| 		*) | ||||
|  | ||||
| 		if (server ~= parent) | ||||
| 		{ | ||||
| 			self.parent := parent. | ||||
| 			self.parent addWidget: self. | ||||
| 		}. | ||||
|  | ||||
| 		server addWindow: self. | ||||
|  | ||||
| 		self _get_bounds(self.bounds). | ||||
| 		self windowOpened. | ||||
| 	} | ||||
|  | ||||
| 	method dispose | ||||
| 	{ | ||||
| 		if (self windowBase notNil) | ||||
|      } | ||||
| } | ||||
|  | ||||
| class X11.Label(X11.Widget) | ||||
| { | ||||
| 	var(#get) text := ''. | ||||
|  | ||||
| 	method text: text | ||||
| 	{ | ||||
| 		self.text := text. | ||||
| 		self displayOn: nil. | ||||
| 	} | ||||
|  | ||||
| 	method displayOn: grctx | ||||
| 	{ | ||||
| 		## grctx _fillRectangle (). | ||||
| 		## grctx _drawText (...). | ||||
| 		## TODO Draw Text... | ||||
| 	} | ||||
|  | ||||
| 	method realize | ||||
| 	{ | ||||
| 		## if i want to use a window to represent it, it must create window here. | ||||
| 		## otherwise, do other works in displayOn??? | ||||
| 	} | ||||
|  | ||||
| 	method dispose | ||||
| 	{ | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class X11.Composite(X11.Widget) | ||||
| { | ||||
| 	var children. | ||||
|  | ||||
| 	method initialize | ||||
| 	{ | ||||
| 		self.children := LinkedList new. | ||||
| 	} | ||||
|  | ||||
| 	method add: widget | ||||
| 	{ | ||||
| 		if (widget parent notNil) | ||||
| 		{ | ||||
| 			self windowClosing. | ||||
| 			selfns.Exception signal: 'Cannot add an already added widget'. | ||||
| 		}. | ||||
|  | ||||
| 			self server removeWindow: self. | ||||
| 			if (self.parent notNil) { self.parent removeWidget: self }. | ||||
| 		self.children addLast: widget. | ||||
| 		widget parent: self. | ||||
| 	} | ||||
|  | ||||
| 			self _dispose_window. | ||||
| 			self windowClosed. ## you can't make a primitive call any more | ||||
| 	method remove: widget | ||||
| 	{ | ||||
| 		| link | | ||||
| 		if (widget parent =~ self) | ||||
| 		{ | ||||
| 			selfns.Exception sinal: 'Cannot remove a foreign widget' | ||||
| 		}. | ||||
|  | ||||
| 			##self.wid := nil. | ||||
| 			self.parent := nil. | ||||
| 		## TODO: unmap and destroy... | ||||
| 		link := self.children findLink: widget. | ||||
| 		self.children removeLink: link. | ||||
| 		widget parent: nil. | ||||
| 	} | ||||
|  | ||||
| 	method childrenCount | ||||
| 	{ | ||||
| 		^self.children size | ||||
| 	} | ||||
|  | ||||
| 	method dispose | ||||
| 	{ | ||||
|           self.children do: [:child | child dispose ] | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class X11.Shell(X11.Composite) | ||||
| { | ||||
| 	var(#get) title. | ||||
| 	var(#get,#set) displayBase. | ||||
|  | ||||
| 	method new: title | ||||
| 	{ | ||||
| 		self.title := title. | ||||
| 	} | ||||
|  | ||||
| 	method title: title | ||||
| 	{ | ||||
| 		self.title := title. | ||||
| 		if (self.realized) | ||||
| 		{ | ||||
| 			## set window title of this window. | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	method windowBase { ^self _get_base } | ||||
| } | ||||
|  | ||||
| class X11.FrameWindow(selfns.Window) | ||||
| { | ||||
| 	method(#class) new: server | ||||
| 	method realize | ||||
| 	{ | ||||
| 		^super new: server. | ||||
| 		| wind | | ||||
| 		if (self.realized)  { ^self }. | ||||
|  | ||||
| 		wind := X11 _create_window(self.displayBase, nil, self.x, self.y, self.width, self.height, self.fgcolor, self.bgcolor). | ||||
| 		if (wind isError) | ||||
| 		{ | ||||
| 			self.Exception signal: ('Cannot create shell ' & self.title). | ||||
| 		}. | ||||
|  | ||||
| 		self.children do: [:child | child realize ]. | ||||
| 		self.realized := true. | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -210,30 +259,46 @@ extend X11 | ||||
| { | ||||
| 	method(#class) new | ||||
| 	{ | ||||
| 		^(super new) __connect_to_server: nil. | ||||
| 		^(super new) __connect_to: nil. | ||||
| 	} | ||||
|  | ||||
| 	method __connect_to_server: name | ||||
| 	method __connect_to: name | ||||
| 	{ | ||||
| 		| base | | ||||
| 		base := self _connect(name). | ||||
| 		if (base isError) { X11.Exception signal: 'cannot connect to server' }. | ||||
| 		##self.base := base. | ||||
| 		base := X11 _open_display(name). | ||||
| 		if (base isError) { self.Exception signal: 'cannot open display' }. | ||||
| 		self.display_base := base. | ||||
| 	} | ||||
|  | ||||
| 	method close | ||||
| 	method dispose | ||||
| 	{ | ||||
| 		if (self _get_base notNil) | ||||
| 		if (self.display_event notNil) | ||||
| 		{ | ||||
| 			self _disconnect. | ||||
| 			##self.cid := nil. | ||||
| 		} | ||||
| 			X11 _free_event. | ||||
| 			self.display_event := nil. | ||||
| 		}. | ||||
|  | ||||
| 		if (self.shell_container notNil) | ||||
| 		{ | ||||
| 			self.shell_container dispose. | ||||
| 			self.shell_container := nil. | ||||
| 		}. | ||||
|  | ||||
| 		if (self.display_base notNil) | ||||
| 		{ | ||||
|  | ||||
| 			X11 _close_display (self.display_base). | ||||
| 			self.display_base := nil. | ||||
| 		}l | ||||
| 	} | ||||
|  | ||||
| 	method initialize | ||||
| 	{ | ||||
| 		super initialize. | ||||
|  | ||||
| 		self.shell_container := self.Composite new. | ||||
| 		self.display_event := self _alloc_event. | ||||
|  | ||||
| 		self.windows := System.Dictionary new: 100. | ||||
|  | ||||
| 		self.expose_event := self.ExposeEvent new. | ||||
| @ -271,30 +336,25 @@ extend X11 | ||||
| 		}. | ||||
| 	} | ||||
|  | ||||
| 	method connect | ||||
| 	method addShell: shell | ||||
| 	{ | ||||
| 		| cid | | ||||
| 		if (self.windows isNil) | ||||
| 		if (shell displayBase isNil) | ||||
| 		{ | ||||
| 			if ((cid := self _connect) isError)  { ^cid }. | ||||
| 			##self.cid := cid. | ||||
| 			self.windows := System.Dictionary new. | ||||
| 			self.shell_container add: shell. | ||||
| 			shell displayBase: self.display_base. | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	method disconnect | ||||
| 	method removeShell: shell | ||||
| 	{ | ||||
| 		if (self.windows notNil) | ||||
| 		if (shell displayBase notNil) | ||||
| 		{ | ||||
| 			self.windows do: [ :frame | | ||||
| 				frame close. | ||||
| 			]. | ||||
| 			self.windows := nil. | ||||
| 			self _disconnect. | ||||
| 			self.shell_container remove: shell. | ||||
| 			shell displayBase: nil. | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	method addWindow: window | ||||
| 	method registerWindow: window | ||||
| 	{ | ||||
| 		^self.windows at: (window windowBase) put: window. | ||||
| 	} | ||||
| @ -309,18 +369,18 @@ extend X11 | ||||
| 		if (self.event_loop_sem isNil) | ||||
| 		{ | ||||
| 			self.event_loop_sem := Semaphore new. | ||||
| 			Processor signal: self.event_loop_sem onInput: (self _get_fd). | ||||
| 			Processor signal: self.event_loop_sem onInput: (X11 _get_fd(self.display_base)). | ||||
| 			self.event_loop_proc := [ | ||||
| 				| event ongoing | | ||||
|  | ||||
| 				ongoing := true. | ||||
| 				while (self.windows size > 0) | ||||
| 				while (self.shell_container childrenCount > 0) | ||||
| 				{ | ||||
| ###'Waiting for X11 event...' dump. | ||||
| 					self.event_loop_sem wait. | ||||
| 					if (ongoing not) { break }. | ||||
|  | ||||
| 					while ((event := self _get_event) notNil) | ||||
| 					while (self _get_event(self.display_base, self.display_event)) | ||||
| 					{ | ||||
| 						if (event isError) | ||||
| 						{ | ||||
| @ -338,7 +398,8 @@ extend X11 | ||||
| 				Processor unsignal: self.event_loop_sem. | ||||
| 				self.event_loop_sem := nil. | ||||
|  | ||||
| 				self disconnect. | ||||
| 				self dispose. | ||||
| 'CLOSING X11 EVENT LOOP' dump. | ||||
| 			] fork. | ||||
| 		} | ||||
| 	} | ||||
| @ -408,91 +469,36 @@ extend X11 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class MyWidget(Window) | ||||
| { | ||||
| } | ||||
|  | ||||
| class MyFrame(X11.FrameWindow) | ||||
| { | ||||
| 	var gc. | ||||
|  | ||||
|  | ||||
| 	method windowOpened | ||||
| 	{ | ||||
| 		super windowOpened. | ||||
|  | ||||
| 		(* | ||||
| 		if (self.gc isNil) | ||||
| 		{ | ||||
| 			self.gc := X11.GC new: self. | ||||
| self.gc foreground: 10. | ||||
| self.gc _drawLine(10, 20, 30, 40). | ||||
| self.gc _drawRect(10, 20, 30, 40). | ||||
| self.gc foreground: 20. | ||||
| self.gc _drawRect(100, 100, 200, 200). | ||||
| 		}. | ||||
|  | ||||
| 		self.b1 := MyWidget new: self.*) | ||||
|  | ||||
| 		self windowResized. | ||||
| 	} | ||||
|  | ||||
| 	method windowClosing | ||||
| 	{ | ||||
| 		super windowClosing. | ||||
| 		(*if (self.gc notNil) | ||||
| 		{ | ||||
| 			self.gc close. | ||||
| 			self.gc := nil. | ||||
| 		}*) | ||||
| 	} | ||||
|  | ||||
| 	method windowResized | ||||
| 	{ | ||||
| 		(* | ||||
| 		| rect | | ||||
|  | ||||
| 		super windowResized. | ||||
|  | ||||
| 		rect := self bounds. | ||||
| 		rect x: 0; y: 0; height: ((rect height) quo: 2); width: ((rect width) - 2). | ||||
| 		self.b1 bounds: rect;*) | ||||
| 	} | ||||
|  | ||||
| 	method expose: event | ||||
| 	{ | ||||
| 		super expose: event. | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class MyObject(Object) | ||||
| { | ||||
| 	var disp1, shell1, shell2. | ||||
|  | ||||
| 	method main1 | ||||
| 	{ | ||||
| 		self.disp1 := X11 new. | ||||
|  | ||||
| 		shell1 := (X11.Shell new title: 'Shell 1'). | ||||
| 		shell2 := (X11.Shell new title: 'Shell 2'). | ||||
|  | ||||
| 		shell1 x: 10; y: 20; width: 100; height: 100. | ||||
| 		shell2 x: 200; y: 200; width: 200; height: 200. | ||||
|  | ||||
| 		self.disp1 addShell: shell1. | ||||
| 		self.disp1 addShell: shell2. | ||||
|  | ||||
| 		self.shell1 add: (X11.Label new text: 'xxxxxxxx'). | ||||
| 		self.shell1 realize. | ||||
| 		self.shell2 realize. | ||||
|  | ||||
| 		self.disp1 enterEventLoop. ## this is not a blocking call. it spawns another process. | ||||
| 	} | ||||
|  | ||||
| 	method(#class) main | ||||
| 	{ | ||||
| 		| disp1 disp2 disp3 f q p | | ||||
|  | ||||
| 		disp1 := X11 new. | ||||
| 		disp2 := X11 new. | ||||
| 		disp3 := X11 new. | ||||
|  | ||||
| 		f := MyFrame new: disp2. | ||||
| 		q := MyFrame new: disp1. | ||||
| 		p := MyFrame new: disp3. | ||||
|  | ||||
| 		disp1 enterEventLoop. ## this is not a blocking call. it spawns another process. | ||||
| 		disp2 enterEventLoop. | ||||
| 		disp3 enterEventLoop. | ||||
|  | ||||
| 		##disp1 := X11 new. | ||||
| 		##f := MyFrame new. | ||||
| 		##f add: Button new. | ||||
| 		##f add: Button new. | ||||
| 		##g := MyFrame new. | ||||
| 		##g add: (b := Button new). | ||||
| 		##disp1 add: f. | ||||
| 		##disp1 add: g. | ||||
| 		##disp1 enterEventLoop. | ||||
| 		^self new main1 | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -38,13 +38,6 @@ | ||||
| #define MC MOO_METHOD_CLASS | ||||
| #define MI MOO_METHOD_INSTANCE | ||||
|  | ||||
| typedef struct x11_t x11_t; | ||||
| struct x11_t | ||||
| { | ||||
| 	Display* disp; | ||||
| 	XEvent* curevt; | ||||
| }; | ||||
|  | ||||
| typedef struct x11_win_t x11_win_t; | ||||
| struct x11_win_t | ||||
| { | ||||
|  | ||||
							
								
								
									
										280
									
								
								moo/mod/x11.c
									
									
									
									
									
								
							
							
						
						
									
										280
									
								
								moo/mod/x11.c
									
									
									
									
									
								
							| @ -39,21 +39,36 @@ struct x11_modctx_t | ||||
|  | ||||
| /* ------------------------------------------------------------------------ */ | ||||
|  | ||||
| static moo_pfrc_t pf_connect (moo_t* moo, moo_ooi_t nargs) | ||||
| #if 0 | ||||
| static moo_pfrc_t pf_get_base (moo_t* moo, moo_ooi_t nargs) | ||||
| { | ||||
| 	x11_trailer_t* x11; | ||||
| 	Display* disp = MOO_NULL; | ||||
| 	XEvent* curevt = MOO_NULL; | ||||
| 	char* dispname = MOO_NULL; | ||||
|  | ||||
| 	x11 = (x11_trailer_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL); | ||||
|  | ||||
| 	if (x11->disp) | ||||
| 	{ | ||||
| 		MOO_DEBUG0 (moo, "<x11.connect> Unable to open a display multiple times\n"); | ||||
| 		MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EEXIST); | ||||
| 		goto oops; | ||||
| 		MOO_STACK_SETRET (moo, nargs, MOO_SMPTR_TO_OOP (x11->disp)); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ENOAVAIL); | ||||
| 	} | ||||
|  | ||||
| 	return MOO_PF_SUCCESS; | ||||
| } | ||||
|  | ||||
|  | ||||
| #endif | ||||
|  | ||||
| /* ------------------------------------------------------------------------ */ | ||||
|  | ||||
| static moo_pfrc_t pf_open_display (moo_t* moo, moo_ooi_t nargs) | ||||
| { | ||||
| 	x11_trailer_t* x11; | ||||
| 	Display* disp = MOO_NULL; | ||||
| 	XEvent* curevt = MOO_NULL; | ||||
| 	char* dispname = MOO_NULL; | ||||
|  | ||||
| 	if (nargs >= 1) | ||||
| 	{ | ||||
| @ -96,9 +111,6 @@ static moo_pfrc_t pf_connect (moo_t* moo, moo_ooi_t nargs) | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| 	x11->disp = disp; | ||||
| 	x11->curevt =  curevt; | ||||
|  | ||||
| 	MOO_ASSERT (moo, MOO_IN_SMPTR_RANGE(disp)); | ||||
|  | ||||
| 	MOO_STACK_SETRET (moo, nargs, MOO_SMPTR_TO_OOP(disp)); | ||||
| @ -112,57 +124,40 @@ oops: | ||||
| 	return MOO_PF_SUCCESS; | ||||
| } | ||||
|  | ||||
| static moo_pfrc_t pf_disconnect (moo_t* moo, moo_ooi_t nargs) | ||||
| static moo_pfrc_t pf_close_display (moo_t* moo, moo_ooi_t nargs) | ||||
| { | ||||
| 	x11_trailer_t* x11; | ||||
| 	moo_oop_t a0; | ||||
| 	 | ||||
| 	a0 = MOO_STACK_GETARG(moo, nargs, 0); | ||||
|  | ||||
| 	x11 = (x11_trailer_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL); | ||||
|  | ||||
| 	if (x11->curevt)  | ||||
| 	if (!MOO_OOP_IS_SMPTR(a0)) | ||||
| 	{ | ||||
| 		moo_freemem (moo, x11->curevt);  | ||||
| 		x11->curevt = MOO_NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (x11->disp) | ||||
| 	{ | ||||
| 		XCloseDisplay (x11->disp); | ||||
| 		x11->disp = MOO_NULL; | ||||
| 	} | ||||
|  | ||||
| 	MOO_STACK_SETRETTORCV (moo, nargs); | ||||
| 	return MOO_PF_SUCCESS; | ||||
| } | ||||
|  | ||||
| static moo_pfrc_t pf_get_base (moo_t* moo, moo_ooi_t nargs) | ||||
| { | ||||
| 	x11_trailer_t* x11; | ||||
|  | ||||
| 	x11 = (x11_trailer_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL); | ||||
|  | ||||
| 	if (x11->disp) | ||||
| 	{ | ||||
| 		MOO_STACK_SETRET (moo, nargs, MOO_SMPTR_TO_OOP (x11->disp)); | ||||
| 		MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ENOAVAIL); | ||||
| 		XCloseDisplay (MOO_OOP_TO_SMPTR(a0)); | ||||
| 		MOO_STACK_SETRETTORCV (moo, nargs); | ||||
| 	} | ||||
|  | ||||
| 	return MOO_PF_SUCCESS; | ||||
| } | ||||
|  | ||||
|  | ||||
| static moo_pfrc_t pf_get_fd (moo_t* moo, moo_ooi_t nargs) | ||||
| { | ||||
| 	x11_trailer_t* x11; | ||||
| 	moo_oop_t a0; | ||||
|  | ||||
| 	x11 = (x11_trailer_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL); | ||||
| 	a0 = MOO_STACK_GETARG(moo, nargs, 0); | ||||
|  | ||||
| 	if (x11->disp) | ||||
| 	if (!MOO_OOP_IS_SMPTR(a0)) | ||||
| 	{ | ||||
| 		int c; | ||||
| 		MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		moo_ooi_t c; | ||||
| 		c = ConnectionNumber(MOO_OOP_TO_SMPTR(a0)); | ||||
|  | ||||
| 		c = ConnectionNumber(x11->disp); | ||||
| 		if (!MOO_IN_SMOOI_RANGE(c)) | ||||
| 		{ | ||||
| 			MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ERANGE); | ||||
| @ -172,48 +167,210 @@ static moo_pfrc_t pf_get_fd (moo_t* moo, moo_ooi_t nargs) | ||||
| 			MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(c)); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ENOAVAIL); | ||||
| 	} | ||||
|  | ||||
| 	return MOO_PF_SUCCESS; | ||||
| } | ||||
|  | ||||
| static moo_pfrc_t pf_get_event (moo_t* moo, moo_ooi_t nargs) | ||||
| { | ||||
| 	x11_trailer_t* x11; | ||||
| 	 | ||||
| 	moo_oop_t a0, a1; | ||||
|  | ||||
| 	x11 = (x11_trailer_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL); | ||||
| 	if (XPending(x11->disp)) | ||||
| 	a0 = MOO_STACK_GETARG(moo, nargs, 0); /* display - SmallPointer (Display*) */ | ||||
| 	a1 = MOO_STACK_GETARG(moo, nargs, 1); /* event to return - SmallPointer (XEvent*) */ | ||||
|  | ||||
| 	 | ||||
| 	if (!MOO_OOP_IS_SMPTR(a0) || !MOO_OOP_IS_SMPTR(a1)) | ||||
| 	{ | ||||
| 		XNextEvent (x11->disp, x11->curevt); | ||||
| 		MOO_STACK_SETRET (moo, nargs, MOO_SMPTR_TO_OOP(x11->curevt)); | ||||
| 		MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		/* nil if there is no event */ | ||||
| 		MOO_STACK_SETRET (moo, nargs, moo->_nil); | ||||
| 		Display* disp; | ||||
| 		XEvent*  event; | ||||
|  | ||||
| 		disp = MOO_OOP_TO_SMPTR(a0); | ||||
| 		event = MOO_OOP_TO_SMPTR(a1); | ||||
| 		if (XPending(disp)) | ||||
| 		{ | ||||
| 			XNextEvent (disp, event); | ||||
| 			MOO_STACK_SETRET (moo, nargs, moo->_true); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			/* nil if there is no event */ | ||||
| 			MOO_STACK_SETRET (moo, nargs, moo->_false); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return MOO_PF_SUCCESS; | ||||
| } | ||||
|  | ||||
|  | ||||
| static moo_pfrc_t pf_get_evtbuf (moo_t* moo, moo_ooi_t nargs) | ||||
| { | ||||
| 	x11_trailer_t* tr; | ||||
|  | ||||
| 	tr = moo_getobjtrailer (moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL); | ||||
|  | ||||
| 	 | ||||
| 	return MOO_PF_SUCCESS; | ||||
| } | ||||
|  | ||||
| static moo_pfrc_t pf_create_window (moo_t* moo, moo_ooi_t nargs) | ||||
| { | ||||
| 	Window wind; /* Window -> XID, unsigned long */ | ||||
|  | ||||
| 	Display* disp; | ||||
| 	int scrn; | ||||
| 	Window parent; | ||||
| 	XSetWindowAttributes attrs; | ||||
|  | ||||
| 	moo_oop_t a0, a1, a2, a3, a4, a5, a6, a7; | ||||
|  | ||||
| 	a0 = MOO_STACK_GETARG(moo, nargs, 0); /* display - SmallPointer (Display*) */ | ||||
| 	a1 = MOO_STACK_GETARG(moo, nargs, 1); /* parent window - Integer or nil (Window) */ | ||||
| 	a2 = MOO_STACK_GETARG(moo, nargs, 2); /* x - SmallInteger */ | ||||
| 	a3 = MOO_STACK_GETARG(moo, nargs, 3); /* y - SmallInteger */ | ||||
| 	a4 = MOO_STACK_GETARG(moo, nargs, 4); /* width - SmallInteger */ | ||||
| 	a5 = MOO_STACK_GETARG(moo, nargs, 5); /* height - SmallInteger */ | ||||
| 	a6 = MOO_STACK_GETARG(moo, nargs, 6); /* fgcolor - SmallInteger */ | ||||
| 	a7 = MOO_STACK_GETARG(moo, nargs, 7); /* bgcolor - SmallInteger */ | ||||
|  | ||||
| 	if (!MOO_OOP_IS_SMPTR(a0) ||  | ||||
| 	    !MOO_OOP_IS_SMOOI(a2) || !MOO_OOP_IS_SMOOI(a3) || !MOO_OOP_IS_SMOOI(a4) || | ||||
| 	    !MOO_OOP_IS_SMOOI(a5) || !MOO_OOP_IS_SMOOI(a6) || !MOO_OOP_IS_SMOOI(a7)) | ||||
| 	{ | ||||
| 	einval: | ||||
| 		MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); | ||||
| 		goto done; | ||||
| 	} | ||||
|  | ||||
| 	disp = MOO_OOP_TO_SMPTR(a0); | ||||
|  | ||||
| 	if (a1 == moo->_nil)  | ||||
| 	{ | ||||
| 		scrn = DefaultScreen (disp); | ||||
| 		parent = RootWindow (disp, scrn); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		moo_oow_t tmpoow; | ||||
| 		XWindowAttributes wa; | ||||
| 		if (moo_inttooow(moo, a1, &tmpoow) <= 0) goto einval; | ||||
|  | ||||
| 		parent = tmpoow; | ||||
| 		XGetWindowAttributes (disp, parent, &wa); | ||||
| 		MOO_ASSERT (moo, XRootWindowOfScreen(wa.screen) == parent); | ||||
| 		scrn = XScreenNumberOfScreen(wa.screen); | ||||
| 	} | ||||
|  | ||||
| 	attrs.event_mask = ExposureMask; /* TODO: accept it as a parameter??? */ | ||||
| 	attrs.border_pixel = BlackPixel (disp, scrn); /* TODO: use a6 */ | ||||
| 	attrs.background_pixel = WhitePixel (disp, scrn);/* TODO: use a7 */ | ||||
|  | ||||
| 	wind = XCreateWindow ( | ||||
| 		disp, | ||||
| 		parent, | ||||
| 		MOO_OOP_TO_SMOOI(a2), /* x */ | ||||
| 		MOO_OOP_TO_SMOOI(a3), /* y */ | ||||
| 		MOO_OOP_TO_SMOOI(a4), /* width */ | ||||
| 		MOO_OOP_TO_SMOOI(a5), /* height */ | ||||
| 		1, /* border width */ | ||||
| 		CopyFromParent, /* depth */ | ||||
| 		InputOutput,    /* class */ | ||||
| 		CopyFromParent, /* visual */ | ||||
| 		CWEventMask | CWBackPixel | CWBorderPixel, &attrs); | ||||
| 	if (!wind) | ||||
| 	{ | ||||
| 		MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ESYSERR); | ||||
| 		goto done; | ||||
| 	} | ||||
|  | ||||
| 	a0 = moo_oowtoint (moo, wind); | ||||
| 	if (!a0)  | ||||
| 	{ | ||||
| 		MOO_STACK_SETRETTOERRNUM (moo, nargs); | ||||
| 		goto done; | ||||
| 	} | ||||
|  | ||||
| /* TODO: remvoe this */ | ||||
| XMapWindow (disp, wind); | ||||
| XFlush (disp); | ||||
|  | ||||
| #if 0 | ||||
| 	if (parent == screen->root) | ||||
| 	{ | ||||
| 		cookie = xcb_intern_atom(c, 1, 12, "WM_PROTOCOLS"); | ||||
| 		reply = xcb_intern_atom_reply(c, cookie, 0); | ||||
|  | ||||
| 		cookie = xcb_intern_atom(c, 0, 16, "WM_DELETE_WINDOW"); | ||||
| 		win->dwar = xcb_intern_atom_reply(c, cookie, 0); | ||||
|  | ||||
| 		xcb_change_property(c, XCB_PROP_MODE_REPLACE, wid, reply->atom, 4, 32, 1, &win->dwar->atom); | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	MOO_STACK_SETRET (moo, nargs, a0);  | ||||
| done: | ||||
| 	return MOO_PF_SUCCESS; | ||||
| } | ||||
|  | ||||
| static moo_pfrc_t pf_destroy_window (moo_t* moo, moo_ooi_t nargs) | ||||
| { | ||||
| 	moo_oop_t a0, a1; | ||||
|  | ||||
|  | ||||
| 	a0 = MOO_STACK_GETARG(moo, nargs, 0); /* display - SmallPointer (Display*) */ | ||||
| 	a1 = MOO_STACK_GETARG(moo, nargs, 1); /* window - Integer (Window) */ | ||||
|  | ||||
| 	if (!MOO_OOP_IS_SMPTR(a0)) | ||||
| 	 | ||||
| 	{ | ||||
| 	einval: | ||||
| 		MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		Display* disp; | ||||
| 		moo_oow_t wind; | ||||
|  | ||||
| 		disp = MOO_OOP_TO_SMPTR(a0); | ||||
| 		if (moo_inttooow(moo, a1, &wind) <= 0) goto einval; | ||||
|  | ||||
| 		XUnmapWindow (disp, (Window)wind);  | ||||
| 		XDestroyWindow (disp, (Window)wind); | ||||
| XFlush (disp); | ||||
|  | ||||
| 		MOO_STACK_SETRETTORCV (moo, nargs);  | ||||
| 	} | ||||
| 	return MOO_PF_SUCCESS; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* ------------------------------------------------------------------------ */ | ||||
|  | ||||
| static moo_pfinfo_t x11_pfinfo[] = | ||||
| { | ||||
| 	{ MC, { '_','c','l','o','s','e','_','d','i','s','p','l','a','y','\0' },     0, { pf_close_display,   1, 1 } }, | ||||
| 	{ MC, { '_','c','r','e','a','t','e','_','w','i','n','d','o','w','\0' },     0, { pf_create_window,   8, 8 } }, | ||||
| 	{ MC, { '_','d','e','s','t','r','o','y','_','w','i','n','d','o','w','\0' }, 0, { pf_destroy_window,  2, 2 } }, | ||||
| 	{ MC, { '_','g','e','t','_','e','v','e','n','t','\0'},                      0, { pf_get_event,       2, 2 } }, | ||||
| 	{ MI, { '_','g','e','t','_','e','v','t','b','u','f','\0'},                  0, { pf_get_evtbuf,      0, 0 } }, | ||||
| 	{ MC, { '_','g','e','t','_','f','d','\0' },                                 0, { pf_get_fd,          1, 1 } }, | ||||
| 	{ MC, { '_','o','p','e','n','_','d','i','s','p','l','a','y','\0' },         0, { pf_open_display,    0, 1 } } | ||||
| 	 | ||||
|  | ||||
| 	{ MI, { '_','c','o','n','n','e','c','t','\0' },                        0, { pf_connect,    0, 1 } }, | ||||
| 	{ MI, { '_','d','i','s','c','o','n','n','e','c','t','\0' },            0, { pf_disconnect, 0, 0 } }, | ||||
| #if 0 | ||||
| 	{ MI, { '_','g','e','t','_','b','a','s','e','\0' },                    0, { pf_get_base,   0, 0 } }, | ||||
| 	{ MI, { '_','g','e','t','_','e','v','e','n','t','\0'},                 0, { pf_get_event,  0, 0 } }, | ||||
| 	{ MI, { '_','g','e','t','_','f','d','\0' },                            0, { pf_get_fd,     0, 0 } } | ||||
|  | ||||
| 	 | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| static int x11_import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class) | ||||
| { | ||||
| 	if (moo_setclasstrsize(moo, _class, MOO_SIZEOF(x11_t), MOO_NULL) <= -1) return -1; | ||||
| 	if (moo_setclasstrsize(moo, _class, MOO_SIZEOF(x11_trailer_t), MOO_NULL) <= -1) return -1; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -273,4 +430,3 @@ int moo_mod_x11 (moo_t* moo, moo_mod_t* mod) | ||||
| } | ||||
|  | ||||
| /* ------------------------------------------------------------------------ */ | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user