added X11.moo
This commit is contained in:
		
							
								
								
									
										877
									
								
								moo/kernel/X11.moo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										877
									
								
								moo/kernel/X11.moo
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,877 @@ | ||||
| #include 'Moo.moo'. | ||||
|  | ||||
| ###var xxxx. ## global variables. | ||||
|  | ||||
| class X11(Object) from 'x11' | ||||
| { | ||||
| 	dcl(#class) connection. | ||||
| 	dcl id. | ||||
|  | ||||
| 	dcl event_loop_sem event_loop_proc. | ||||
| 	dcl ll_event_blocks. | ||||
|  | ||||
| 	dcl expose_event. | ||||
| 	dcl key_event. | ||||
| 	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 } | ||||
| } | ||||
|  | ||||
| class X11.Exception(System.Exception) | ||||
| { | ||||
| } | ||||
|  | ||||
| ## --------------------------------------------------------------------------- | ||||
| ## Event | ||||
| ## --------------------------------------------------------------------------- | ||||
| pooldic X11.LLEvent | ||||
| { | ||||
| 	KEY_PRESS         := 2. | ||||
| 	KEY_RELEASE       := 3. | ||||
| 	BUTTON_PRESS      := 4. | ||||
| 	BUTTON_RELEASE    := 5. | ||||
| 	MOTION_NOTIFY     := 6. | ||||
| 	ENTER_NOTIFY      := 7. | ||||
| 	LEAVE_NOTIFY      := 8. | ||||
| 	EXPOSE            := 12. | ||||
| 	VISIBILITY_NOTIFY := 15. | ||||
| 	CLIENT_MESSAGE    := 33. | ||||
| } | ||||
|  | ||||
| class X11.Event(Object) | ||||
| { | ||||
| } | ||||
|  | ||||
| class X11.InputEvent(X11.Event) | ||||
| { | ||||
| } | ||||
|  | ||||
| class X11.KeyEvent(X11.InputEvent) | ||||
| { | ||||
| } | ||||
|  | ||||
| class X11.MouseEvent(X11.InputEvent) | ||||
| { | ||||
| 	dcl x y. | ||||
|  | ||||
| 	method x { ^self.x } | ||||
| 	method y { ^self.y } | ||||
|  | ||||
| 	method x: x y: y | ||||
| 	{ | ||||
| 		self.x := x. | ||||
| 		self.y := y. | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class X11.MouseWheelEvent(X11.InputEvent) | ||||
| { | ||||
| 	dcl x y amount. | ||||
| 	 | ||||
| 	method x { ^self.x } | ||||
| 	method y { ^self.y } | ||||
| 	method amount { ^self.amount } | ||||
|  | ||||
| 	method x: x y: y amount: amount | ||||
| 	{ | ||||
| 		self.x := x. | ||||
| 		self.y := y. | ||||
| 		self.amount := amount. | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class X11.ExposeEvent(X11.Event) | ||||
| { | ||||
| 	dcl x y width height. | ||||
|  | ||||
| 	method x { ^self.x } | ||||
| 	method y { ^self.y } | ||||
| 	method width { ^self.width } | ||||
| 	method height { ^self.height } | ||||
| 	 | ||||
| 	method x: x y: y width: width height: height | ||||
| 	{ | ||||
| 		self.x := x. | ||||
| 		self.y := y. | ||||
| 		self.width := width. | ||||
| 		self.height := height. | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class X11.WindowEvent(X11.Event) | ||||
| { | ||||
| } | ||||
|  | ||||
| class X11.FrameEvent(X11.Event) | ||||
| { | ||||
| } | ||||
|  | ||||
|  | ||||
| ## --------------------------------------------------------------------------- | ||||
| ## Graphics Context | ||||
| ## --------------------------------------------------------------------------- | ||||
| class X11.GC(Object) from 'x11.gc' | ||||
| { | ||||
| 	dcl window id. | ||||
|  | ||||
| 	method(#primitive) _make (connection, 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(#class) new: window | ||||
| 	{ | ||||
| 		^(super new) __open_on: window | ||||
| 	} | ||||
|  | ||||
| 	method __open_on: window | ||||
| 	{ | ||||
| 		if ((id := self _make(window connection id, window id)) isError)  | ||||
| 		{ | ||||
| 			X11.Exception signal: 'cannot make a graphic context' | ||||
| 		}. | ||||
|  | ||||
| 		self.window := window. | ||||
| 		self.id := id. | ||||
| 	} | ||||
|  | ||||
| 	method close | ||||
| 	{ | ||||
| 		if (self.window notNil) | ||||
| 		{ | ||||
| 			self _kill. | ||||
| 			self.window := nil. | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| ## --------------------------------------------------------------------------- | ||||
| ## --------------------------------------------------------------------------- | ||||
| class X11.Component(Object) | ||||
| { | ||||
| 	dcl parent. | ||||
|  | ||||
| 	method parent | ||||
| 	{ | ||||
| 		^self.parent | ||||
| 	} | ||||
|  | ||||
| 	method parent: parent | ||||
| 	{ | ||||
| 		self.parent := parent. | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class X11.Canvas(Component) | ||||
| { | ||||
| 	method paint: gr | ||||
| 	{ | ||||
| 		self subclassResponsibility: #paint | ||||
| 	} | ||||
|  | ||||
| 	method update: gr | ||||
| 	{ | ||||
| 		self subclassResponsibility: #paint | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class X11.Container(Component) | ||||
| { | ||||
| 	dcl components capacity size. | ||||
|  | ||||
| 	method initialize | ||||
| 	{ | ||||
| 		self.size := 0. | ||||
| 		self.capacity := 128. | ||||
| ## TODO: change System.Array to Danamically resized array. | ||||
| 		self.components := System.Array new: self.capacity. | ||||
| 	} | ||||
|  | ||||
| 	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(#class) new: parent | ||||
| 	{ | ||||
| 		^(super new) __open_on_window: parent | ||||
| 	} | ||||
| 	 | ||||
| 	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) }. | ||||
| 		 | ||||
| 		self.id := id. | ||||
| 		self.parent := parent. | ||||
| 		parent addComponent: self. | ||||
|  | ||||
| 		parent connection addFrame: self. | ||||
| 		 | ||||
| 		self windowOpened. | ||||
| 	} | ||||
|  | ||||
| 	method expose: event | ||||
| 	{ | ||||
| 		('EXPOSE  IN WINDOWS....' & (self.id asString) & ' ' & (event x asString) & ' ' & (event y asString) & ' ' & (event width asString) & ' ' & (event height asString))  dump. | ||||
| 	} | ||||
|  | ||||
| 	(* TODO: take the followings out to a seperate mouse listener??? *) | ||||
| 	method mouseEntered: event | ||||
| 	{ | ||||
| 	} | ||||
| 	method mouseExited: event | ||||
| 	{ | ||||
| 	} | ||||
| 	method mouseClicked: event | ||||
| 	{ | ||||
| 	} | ||||
| 	method mousePressed: event | ||||
| 	{ | ||||
| 		('MOUSE PRESSED' & (self.id asString) & ' ' & (event x asString) & ' ' & (event y asString))  dump. | ||||
| 	} | ||||
| 	method mouseReleased: event | ||||
| 	{ | ||||
| 		('MOUSE RELEASED' & (self.id 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. | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	method windowOpened | ||||
| 	{ | ||||
| 	} | ||||
| 	method windowClosing | ||||
| 	{ | ||||
| 	} | ||||
| 	method windowClosed | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| class X11.Frame(Window) | ||||
| { | ||||
| 	dcl connection. | ||||
|  | ||||
| 	## method connection: connection { self.connection := connection }  | ||||
| 	method connection { ^self.connection } | ||||
| 	 | ||||
| 	method(#class) new | ||||
| 	{ | ||||
| 		##^(super new) __open_on: X11 connection. | ||||
| 		^(super new) __open_on: X11 connect.  ## connect if X11 is not connected. | ||||
| 	} | ||||
|  | ||||
| 	method __open_on: connection | ||||
| 	{ | ||||
| 		| id | | ||||
|  | ||||
| 		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 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. | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	##method show: flag | ||||
| 	##{ | ||||
| 	##} | ||||
|  | ||||
| 	(* | ||||
| 	method windowActivated: event | ||||
| 	{ | ||||
| 	} | ||||
| 	method windowDeactivated: event | ||||
| 	{ | ||||
| 	} | ||||
| 	method windowIconified: event | ||||
| 	{ | ||||
| 	} | ||||
| 	method windowDeiconified: event | ||||
| 	{ | ||||
| 	}*) | ||||
| } | ||||
|  | ||||
| class X11.Button(Component) | ||||
| { | ||||
| } | ||||
|  | ||||
|  | ||||
| extend X11 | ||||
| { | ||||
| 	method(#class) connect | ||||
| 	{ | ||||
| 		| c |  | ||||
| 		if (self.connection isNil)  | ||||
| 		{ | ||||
| 			c := self new. | ||||
| 			if (c connect isError) { X11.Exception signal: 'cannot connect' }. | ||||
| 			self.connection := c. | ||||
| 		}. | ||||
| 		^self.connection | ||||
| 	} | ||||
| 	 | ||||
| 	method(#class) disconnect | ||||
| 	{ | ||||
| 		if (self.connection notNil)  | ||||
| 		{ | ||||
| 			self.connection disconnect. | ||||
| 			self.connection := nil. | ||||
| 		}. | ||||
| 		^self.connection | ||||
| 	} | ||||
| 	 | ||||
| 	method(#class) connection | ||||
| 	{ | ||||
| 		^self.connection | ||||
| 	} | ||||
|  | ||||
| 	method(#class) enterEventLoop | ||||
| 	{ | ||||
| 		^self connect enterEventLoop | ||||
| 	} | ||||
|  | ||||
| 	method initialize | ||||
| 	{ | ||||
| 		super initialize. | ||||
|  | ||||
| 		self.expose_event := X11.ExposeEvent new. | ||||
| 		self.key_event := X11.KeyEvent new. | ||||
| 		self.mouse_event := X11.MouseEvent new. | ||||
| 		self.mouse_wheel_event := X11.MouseWheelEvent new. | ||||
|  | ||||
| 		self.ll_event_blocks := System.Dictionary new. | ||||
| 		self.ll_event_blocks | ||||
| 			at: X11.LLEvent.KEY_PRESS      put: #__handle_key_event:; | ||||
| 			at: X11.LLEvent.KEY_RELEASE    put: #__handle_key_event:; | ||||
| 			at: X11.LLEvent.BUTTON_PRESS   put: #__handle_button_event:; | ||||
| 			at: X11.LLEvent.BUTTON_RELEASE put: #__handle_button_event:; | ||||
| 			at: X11.LLEvent.MOTION_NOTIFY  put: #__handle_notify:; | ||||
| 			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.CLIENT_MESSAGE put: #__handle_client_message:. | ||||
| 	} | ||||
|  | ||||
| 	method connect | ||||
| 	{ | ||||
| 		| t | | ||||
| 		if (self.frames isNil) | ||||
| 		{ | ||||
| 			if ((t := self _connect) isError)  { ^t }. | ||||
| 			self.id := t. | ||||
| 			self.frames := System.Dictionary new. | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	method disconnect | ||||
| 	{ | ||||
| 		if (self.frames notNil) | ||||
| 		{ | ||||
| 			self.frames do: [ :frame | | ||||
| 				frame close. | ||||
| 			]. | ||||
| 			self.frames := nil. | ||||
| 			self _disconnect. | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	method addFrame: frame | ||||
| 	{ | ||||
| 		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. | ||||
| 	} | ||||
|  | ||||
| 	method removeFrame: frame | ||||
| 	{ | ||||
| 		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. | ||||
| 	} | ||||
|  | ||||
| 	method enterEventLoop | ||||
| 	{ | ||||
| 		if (self.event_loop_sem isNil) | ||||
| 		{ | ||||
| 			self.event_loop_sem := Semaphore new. | ||||
| 			Processor signal: self.event_loop_sem onInput: (self _get_fd). | ||||
| 			self.event_loop_proc := [  | ||||
| 				| event ongoing |  | ||||
| 				 | ||||
| 				ongoing := true. | ||||
| 				while (self.frames size > 0)  | ||||
| 				{ | ||||
| 'Waiting for X11 event...' dump. | ||||
| 					self.event_loop_sem wait. | ||||
| 					if (ongoing not) { break }. | ||||
|  | ||||
| 					while ((event := self _get_event) notNil)  | ||||
| 					{ | ||||
| 					## XCB_EXPOSE 12 | ||||
| 					## XCB_DESTROY_WINDOW 4 | ||||
| ('EVENT================>' & event asString) dump. | ||||
| 						if (event isError) | ||||
| 						{ | ||||
| 							 'Error has occurred in ....' dump. | ||||
| 							ongoing := false. | ||||
| 							break. | ||||
| 						} | ||||
| 						else  | ||||
| 						{  | ||||
| 							self __dispatch_event: event.  | ||||
| 						}. | ||||
| 					}. | ||||
| 				}. | ||||
|  | ||||
| 				Processor unsignal: self.event_loop_sem. | ||||
| 				self.event_loop_sem := nil. | ||||
| 				 | ||||
| 				self disconnect. | ||||
| 			] fork. | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	method exitEventLoop | ||||
| 	{ | ||||
| 		if (self.event_loop_sem notNil) | ||||
| 		{ | ||||
| 			###self.even_loop_sem ... | ||||
| 			self.event_loop_proc terminate. | ||||
| 			self.event_loop_proc := nil. | ||||
| 			self.event_loop_sem := nil. | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	method signal_event_loop_semaphore | ||||
| 	{ | ||||
| 		self.event_loop_sem signal. | ||||
| 	} | ||||
|  | ||||
| 	method __dispatch_event: event | ||||
| 	{ | ||||
| 		| type mthname | | ||||
| 		 | ||||
| 		##type := System _getUint8(event, 0). | ||||
| 		type := event getUint8(0). | ||||
| 		 | ||||
| 		mthname := self.ll_event_blocks at: (type bitAnd: 16r7F). | ||||
| 		if (mthname isError) | ||||
| 		{ | ||||
| 			(* unknown event. ignore it *) | ||||
| ('IGNORING UNKNOWN LL-EVENT TYPE ' & type asString) dump. | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| ('Performing ...' & mthname asString) dump. | ||||
| 			^self perform (mthname, event). | ||||
| 			##^self perform: mthname with: event. | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	method __handle_notify: type | ||||
| 	{ | ||||
| 		^9999999999 | ||||
| 	} | ||||
|  | ||||
| 	method __handle_expose: event | ||||
| 	{ | ||||
| 		(* | ||||
| 			typedef struct xcb_expose_event_t { | ||||
| 				uint8_t      response_type; | ||||
| 				uint8_t      pad0; | ||||
| 				uint16_t     sequence; | ||||
| 				xcb_window_t window; // uint32_t | ||||
| 				uint16_t     x; | ||||
| 				uint16_t     y; | ||||
| 				uint16_t     width; | ||||
| 				uint16_t     height; | ||||
| 				uint16_t     count; | ||||
| 				uint8_t      pad1[2]; | ||||
| 			} xcb_expose_event_t; | ||||
| 		*) | ||||
|  | ||||
| 		| wid frame | | ||||
|  | ||||
| 		##wid := System _getUint32(event, 4). ## window | ||||
| 		wid := event getUint32(4). | ||||
| 		frame := self.frames at: wid. | ||||
|  | ||||
| 		if (frame notError) | ||||
| 		{ | ||||
| 			(* | ||||
| 			self.expose_event  | ||||
| 				x: System _getUint16(event, 8)        ## x | ||||
| 				y: System _getUint16(event, 10)       ## y | ||||
| 				width: System _getUint16(event, 12)   ## width | ||||
| 				height: System _getUint16(event, 14). ## height | ||||
| 			*) | ||||
| 			self.expose_event  | ||||
| 				x: event getUint16(8)        ## x | ||||
| 				y: event getUint16(10)       ## y | ||||
| 				width: event getUint16(12)   ## width | ||||
| 				height: event getUint16(14). ## height | ||||
|  | ||||
| 			frame expose: self.expose_event. | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			System logNl: ('Expose event on unknown window - ' & wid asString). | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	method __handle_button_event: event | ||||
| 	{ | ||||
| 		(* | ||||
| 			typedef struct xcb_button_press_event_t { | ||||
| 				uint8_t         response_type; | ||||
| 				xcb_button_t    detail;  // uint8_t | ||||
| 				uint16_t        sequence; | ||||
| 				xcb_timestamp_t time;    // uint32_t | ||||
| 				xcb_window_t    root;    // uint32_t | ||||
| 				xcb_window_t    event; | ||||
| 				xcb_window_t    child; | ||||
| 				int16_t         root_x; | ||||
| 				int16_t         root_y; | ||||
| 				int16_t         event_x; | ||||
| 				int16_t         event_y; | ||||
| 				uint16_t        state; | ||||
| 				uint8_t         same_screen; | ||||
| 				uint8_t         pad0; | ||||
| 			} xcb_button_press_event_t; | ||||
| 			typedef xcb_button_press_event_t xcb_button_release_event_t; | ||||
| 		*) | ||||
|  | ||||
| 		| type wid frame 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. | ||||
|  | ||||
| 		if (frame notError) | ||||
| 		{ | ||||
| 			##detail := System _getUint8(event, 1). | ||||
| 			detail := event getUint8(1). | ||||
| 			if (detail >= 1 and: [detail <= 3]) | ||||
| 			{ | ||||
| 				(* | ||||
| 				self.mouse_event  | ||||
| 					## TODO: encode detail also.. | ||||
| 					x: System _getUint16(event, 24)   ## event_x | ||||
| 					y: System _getUint16(event, 26).  ## event_y | ||||
| 				*) | ||||
| 				self.mouse_event  | ||||
| 					## TODO: encode detail also.. | ||||
| 					x: event getUint16(24)   ## event_x | ||||
| 					y: event getUint16(26).  ## event_y | ||||
| 				 | ||||
| 				if (type == X11.LLEvent.BUTTON_PRESS) | ||||
| 				{ | ||||
| 					frame mousePressed: self.mouse_event | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					frame mouseReleased: self.mouse_event | ||||
| 				} | ||||
| 			} | ||||
| 			elsif (detail == 4 or: [detail == 5]) | ||||
| 			{ | ||||
| 				if (type == X11.LLEvent.BUTTON_RELEASE) | ||||
| 				{ | ||||
| 					(* | ||||
| 					self.mouse_wheel_event | ||||
| 						x: System _getUint16(event, 24)   ## event_x | ||||
| 						y: System _getUint16(event, 26)   ## event_y | ||||
| 						amount: (if (detail == 4) { -1 } else { 1 }). | ||||
| 					*) | ||||
| 					self.mouse_wheel_event | ||||
| 						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 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			System logNl: ('Button event on unknown window - ' & wid asString). | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	method __handle_client_message: event | ||||
| 	{ | ||||
| 		(* | ||||
| 			typedef union xcb_client_message_data_t { | ||||
| 				uint8_t  data8[20]; | ||||
| 				uint16_t data16[10]; | ||||
| 				uint32_t data32[5]; | ||||
| 			} xcb_client_message_data_t; | ||||
|  | ||||
| 			typedef struct xcb_client_message_event_t { | ||||
| 				uint8_t                   response_type; | ||||
| 				uint8_t                   format; | ||||
| 				uint16_t                  sequence; | ||||
| 				xcb_window_t              window;    // uint32_t | ||||
| 				xcb_atom_t                type;      // uint32_t | ||||
| 				xcb_client_message_data_t data; | ||||
| 			} xcb_client_message_event_t; | ||||
| 		*) | ||||
| 		| type wid frame dw | | ||||
| 		 | ||||
| 		##wid := System _getUint32(event, 4). ## window | ||||
| 		wid := event getUint32(4). ## window | ||||
| 		frame := self.frames at: wid. | ||||
| 		 | ||||
| 		if (frame notError) | ||||
| 		{ | ||||
| 			##dw := System _getUint32(event, 12). ## data.data32[0] | ||||
| 			dw := event getUint32(12). ## data.data32[0] | ||||
| 			if (dw == frame _get_dwatom) | ||||
| 			{ | ||||
| 				## TODO: call close query callback??? | ||||
| 				frame close. | ||||
| 			} | ||||
| 			 | ||||
| 			## TODO: handle other client messages | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			System logNl: ('Client message on unknown window - ' & wid asString). | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	method __handle_key_event: type | ||||
| 	{ | ||||
| 		(* | ||||
| 			typedef struct xcb_key_press_event_t { | ||||
| 				uint8_t         response_type; | ||||
| 				xcb_keycode_t   detail; | ||||
| 				uint16_t        sequence; | ||||
| 				xcb_timestamp_t time; | ||||
| 				xcb_window_t    root; | ||||
| 				xcb_window_t    event; | ||||
| 				xcb_window_t    child; | ||||
| 				int16_t         root_x; | ||||
| 				int16_t         root_y; | ||||
| 				int16_t         event_x; | ||||
| 				int16_t         event_y; | ||||
| 				uint16_t        state; | ||||
| 				uint8_t         same_screen; | ||||
| 				uint8_t         pad0; | ||||
| 			} xcb_key_press_event_t; | ||||
| 			typedef xcb_key_press_event_t xcb_key_release_event_t; | ||||
| 		*) | ||||
|  | ||||
| 		if (type = X11.LLEvent.KEY_PRESS) | ||||
| 		{ | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| class MyButton(X11.Window) | ||||
| { | ||||
| 	method expose: event | ||||
| 	{ | ||||
| 	|gc| | ||||
| 	 | ||||
|  | ||||
| 		super expose: event. | ||||
| 		 | ||||
|  | ||||
| gc := X11.GC new: self.	 | ||||
| gc _foreground: 2.	 | ||||
| gc _fillRect(0, 0, 50, 50). | ||||
| gc close. | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class MyFrame(X11.Frame) | ||||
| { | ||||
| 	dcl gc. | ||||
| 	dcl b1. | ||||
| 	dcl b2. | ||||
|  | ||||
| 	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). | ||||
| 		}. | ||||
| 		 | ||||
| 		b1 := MyButton new: self. | ||||
| 	} | ||||
|  | ||||
| 	method windowClosing | ||||
| 	{ | ||||
| 		super windowClosing. | ||||
| 		(*if (self.gc notNil) | ||||
| 		{ | ||||
| 			self.gc close. | ||||
| 			self.gc := nil. | ||||
| 		}*) | ||||
| 	} | ||||
|  | ||||
| 	method expose: event | ||||
| 	{ | ||||
| 		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 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 _drawRect(100, 100, 200, 200).*) | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| class MyObject(Object) | ||||
| {	 | ||||
| 	method(#class) abc | ||||
| 	{ | ||||
| 	^9234554123489129038123908123908312908 | ||||
| 	} | ||||
| 	 | ||||
| 	method(#class) main  | ||||
| 	{ | ||||
| 		| f q | | ||||
|  | ||||
| 		f := 20. | ||||
| 		(q:=:{ 10 -> 20, 20 -> 30, f + 40 -> self abc, (Association key: 10 value: 49), f -> f })dump. | ||||
| 		(q at: 60) dump. | ||||
| 		(q at: 10) dump. | ||||
|  | ||||
|  | ||||
| 		#( #a:y: #b #c) dump. | ||||
| 		f := LinkedList new. | ||||
| 		f addLast: 10. | ||||
| 		f addLast: 20. | ||||
| 		q := f addLast: 30. | ||||
| 		f addLast: 40. | ||||
| 		f removeLink: q. | ||||
| 		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. | ||||
| 		q := MyFrame new. | ||||
|  | ||||
| 	##	MyButton new: q. | ||||
| 	##	MyButton new: f. | ||||
|  | ||||
| (* | ||||
| 		f add: X11.Button new: 'click me'. | ||||
| 		f width: 200 height: 200. | ||||
| 		f show. | ||||
| *) | ||||
| 		 | ||||
| 		X11 enterEventLoop. ## this is not a blocking call. it spawns another process. | ||||
|  | ||||
| 		(*while (true) | ||||
| 		{ | ||||
| 			'111' dump. | ||||
| 			##x signal_event_loop_semaphore. | ||||
| 			Processor sleepFor: 5. | ||||
| 		}.*) | ||||
| 		## [ while (true) { '111' dump. Processor sleepFor: 1. } ] fork. | ||||
|  | ||||
| 		##X11 disconnect. | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user