more xcb implementation code
This commit is contained in:
		| @ -4,8 +4,12 @@ | ||||
|  | ||||
| class X11(Object) from 'x11' | ||||
| { | ||||
| 	dcl(#class) connection. | ||||
| 	dcl id. | ||||
| 	(* The X11 class represents a X11 display *) | ||||
|  | ||||
| 	dcl(#class) default_display. | ||||
|  | ||||
| 	dcl cid. | ||||
| 	dcl windows. ## all windows registered | ||||
|  | ||||
| 	dcl event_loop_sem event_loop_proc. | ||||
| 	dcl ll_event_blocks. | ||||
| @ -15,20 +19,52 @@ class X11(Object) from 'x11' | ||||
| 	dcl mouse_event. | ||||
| 	dcl mouse_wheel_event. | ||||
|  | ||||
| 	dcl frames. | ||||
|  | ||||
| 	method(#primitive) _connect. | ||||
| 	method(#primitive) _disconnect. | ||||
| 	method(#primitive) _get_fd. | ||||
| 	method(#primitive) _get_event. | ||||
| 	 | ||||
| 	method id { ^self.id } | ||||
| 	method cid { ^self.cid } | ||||
| 	method wid { ^nil } | ||||
| 	method display { ^self } | ||||
| } | ||||
|  | ||||
| class X11.Exception(System.Exception) | ||||
| { | ||||
| } | ||||
|  | ||||
| class X11.Rectangle(Object) | ||||
| { | ||||
| 	dcl x y width height. | ||||
|  | ||||
| 	method initialize | ||||
| 	{ | ||||
| 		self.x := 0. | ||||
| 		self.y := 0. | ||||
| 		self.width := 0. | ||||
| 		self.height := 0. | ||||
| 	} | ||||
| 	 | ||||
| 	method x { ^self.x } | ||||
| 	method y { ^self.y } | ||||
| 	method width { ^self.width } | ||||
| 	method height { ^self.height } | ||||
|  | ||||
| 	method x: x { self.x := x } | ||||
| 	method y: y { self.y := y } | ||||
| 	method width: width { self.width := width } | ||||
| 	method height: height { self.height := height } | ||||
|  | ||||
| 	method x: x y: y width: width height: height  | ||||
| 	{ | ||||
| 		self.x := x. | ||||
| 		self.y := y. | ||||
| 		self.width := width. | ||||
| 		self.height := height. | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| ## --------------------------------------------------------------------------- | ||||
| ## Event | ||||
| ## --------------------------------------------------------------------------- | ||||
| @ -43,6 +79,7 @@ pooldic X11.LLEvent | ||||
| 	LEAVE_NOTIFY      := 8. | ||||
| 	EXPOSE            := 12. | ||||
| 	VISIBILITY_NOTIFY := 15. | ||||
| 	CONFIGURE_NOTIFY  := 22. | ||||
| 	CLIENT_MESSAGE    := 33. | ||||
| } | ||||
|  | ||||
| @ -118,16 +155,26 @@ class X11.FrameEvent(X11.Event) | ||||
| ## --------------------------------------------------------------------------- | ||||
| ## Graphics Context | ||||
| ## --------------------------------------------------------------------------- | ||||
| pooldic X11.GCAttr | ||||
| { | ||||
| 	(* see xcb/xproto.h *) | ||||
| 	GC_FOREGROUND := 4.  | ||||
| 	GC_BACKGROUND := 8. | ||||
| 	GC_LINE_WIDTH := 16. | ||||
| 	GC_LINE_STYLE := 32. | ||||
| 	GC_FONT       := 16384. | ||||
| } | ||||
|  | ||||
| class X11.GC(Object) from 'x11.gc' | ||||
| { | ||||
| 	dcl window id. | ||||
|  | ||||
| 	method(#primitive) _make (connection, window). | ||||
| 	method(#primitive) _make (display, window). | ||||
| 	method(#primitive) _kill. | ||||
| 	method(#primitive) _drawLine(x1, y1, x2, y2). | ||||
| 	method(#primitive) _drawRect(x, y, width, height). | ||||
| 	method(#primitive) _fillRect(x, y, width, height). | ||||
| 	method(#primitive) _foreground: color. | ||||
| 	method(#primitive) _change(gcattr, value). | ||||
|  | ||||
| 	method(#class) new: window | ||||
| 	{ | ||||
| @ -136,7 +183,7 @@ class X11.GC(Object) from 'x11.gc' | ||||
|  | ||||
| 	method __open_on: window | ||||
| 	{ | ||||
| 		if ((id := self _make(window connection id, window id)) isError)  | ||||
| 		if ((id := self _make(window display cid, window wid)) isError)  | ||||
| 		{ | ||||
| 			X11.Exception signal: 'cannot make a graphic context' | ||||
| 		}. | ||||
| @ -147,20 +194,45 @@ class X11.GC(Object) from 'x11.gc' | ||||
|  | ||||
| 	method close | ||||
| 	{ | ||||
| 		if (self.window notNil) | ||||
| 		if (self.id notNil) | ||||
| 		{ | ||||
| 			self _kill. | ||||
| 			self.id := nil. | ||||
| 			self.window := nil. | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	method foreground: value | ||||
| 	{ | ||||
| 		^self _change (X11.GCAttr.GC_FOREGROUND, value) | ||||
| 	} | ||||
|  | ||||
| 	method background: value | ||||
| 	{ | ||||
| 		^self _change (X11.GCAttr.GC_BACKGROUND, value) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| ## --------------------------------------------------------------------------- | ||||
| ## --------------------------------------------------------------------------- | ||||
|  | ||||
|  | ||||
| class X11.Component(Object) | ||||
| { | ||||
| 	dcl parent. | ||||
|  | ||||
| 	method new | ||||
| 	{ | ||||
| 		## you must call new: parent instead. | ||||
| 		self cannotInstantiate | ||||
| 	} | ||||
|  | ||||
| 	method new: parent | ||||
| 	{ | ||||
| 		## you must call new: parent instead. | ||||
| 		self cannotInstantiate | ||||
| 	} | ||||
|  | ||||
| 	method parent | ||||
| 	{ | ||||
| 		^self.parent | ||||
| @ -170,6 +242,19 @@ class X11.Component(Object) | ||||
| 	{ | ||||
| 		self.parent := parent. | ||||
| 	} | ||||
|  | ||||
| 	method display  | ||||
| 	{  | ||||
| 		| p pp | | ||||
| 		p := self. | ||||
| 		while ((pp := p parent) notNil) { p := pp }. | ||||
| 		^p display. | ||||
| 	} | ||||
|  | ||||
| 	method display: display | ||||
| 	{ | ||||
| 		## do nothing | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class X11.Canvas(Component) | ||||
| @ -185,54 +270,19 @@ class X11.Canvas(Component) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class X11.Container(Component) | ||||
| class X11.WindowedComponent(Component) from 'x11.win' | ||||
| { | ||||
| 	dcl components capacity size. | ||||
| 	dcl(#class) geom. | ||||
| 	dcl wid. | ||||
| 	 | ||||
| 	method initialize | ||||
| 	{ | ||||
| 		self.size := 0. | ||||
| 		self.capacity := 128. | ||||
| ## TODO: change System.Array to Danamically resized array. | ||||
| 		self.components := System.Array new: self.capacity. | ||||
| 	} | ||||
| 	method(#primitive) _get_window_dwatom. | ||||
| 	method(#primitive) _get_window_id. | ||||
| 	method(#primitive) _make_window (display, x, y, width, height, parent). | ||||
| 	method(#primitive) _kill_window. | ||||
| 	method(#primitive) _get_window_geometry (geom). | ||||
| 	method(#primitive) _set_window_geometry (geom). | ||||
| 	 | ||||
| 	method addComponent: component | ||||
| 	{ | ||||
| 		| tmp | | ||||
| 		component parent: self. | ||||
| 		if (self.size >= self.capacity) | ||||
| 		{ | ||||
| 			tmp := System.Array new: (self.capacity + 128). | ||||
| 			tmp copy: self.components. | ||||
| 			self.capacity := self.capacity + 128. | ||||
| 			self.components := tmp. | ||||
| 		}. | ||||
| 		 | ||||
| 		self.components at: self.size put: component. | ||||
| 		self.size := self.size + 1. | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class X11.Window(Container) from 'x11.win' | ||||
| { | ||||
| 	dcl id. | ||||
|  | ||||
| 	method(#primitive) _get_dwatom. | ||||
| 	method(#primitive) _get_id. | ||||
| 	 | ||||
| 	method(#primitive) _make (connection, x, y, width, height, parent). | ||||
| 	method(#primitive) _kill. | ||||
|  | ||||
| 	method id { ^self.id } | ||||
|  | ||||
| 	method connection  | ||||
| 	{  | ||||
| 		| p pp | | ||||
| 		p := self. | ||||
| 		while ((pp := p parent) notNil) { p := pp }. | ||||
| 		^p connection. | ||||
| 	} | ||||
| 	method wid { ^self.wid } | ||||
|  | ||||
| 	method(#class) new: parent | ||||
| 	{ | ||||
| @ -241,22 +291,73 @@ class X11.Window(Container) from 'x11.win' | ||||
|  | ||||
| 	method __open_on_window: parent | ||||
| 	{ | ||||
| 		| id | | ||||
| 		id := self _make (parent connection id, 5, 5, 100, 100, parent id). | ||||
| 		if (id isError) { X11.Exception signal: ('cannot make a window - ' & id asString) }. | ||||
| 		| id disp | | ||||
| 		 | ||||
| 		self.id := id. | ||||
| 		disp := parent display. | ||||
|  | ||||
| 		wid := self _make_window (disp cid, 5, 5, 300, 300, parent wid). | ||||
| 		if (wid isError) { X11.Exception signal: ('cannot make a window - ' & wid asString) }. | ||||
| 		 | ||||
| 		self.wid := wid. | ||||
| 		self display: disp. | ||||
|  | ||||
| 		if (disp ~= parent)  | ||||
| 		{ | ||||
| 			self.parent := parent. | ||||
| 			parent addComponent: self. | ||||
| 		}. | ||||
|  | ||||
| 		parent connection addFrame: self. | ||||
| 		 | ||||
| 		disp addWindow: self. | ||||
| 		self windowOpened. | ||||
| 	} | ||||
|  | ||||
| 	method close | ||||
| 	{ | ||||
| 		if (self.wid notNil) | ||||
| 		{ | ||||
| 			self windowClosing. | ||||
|  | ||||
| 			self display removeWindow: self. | ||||
| 			if (self.parent notNil) { self.parent removeComponent: self }. | ||||
|  | ||||
| 			self _kill_window. | ||||
| 			self windowClosed. ## you can't make a primitive call any more | ||||
|  | ||||
| 			self.wid := nil. | ||||
| 			self.parent := nil. | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	method bounds | ||||
| 	{ | ||||
| 		| rect | | ||||
| 		rect := X11.Rectangle new. | ||||
| 		self _get_window_geometry (rect). | ||||
| 		^rect. | ||||
| 	} | ||||
| 	 | ||||
| 	method bounds: rect | ||||
| 	{ | ||||
| 		self _set_window_geometry (rect). | ||||
| 	} | ||||
|  | ||||
| 	method windowOpened | ||||
| 	{ | ||||
| 	} | ||||
| 	method windowClosing | ||||
| 	{ | ||||
| 	} | ||||
| 	method windowClosed | ||||
| 	{ | ||||
| 	} | ||||
| 	method windowResized | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	method expose: event | ||||
| 	{ | ||||
| 		('EXPOSE  IN WINDOWS....' & (self.id asString) & ' ' & (event x asString) & ' ' & (event y asString) & ' ' & (event width asString) & ' ' & (event height asString))  dump. | ||||
| 	 | ||||
| 	##	('EXPOSE  IN WINDOWS....' & (self.wid asString) & ' ' & (event x asString) & ' ' & (event y asString) & ' ' & (event width asString) & ' ' & (event height asString))  dump. | ||||
| 	} | ||||
|  | ||||
| 	(* TODO: take the followings out to a seperate mouse listener??? *) | ||||
| @ -271,71 +372,62 @@ class X11.Window(Container) from 'x11.win' | ||||
| 	} | ||||
| 	method mousePressed: event | ||||
| 	{ | ||||
| 		('MOUSE PRESSED' & (self.id asString) & ' ' & (event x asString) & ' ' & (event y asString))  dump. | ||||
| 		('MOUSE PRESSED' & (self.wid asString) & ' ' & (event x asString) & ' ' & (event y asString))  dump. | ||||
| 	} | ||||
| 	method mouseReleased: event | ||||
| 	{ | ||||
| 		('MOUSE RELEASED' & (self.id asString) & ' ' & (event x asString) & ' ' & (event y asString))  dump. | ||||
| 		('MOUSE RELEASED' & (self.wid asString) & ' ' & (event x asString) & ' ' & (event y asString))  dump. | ||||
| 	} | ||||
| 	method mouseWheelMoved: event | ||||
| 	{ | ||||
| 		('MOUSE WHEEL MOVED' & (self.id asString) & ' ' & (event x asString) & ' ' & (event y asString) &   ' ' & (event amount asString))  dump. | ||||
| 		('MOUSE WHEEL MOVED' & (self.wid asString) & ' ' & (event x asString) & ' ' & (event y asString) &   ' ' & (event amount asString))  dump. | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	method windowOpened | ||||
| 	{ | ||||
| 	} | ||||
| 	method windowClosing | ||||
| 	{ | ||||
| 	} | ||||
| 	method windowClosed | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| class X11.Frame(Window) | ||||
| class X11.Container(WindowedComponent) | ||||
| { | ||||
| 	dcl connection. | ||||
| 	dcl components. | ||||
|  | ||||
| 	## method connection: connection { self.connection := connection }  | ||||
| 	method connection { ^self.connection } | ||||
| 	 | ||||
| 	method(#class) new | ||||
| 	method initialize | ||||
| 	{ | ||||
| 		##^(super new) __open_on: X11 connection. | ||||
| 		^(super new) __open_on: X11 connect.  ## connect if X11 is not connected. | ||||
| 		super initialize. | ||||
| 		self.components := System.Dictionary new: 128. | ||||
| 	} | ||||
|  | ||||
| 	method __open_on: connection | ||||
| 	method addComponent: component | ||||
| 	{ | ||||
| 		| id | | ||||
| 	## TODO: the key is component's wid. it's only supported for WindowedCompoennt. | ||||
| 	##       what is a better key to support Component that's not linked to any window? | ||||
| 		^self.components at: (component wid) put: component | ||||
| 	} | ||||
|  | ||||
| 		id := self _make(connection id, 10, 20, 500, 600, nil). | ||||
| 		if (id isError) { X11.Exception signal: ('cannot make a frame - ' & id asString) }.		 | ||||
|  | ||||
| 		self.id := id. | ||||
| 		self.connection := connection. | ||||
|  | ||||
| 		connection addFrame: self. | ||||
| 		 | ||||
| 		self windowOpened. | ||||
| 	method removeComponent: component | ||||
| 	{ | ||||
| 		^self.components removeKey: (component wid) | ||||
| 	} | ||||
| 	 | ||||
| 	method close | ||||
| 	{ | ||||
| 		if (self.connection notNil) | ||||
| 		{ | ||||
| 			self windowClosing. | ||||
| 			self _kill. | ||||
| 			(* TODO: remove all subcomponents... *) | ||||
| 			self.connection removeFrame: self. | ||||
| 			self windowClosed. | ||||
| 			 | ||||
| 			self.id := 0. | ||||
| 			self.connection := nil. | ||||
| 		self.components do: [:c | c close ]. | ||||
| 		^super close | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class X11.FrameWindow(Container) | ||||
| { | ||||
| 	dcl display. | ||||
|  | ||||
| 	method display { ^self.display } | ||||
| 	method display: display { self.display := display } | ||||
| 	 | ||||
| 	method(#class) new | ||||
| 	{ | ||||
| 		super new: X11 defaultDisplay. ## connect if X11 is not connected. | ||||
| 	} | ||||
| 	 | ||||
| 	method(#class) new: display | ||||
| 	{ | ||||
| 		^super new: display. | ||||
| 	} | ||||
|  | ||||
| 	##method show: flag | ||||
| @ -357,49 +449,68 @@ class X11.Frame(Window) | ||||
| 	}*) | ||||
| } | ||||
|  | ||||
| class X11.Button(Component) | ||||
| class X11.Button(WindowedComponent) | ||||
| { | ||||
| } | ||||
|  | ||||
|  | ||||
| extend X11 | ||||
| { | ||||
| 	method(#class) connect | ||||
| 	method(#class) new | ||||
| 	{ | ||||
| 		| c |  | ||||
| 		if (self.connection isNil)  | ||||
| 		{ | ||||
| 			c := self new. | ||||
| 			if (c connect isError) { X11.Exception signal: 'cannot connect' }. | ||||
| 			self.connection := c. | ||||
| 		}. | ||||
| 		^self.connection | ||||
| 		^(super new) __connect_to_display: nil. | ||||
| 	} | ||||
|  | ||||
| 	method(#class) disconnect | ||||
| 	method __connect_to_display: name | ||||
| 	{ | ||||
| 		if (self.connection notNil)  | ||||
| 		{ | ||||
| 			self.connection disconnect. | ||||
| 			self.connection := nil. | ||||
| 		}. | ||||
| 		^self.connection | ||||
| 	## TODO: make use of name to connect to a non-default display. | ||||
| 		| cid | | ||||
| 		cid := self _connect. | ||||
| 		if (cid isError) { X11.Exception signal: 'cannot connect to display' }. | ||||
| 		self.cid := cid. | ||||
| 	} | ||||
|  | ||||
| 	method(#class) connection | ||||
| 	method close | ||||
| 	{ | ||||
| 		^self.connection | ||||
| 		if (self.cid notNil) | ||||
| 		{ | ||||
| 			self _disconnect. | ||||
| 			self.cid := nil. | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	method(#class) defaultDisplay | ||||
| 	{ | ||||
| 		| conn | | ||||
| 		if (self.default_display isNil) | ||||
| 		{ | ||||
| 			conn := X11 new. | ||||
| 			##if (conn isError) { X11.Exception signal: 'cannot connect to default display' }. | ||||
| 			self.default_display := conn. | ||||
| 		}. | ||||
| 		 | ||||
| 		^self.default_display | ||||
| 	} | ||||
|  | ||||
| 	method(#class) closeDefaultDisplay | ||||
| 	{ | ||||
| 		if (self.default_display notNil) | ||||
| 		{ | ||||
| 			self.default_display close. | ||||
| 			self.default_display := nil. | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	method(#class) enterEventLoop | ||||
| 	{ | ||||
| 		^self connect enterEventLoop | ||||
| 		^self defaultDisplay enterEventLoop | ||||
| 	} | ||||
|  | ||||
| 	method initialize | ||||
| 	{ | ||||
| 		super initialize. | ||||
|  | ||||
| 		self.windows := System.Dictionary new: 100. | ||||
| 		 | ||||
| 		self.expose_event := X11.ExposeEvent new. | ||||
| 		self.key_event := X11.KeyEvent new. | ||||
| 		self.mouse_event := X11.MouseEvent new. | ||||
| @ -415,56 +526,41 @@ extend X11 | ||||
| 			at: X11.LLEvent.ENTER_NOTIFY      put: #__handle_notify:; | ||||
| 			at: X11.LLEvent.LEAVE_NOTIFY      put: #__handle_notify:; | ||||
| 			at: X11.LLEvent.EXPOSE            put: #__handle_expose:; | ||||
| 			at: X11.LLEvent.CONFIGURE_NOTIFY  put: #__handle_configure_notify; | ||||
| 			at: X11.LLEvent.CLIENT_MESSAGE    put: #__handle_client_message:. | ||||
| 	} | ||||
|  | ||||
| 	method connect | ||||
| 	{ | ||||
| 		| t | | ||||
| 		if (self.frames isNil) | ||||
| 		| cid | | ||||
| 		if (self.windows isNil) | ||||
| 		{ | ||||
| 			if ((t := self _connect) isError)  { ^t }. | ||||
| 			self.id := t. | ||||
| 			self.frames := System.Dictionary new. | ||||
| 			if ((cid := self _connect) isError)  { ^cid }. | ||||
| 			self.cid := cid. | ||||
| 			self.windows := System.Dictionary new. | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	method disconnect | ||||
| 	{ | ||||
| 		if (self.frames notNil) | ||||
| 		if (self.windows notNil) | ||||
| 		{ | ||||
| 			self.frames do: [ :frame | | ||||
| 			self.windows do: [ :frame | | ||||
| 				frame close. | ||||
| 			]. | ||||
| 			self.frames := nil. | ||||
| 			self.windows := nil. | ||||
| 			self _disconnect. | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	method addFrame: frame | ||||
| 	method addWindow: window | ||||
| 	{ | ||||
| 		if (frame connection ~= self) | ||||
| 		{ | ||||
| 			X11.Exception signal: 'Invalid connection in frame to add'. | ||||
| 		}. | ||||
|  | ||||
| ('ADDING NE FRAME ID' & frame id asString) dump. | ||||
| 		self.frames at: (frame id) put: frame. | ||||
| 		^self.windows at: (window wid) put: window. | ||||
| 	} | ||||
|  | ||||
| 	method removeFrame: frame | ||||
| 	method removeWindow: window | ||||
| 	{ | ||||
| 		if (frame connection ~= self) | ||||
| 		{ | ||||
| 			X11.Exception signal: 'Invalid connection in frame to remove'. | ||||
| 		}. | ||||
|  | ||||
| 		(*self.frames removeLink: frame backlink. | ||||
| 		frame connection: nil. | ||||
| 		frame backlink: nil.*) | ||||
|  | ||||
| ('REMOVING NE FRAME ID' & frame id asString) dump. | ||||
| 		(self.frames removeKey: (frame id)) dump. | ||||
| 		^self.windows removeKey: (window wid) | ||||
| 	} | ||||
|  | ||||
| 	method enterEventLoop | ||||
| @ -477,7 +573,7 @@ extend X11 | ||||
| 				| event ongoing |  | ||||
| 				 | ||||
| 				ongoing := true. | ||||
| 				while (self.frames size > 0)  | ||||
| 				while (self.windows size > 0)  | ||||
| 				{ | ||||
| 'Waiting for X11 event...' dump. | ||||
| 					self.event_loop_sem wait. | ||||
| @ -568,13 +664,13 @@ extend X11 | ||||
| 			} xcb_expose_event_t; | ||||
| 		*) | ||||
|  | ||||
| 		| wid frame | | ||||
| 		| wid window | | ||||
|  | ||||
| 		##wid := System _getUint32(event, 4). ## window | ||||
| 		wid := event getUint32(4). | ||||
| 		frame := self.frames at: wid. | ||||
| 		window := self.windows at: wid. | ||||
|  | ||||
| 		if (frame notError) | ||||
| 		if (window notError) | ||||
| 		{ | ||||
| 			(* | ||||
| 			self.expose_event  | ||||
| @ -589,7 +685,7 @@ extend X11 | ||||
| 				width: event getUint16(12)   ## width | ||||
| 				height: event getUint16(14). ## height | ||||
|  | ||||
| 			frame expose: self.expose_event. | ||||
| 			window expose: self.expose_event. | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| @ -619,15 +715,15 @@ extend X11 | ||||
| 			typedef xcb_button_press_event_t xcb_button_release_event_t; | ||||
| 		*) | ||||
|  | ||||
| 		| type wid frame detail | | ||||
| 		| type wid window detail | | ||||
| 		type := System _getUint8(event, 0) bitAnd: 16r7F. ## lower 7 bits of response_type | ||||
| 		wid := System _getUint32(event, 12). ## event | ||||
| 		##type := event getUint8(0) bitAnd: 16r7F. ## lower 7 bits of response_type | ||||
| 		##wid := event getUint32(12). ## event | ||||
| 		 | ||||
| 		frame := self.frames at: wid. | ||||
| 		window := self.windows at: wid. | ||||
|  | ||||
| 		if (frame notError) | ||||
| 		if (window notError) | ||||
| 		{ | ||||
| 			##detail := System _getUint8(event, 1). | ||||
| 			detail := event getUint8(1). | ||||
| @ -646,11 +742,11 @@ extend X11 | ||||
| 				 | ||||
| 				if (type == X11.LLEvent.BUTTON_PRESS) | ||||
| 				{ | ||||
| 					frame mousePressed: self.mouse_event | ||||
| 					window mousePressed: self.mouse_event | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					frame mouseReleased: self.mouse_event | ||||
| 					window mouseReleased: self.mouse_event | ||||
| 				} | ||||
| 			} | ||||
| 			elsif (detail == 4 or: [detail == 5]) | ||||
| @ -667,7 +763,7 @@ extend X11 | ||||
| 						x: event getUint16(24)   ## event_x | ||||
| 						y: event getUint16(26)   ## event_y | ||||
| 						amount: (if (detail == 4) { -1 } else { 1 }). | ||||
| 					frame mouseWheelMoved: self.mouse_wheel_event | ||||
| 					window mouseWheelMoved: self.mouse_wheel_event | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| @ -677,6 +773,29 @@ extend X11 | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	method __handle_configure_notify: event | ||||
| 	{ | ||||
| 		(* | ||||
| 		typedef struct xcb_configure_notify_event_t { | ||||
| 			uint8_t      response_type; | ||||
| 			uint8_t      pad0; | ||||
| 			uint16_t     sequence; | ||||
| 			xcb_window_t event; | ||||
| 			xcb_window_t window; | ||||
| 			xcb_window_t above_sibling; | ||||
| 			int16_t      x; | ||||
| 			int16_t      y; | ||||
| 			uint16_t     width; | ||||
| 			uint16_t     height; | ||||
| 			uint16_t     border_width; | ||||
| 			uint8_t      override_redirect; | ||||
| 			uint8_t      pad1; | ||||
| 		} xcb_configure_notify_event_t; | ||||
| 		*) | ||||
|  | ||||
| 		 | ||||
| 	} | ||||
|  | ||||
| 	method __handle_client_message: event | ||||
| 	{ | ||||
| 		(* | ||||
| @ -695,20 +814,20 @@ extend X11 | ||||
| 				xcb_client_message_data_t data; | ||||
| 			} xcb_client_message_event_t; | ||||
| 		*) | ||||
| 		| type wid frame dw | | ||||
| 		| type wid window dw | | ||||
| 		 | ||||
| 		##wid := System _getUint32(event, 4). ## window | ||||
| 		wid := event getUint32(4). ## window | ||||
| 		frame := self.frames at: wid. | ||||
| 		window := self.windows at: wid. | ||||
| 		 | ||||
| 		if (frame notError) | ||||
| 		if (window notError) | ||||
| 		{ | ||||
| 			##dw := System _getUint32(event, 12). ## data.data32[0] | ||||
| 			dw := event getUint32(12). ## data.data32[0] | ||||
| 			if (dw == frame _get_dwatom) | ||||
| 			if (dw == window _get_window_dwatom) | ||||
| 			{ | ||||
| 				## TODO: call close query callback??? | ||||
| 				frame close. | ||||
| 				window close. | ||||
| 			} | ||||
| 			 | ||||
| 			## TODO: handle other client messages | ||||
| @ -751,24 +870,22 @@ extend X11 | ||||
| } | ||||
|  | ||||
|  | ||||
| class MyButton(X11.Window) | ||||
| class MyButton(X11.Button) | ||||
| { | ||||
| 	method expose: event | ||||
| 	{ | ||||
| 	|gc| | ||||
| 	 | ||||
|  | ||||
| |gc| | ||||
| 		super expose: event. | ||||
|  | ||||
|  | ||||
| 	'XXXXXXXXXXXXXXXXXXXXXXXXXXx' dump. | ||||
| gc := X11.GC new: self.	 | ||||
| gc _foreground: 2.	 | ||||
| gc foreground: 16rFF8877.	 | ||||
| gc _fillRect(0, 0, 50, 50). | ||||
| gc close. | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class MyFrame(X11.Frame) | ||||
| class MyFrame(X11.FrameWindow) | ||||
| { | ||||
| 	dcl gc. | ||||
| 	dcl b1. | ||||
| @ -776,18 +893,20 @@ class MyFrame(X11.Frame) | ||||
|  | ||||
| 	method windowOpened | ||||
| 	{ | ||||
| 		 | ||||
| 		super windowOpened. | ||||
| 		 | ||||
| 		if (self.gc isNil) | ||||
| 		{ | ||||
| 			self.gc := X11.GC new: self. | ||||
| self.gc _foreground: 10. | ||||
| self.gc foreground: 10. | ||||
| self.gc _drawLine(10, 20, 30, 40). | ||||
| self.gc _drawRect(10, 20, 30, 40). | ||||
| self.gc _foreground: 20. | ||||
| self.gc foreground: 20. | ||||
| self.gc _drawRect(100, 100, 200, 200). | ||||
| 		}. | ||||
| 		 | ||||
| 		b1 := MyButton new: self. | ||||
| 		self.b1 := MyButton new: self. | ||||
| 	} | ||||
|  | ||||
| 	method windowClosing | ||||
| @ -802,17 +921,24 @@ self.gc _drawRect(100, 100, 200, 200). | ||||
|  | ||||
| 	method expose: event | ||||
| 	{ | ||||
|  | ||||
| 		| rect |  | ||||
|  | ||||
| 		super expose: event. | ||||
| 		 | ||||
| 		(* | ||||
| 		('EXPOSE....' & (self.id asString) & ' ' & (event x asString) & ' ' & (event y asString) & ' ' & (event width asString) & ' ' & (event height asString))  dump. | ||||
| 		 | ||||
| self.gc _foreground: 2.	 | ||||
| self.gc foreground: 2.	 | ||||
| ##self.gc drawLine: (10@20) to: (30@40). | ||||
| self.gc _drawLine(10, 20, 300, 400). | ||||
| self.gc _drawRect(10, 20, 30, 40). | ||||
| self.gc _foreground: 20. | ||||
| self.gc foreground: 20. | ||||
| self.gc _drawRect(100, 100, 200, 200).*) | ||||
|  | ||||
| 		rect := self bounds. | ||||
| 		rect x: 0; y: 0; height: ((rect height) quo: 2); width: ((rect width) - 2). | ||||
| 		self.b1 bounds: rect; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -827,7 +953,7 @@ class MyObject(Object) | ||||
| 	 | ||||
| 	method(#class) main  | ||||
| 	{ | ||||
| 		| f q | | ||||
| 		| f q x11 | | ||||
|  | ||||
| 		f := 20. | ||||
| 		(q:=:{ 10 -> 20, 20 -> 30, f + 40 -> self abc, (Association key: 10 value: 49), f -> f })dump. | ||||
| @ -845,12 +971,11 @@ class MyObject(Object) | ||||
| 		f addLastLink: q. | ||||
| 		(f findLink: 30) prev value dump. | ||||
|  | ||||
|  | ||||
| 		f do: [:v | v dump ]. | ||||
| 		(f size asString & ' elements in list') dump. | ||||
|  | ||||
| 		##X11 connect. | ||||
| 	##	f := MyFrame new. | ||||
| 	##	f := MyFrame new: d. | ||||
| 		q := MyFrame new. | ||||
|  | ||||
| 	##	MyButton new: q. | ||||
| @ -873,5 +998,7 @@ class MyObject(Object) | ||||
| 		## [ while (true) { '111' dump. Processor sleepFor: 1. } ] fork. | ||||
|  | ||||
| 		##X11 disconnect. | ||||
| 		 | ||||
| 		##X11 closeDefaultDisplay. | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -407,7 +407,7 @@ struct moo_ntime_t | ||||
| #define MOO_UCI_EOF ((moo_ooci_t)-1) | ||||
|  | ||||
| #define MOO_SIZEOF(x) (sizeof(x)) | ||||
| #define MOO_COUNTOF(x) (sizeof(x) / sizeof(x[0])) | ||||
| #define MOO_COUNTOF(x) (sizeof(x) / sizeof((x)[0])) | ||||
|  | ||||
| /** | ||||
|  * The MOO_OFFSETOF() macro returns the offset of a field from the beginning | ||||
|  | ||||
| @ -46,7 +46,7 @@ | ||||
|  | ||||
| #if !defined(NDEBUG) | ||||
| /* this is for gc debugging */ | ||||
| #define MOO_DEBUG_GC | ||||
| /*#define MOO_DEBUG_GC*/ | ||||
| #define MOO_DEBUG_COMPILER | ||||
| /*#define MOO_DEBUG_VM_PROCESSOR*/ | ||||
| /*#define MOO_DEBUG_VM_EXEC*/ | ||||
|  | ||||
| @ -651,7 +651,7 @@ moo_pfbase_t* moo_querymod (moo_t* moo, const moo_ooch_t* pfid, moo_oow_t pfidle | ||||
| 	if ((pfbase = mdp->mod.query (moo, &mdp->mod, sep + 1, pfidlen - mod_name_len - 1)) == MOO_NULL)  | ||||
| 	{ | ||||
| 		/* the primitive function is not found. but keep the module open even if it's opened above */ | ||||
| 		MOO_DEBUG2 (moo, "Cannot find a primitive function [%js] in a module [%js]\n", sep + 1, mdp->mod.name); | ||||
| 		MOO_DEBUG3 (moo, "Cannot find a primitive function [%.*js] in a module [%js]\n", pfidlen - mod_name_len - 1, sep + 1, mdp->mod.name); | ||||
| 		moo->errnum = MOO_ENOENT; /* TODO: proper error code and handling */ | ||||
| 		return MOO_NULL; | ||||
| 	} | ||||
|  | ||||
							
								
								
									
										118
									
								
								moo/mod/x11.c
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								moo/mod/x11.c
									
									
									
									
									
								
							| @ -318,22 +318,30 @@ static moo_pfrc_t pf_gc_fill_rect (moo_t* moo, moo_ooi_t nargs) | ||||
| 	return MOO_PF_SUCCESS; | ||||
| } | ||||
|  | ||||
| static moo_pfrc_t pf_gc_set_foreground (moo_t* moo, moo_ooi_t nargs) | ||||
| static moo_pfrc_t pf_gc_change (moo_t* moo, moo_ooi_t nargs) | ||||
| { | ||||
| 	x11_gc_t* gc; | ||||
| 	moo_oop_t t; | ||||
| 	moo_oow_t tmpoow; | ||||
| 	uint32_t value; | ||||
|  | ||||
| 	gc = (x11_gc_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL); | ||||
|  | ||||
| 	if (moo_inttooow (moo, MOO_STACK_GETARG(moo, nargs, 0), &tmpoow) <= 0) | ||||
| 	t = MOO_STACK_GETARG(moo, nargs, 0); | ||||
| 	if (!MOO_OOP_IS_SMOOI(t)) | ||||
| 	{ | ||||
| 	einval: | ||||
| 		MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); | ||||
| 		return MOO_PF_SUCCESS; | ||||
| 	} | ||||
|  | ||||
| 	if (moo_inttooow (moo, MOO_STACK_GETARG(moo, nargs, 1), &tmpoow) <= 0) goto einval; | ||||
| 	value = tmpoow; | ||||
|  | ||||
| 	xcb_change_gc (gc->c, gc->id, XCB_GC_FOREGROUND, &value); | ||||
| 	/* XCB_GC_FUNCTION, XCB_GC_PLANE_MASK, XCB_GC_FOREGROUND,  XCB_GC_BACKGROUND, etc  | ||||
| 	 * this primitive allows only 1 value to be used. you must not specify | ||||
| 	 * a bitwise-ORed mask of more than 1 XCB_GC_XXX enumerator. */ | ||||
| 	xcb_change_gc (gc->c, gc->id, MOO_OOP_TO_SMOOI(t), &value); | ||||
| 	xcb_flush (gc->c); | ||||
|  | ||||
| 	MOO_STACK_SETRETTORCV (moo, nargs); | ||||
| @ -423,12 +431,91 @@ static moo_pfrc_t pf_win_get_dwatom (moo_t* moo, moo_ooi_t nargs) | ||||
| 	win = (x11_win_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL); | ||||
|  | ||||
| 	x = moo_oowtoint (moo, win->dwar->atom); | ||||
| 	if (!x) return MOO_PF_HARD_FAILURE; | ||||
| 	if (!x)  | ||||
| 	{ | ||||
| 		MOO_STACK_SETRETTOERRNUM (moo, nargs); | ||||
| 		return MOO_PF_SUCCESS; | ||||
| 	} | ||||
|  | ||||
| 	MOO_STACK_SETRET (moo, nargs, x); | ||||
| 	return MOO_PF_SUCCESS; | ||||
| } | ||||
|  | ||||
| static moo_pfrc_t pf_win_get_geometry (moo_t* moo, moo_ooi_t nargs) | ||||
| { | ||||
| 	x11_win_t* win; | ||||
| 	moo_oop_t t; | ||||
| 	xcb_get_geometry_cookie_t gc; | ||||
| 	xcb_get_geometry_reply_t* geom; | ||||
|  | ||||
| 	win = (x11_win_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL); | ||||
| 	t = MOO_STACK_GETARG(moo, nargs, 0); | ||||
|  | ||||
| 	/* expecting an object composed of 4 object pointers */ | ||||
| 	if (!MOO_OOP_IS_POINTER(t) || MOO_OBJ_GET_FLAGS_TYPE(t) != MOO_OBJ_TYPE_OOP || MOO_OBJ_GET_SIZE(t) != 4) | ||||
| 	{ | ||||
| 		MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); | ||||
| 		return MOO_PF_SUCCESS; | ||||
| 	} | ||||
|  | ||||
| 	gc = xcb_get_geometry (win->c, win->id); | ||||
| 	geom = xcb_get_geometry_reply (win->c, gc, NULL); | ||||
|  | ||||
| 	((moo_oop_oop_t)t)->slot[0] = MOO_SMOOI_TO_OOP(geom->x); | ||||
| 	((moo_oop_oop_t)t)->slot[1] = MOO_SMOOI_TO_OOP(geom->y); | ||||
| 	((moo_oop_oop_t)t)->slot[2] = MOO_SMOOI_TO_OOP(geom->width); | ||||
| 	((moo_oop_oop_t)t)->slot[3] = MOO_SMOOI_TO_OOP(geom->height); | ||||
|  | ||||
| 	free (geom); | ||||
|  | ||||
| 	MOO_STACK_SETRET (moo, nargs, t); | ||||
| 	return MOO_PF_SUCCESS; | ||||
| } | ||||
|  | ||||
| static moo_pfrc_t pf_win_set_geometry (moo_t* moo, moo_ooi_t nargs) | ||||
| { | ||||
| 	x11_win_t* win; | ||||
| 	moo_oop_t t; | ||||
| 	uint32_t values[4]; | ||||
| 	int flags = 0, vcount = 0; | ||||
|  | ||||
| 	win = (x11_win_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL); | ||||
| 	t = MOO_STACK_GETARG(moo, nargs, 0); | ||||
|  | ||||
| 	/* expecting an object composed of 4 object pointers */ | ||||
| 	if (!MOO_OOP_IS_POINTER(t) || MOO_OBJ_GET_FLAGS_TYPE(t) != MOO_OBJ_TYPE_OOP || MOO_OBJ_GET_SIZE(t) != 4) | ||||
| 	{ | ||||
| 		MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); | ||||
| 		return MOO_PF_SUCCESS; | ||||
| 	} | ||||
|  | ||||
| 	if (MOO_OOP_IS_SMOOI(((moo_oop_oop_t)t)->slot[0])) | ||||
| 	{ | ||||
| 		flags |= XCB_CONFIG_WINDOW_X; | ||||
| 		values[vcount++] = MOO_OOP_TO_SMOOI(((moo_oop_oop_t)t)->slot[0]); | ||||
| 	} | ||||
| 	if (MOO_OOP_IS_SMOOI(((moo_oop_oop_t)t)->slot[1])) | ||||
| 	{ | ||||
| 		flags |= XCB_CONFIG_WINDOW_Y; | ||||
| 		values[vcount++] = MOO_OOP_TO_SMOOI(((moo_oop_oop_t)t)->slot[1]); | ||||
| 	} | ||||
| 	if (MOO_OOP_IS_SMOOI(((moo_oop_oop_t)t)->slot[2])) | ||||
| 	{ | ||||
| 		flags |= XCB_CONFIG_WINDOW_WIDTH; | ||||
| 		values[vcount++] = MOO_OOP_TO_SMOOI(((moo_oop_oop_t)t)->slot[2]); | ||||
| 	} | ||||
| 	if (MOO_OOP_IS_SMOOI(((moo_oop_oop_t)t)->slot[3])) | ||||
| 	{ | ||||
| 		flags |= XCB_CONFIG_WINDOW_HEIGHT; | ||||
| 		values[vcount++] = MOO_OOP_TO_SMOOI(((moo_oop_oop_t)t)->slot[3]); | ||||
| 	} | ||||
|  | ||||
| 	xcb_configure_window (win->c, win->id, flags, values); | ||||
|  | ||||
| 	MOO_STACK_SETRETTORCV (moo, nargs); | ||||
| 	return MOO_PF_SUCCESS; | ||||
| } | ||||
|  | ||||
| static moo_pfrc_t pf_win_get_id (moo_t* moo, moo_ooi_t nargs) | ||||
| { | ||||
| 	x11_win_t* win; | ||||
| @ -437,7 +524,11 @@ static moo_pfrc_t pf_win_get_id (moo_t* moo, moo_ooi_t nargs) | ||||
| 	win = (x11_win_t*)moo_getobjtrailer(moo, MOO_STACK_GETRCV(moo, nargs), MOO_NULL); | ||||
|  | ||||
| 	x = moo_oowtoint (moo, win->id); | ||||
| 	if (!x) return MOO_PF_HARD_FAILURE; | ||||
| 	if (!x)  | ||||
| 	{ | ||||
| 		MOO_STACK_SETRETTOERRNUM (moo, nargs); | ||||
| 		return MOO_PF_SUCCESS; | ||||
| 	} | ||||
|  | ||||
| 	MOO_STACK_SETRET (moo, nargs, x); | ||||
| 	return MOO_PF_SUCCESS; | ||||
| @ -643,10 +734,10 @@ int moo_mod_x11 (moo_t* moo, moo_mod_t* mod) | ||||
|  | ||||
| static moo_pfinfo_t x11_gc_pfinfo[] = | ||||
| { | ||||
| 	{ I, { '_','d','r','a','w','L','i','n','e' },                              0, { pf_gc_draw_line,      4, 4 } }, | ||||
| 	{ I, { '_','d','r','a','w','R','e','c','t' },                              0, { pf_gc_draw_rect,      4, 4 } }, | ||||
| 	{ I, { '_','c','h','a','n','g','e','\0' },                                 0, { pf_gc_change,         2, 2,} }, | ||||
| 	{ I, { '_','d','r','a','w','L','i','n','e','\0' },                         0, { pf_gc_draw_line,      4, 4 } }, | ||||
| 	{ I, { '_','d','r','a','w','R','e','c','t','\0' },                         0, { pf_gc_draw_rect,      4, 4 } }, | ||||
| 	{ I, { '_','f','i','l','l','R','e','c','t' },                              0, { pf_gc_fill_rect,      4, 4 } }, | ||||
| 	{ I, { '_','f','o','r','e','g','r','o','u','n','d',':','\0' },             0, { pf_gc_set_foreground, 1, 1 } }, | ||||
| 	{ I, { '_','g','e','t','_','i','d','\0' },                                 0, { pf_gc_get_id,         0, 0 } }, | ||||
| 	{ I, { '_','k','i','l','l','\0' },                                         0, { pf_gc_kill,           0, 0 } }, | ||||
| 	{ I, { '_','m','a','k','e','\0' },                                         0, { pf_gc_make,           2, 2 } } | ||||
| @ -685,11 +776,12 @@ int moo_mod_x11_gc (moo_t* moo, moo_mod_t* mod) | ||||
|  | ||||
| static moo_pfinfo_t x11_win_pfinfo[] = | ||||
| { | ||||
| 	{ I, { '_','g','e','t','_','d','w','a','t','o','m','\0'}, 0, { pf_win_get_dwatom,   0, 0 } }, | ||||
| 	{ I, { '_','g','e','t','_','i','d','\0' },                0, { pf_win_get_id,       0, 0 } }, | ||||
|  | ||||
| 	{ I, { '_','k','i','l','l','\0' },                        0, { pf_win_kill,         0, 0 } }, | ||||
| 	{ I, { '_','m','a','k','e','\0' },                        0, { pf_win_make,         6, 6 } } | ||||
| 	{ I, { '_','g','e','t','_','w','i','n','d','o','w','_','d','w','a','t','o','m','\0'},         0, { pf_win_get_dwatom,   0, 0 } }, | ||||
| 	{ I, { '_','g','e','t','_','w','i','n','d','o','w','_','g','e','o','m','e','t','r','y','\0'}, 0, { pf_win_get_geometry, 1, 1 } }, | ||||
| 	{ I, { '_','g','e','t','_','w','i','n','d','o','w','_','i','d','\0' },                        0, { pf_win_get_id,       0, 0 } }, | ||||
| 	{ I, { '_','k','i','l','l','_','w','i','n','d','o','w','\0' },                                0, { pf_win_kill,         0, 0 } }, | ||||
| 	{ I, { '_','m','a','k','e','_','w','i','n','d','o','w','\0' },                                0, { pf_win_make,         6, 6 } }, | ||||
| 	{ I, { '_','s','e','t','_','w','i','n','d','o','w','_','g','e','o','m','e','t','r','y','\0'}, 0, { pf_win_set_geometry, 1, 1 } } | ||||
| }; | ||||
|  | ||||
| static int x11_win_import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user