interim commit of ongoing X11 works
This commit is contained in:
@ -2,26 +2,49 @@
|
||||
|
||||
class X11(Object) from 'x11'
|
||||
{
|
||||
## =====================================================================
|
||||
## this part of the class must match the internal
|
||||
## definition struct x11_t defined in _x11.h
|
||||
## ---------------------------------------------------------------------
|
||||
var display_base := nil.
|
||||
var shell_container := nil.
|
||||
|
||||
var windows. ## all windows registered
|
||||
|
||||
var event_loop_sem, event_loop_proc.
|
||||
var ll_event_blocks.
|
||||
|
||||
var llevent.
|
||||
var expose_event.
|
||||
var key_event.
|
||||
var mouse_event.
|
||||
var mouse_wheel_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).
|
||||
var shell_container := nil.
|
||||
var window_registrar. ## all windows registered
|
||||
|
||||
method(#primitive) _get_evtbuf.
|
||||
var event_loop_sem, event_loop_proc.
|
||||
var llevent_blocks.
|
||||
|
||||
method(#primitive,#liberal) _open_display(name).
|
||||
method(#primitive) _close_display.
|
||||
method(#primitive) _get_fd.
|
||||
method(#primitive) _get_event.
|
||||
|
||||
method(#primitive) _create_window(parent_window, x, y, width, height, fgcolor, bgcolor).
|
||||
method(#primitive) _destroy_window(window).
|
||||
|
||||
##method(#primitive) _fill_rectangle(window, gc, x, y, width, height).
|
||||
method(#primitive) _draw_rectangle(window, gc, x, y, width, height).
|
||||
|
||||
method __create_window(parent_window, x, y, width, height, fgcolor, bgcolor, owner)
|
||||
{
|
||||
| w |
|
||||
w := self _create_window(parent_window, x, y, width, height, fgcolor, bgcolor).
|
||||
if (w notError) { self.window_registrar at: w put: owner }.
|
||||
^w
|
||||
}
|
||||
|
||||
method __close_window(window_handle)
|
||||
{
|
||||
| w |
|
||||
w := self _destroy_window(window_handle).
|
||||
if (w notError) { self.window_registrar removeKey: window_handle }
|
||||
}
|
||||
}
|
||||
|
||||
class X11.Exception(System.Exception)
|
||||
@ -50,7 +73,7 @@ class X11.Rectangle(Object)
|
||||
## ---------------------------------------------------------------------------
|
||||
## Event
|
||||
## ---------------------------------------------------------------------------
|
||||
pooldic X11.LLEvent
|
||||
pooldic X11.LLEventType
|
||||
{
|
||||
KEY_PRESS := 2.
|
||||
KEY_RELEASE := 3.
|
||||
@ -66,6 +89,11 @@ pooldic X11.LLEvent
|
||||
CLIENT_MESSAGE := 33.
|
||||
}
|
||||
|
||||
class X11.LLEvent(Object)
|
||||
{
|
||||
var(#get) type := 0, window := 0, x := 0, y := 0, width := 0, height := 0.
|
||||
}
|
||||
|
||||
class X11.Event(Object)
|
||||
{
|
||||
}
|
||||
@ -109,6 +137,45 @@ class X11.ExposeEvent(X11.Event)
|
||||
|
||||
|
||||
|
||||
## ---------------------------------------------------------------------------
|
||||
## X11 Context
|
||||
## ---------------------------------------------------------------------------
|
||||
class X11.GraphicsContext(Object)
|
||||
{
|
||||
var(#get) widget := nil, gcHandle := nil.
|
||||
|
||||
var(#get,#set)
|
||||
foreground := 0,
|
||||
background := 0,
|
||||
lineWidth := 1,
|
||||
lineStyle := 0,
|
||||
fillStyle := 0.
|
||||
|
||||
method(#class) new: widget
|
||||
{
|
||||
^(super new) __make_gc_on: widget
|
||||
}
|
||||
|
||||
method __make_gc_on: widget
|
||||
{
|
||||
| gc |
|
||||
gc := widget displayServer _create_gc (widget windowHandle).
|
||||
if (gc isError) { selfns.Exception signal: 'Cannot create a graphics context' }.
|
||||
self.gcHandle := gc.
|
||||
self.widget := widget.
|
||||
}
|
||||
|
||||
method fillRectangle(x, y, width, height)
|
||||
{
|
||||
^self.widget displayServer _fill_rectangle (self.widget windowHandle, self.gcHandle, x, y, width, height).
|
||||
}
|
||||
|
||||
method drawRectangle(x, y, width, height)
|
||||
{
|
||||
^self.widget displayServer _draw_rectangle (self.widget windowHandle, self.gcHandle, x, y, width, height).
|
||||
}
|
||||
}
|
||||
|
||||
## ---------------------------------------------------------------------------
|
||||
## X11 Widgets
|
||||
## ---------------------------------------------------------------------------
|
||||
@ -125,23 +192,41 @@ class X11.Widget(Object)
|
||||
bgcolor := 0,
|
||||
realized := false.
|
||||
|
||||
method displayOn: grctx
|
||||
{
|
||||
}
|
||||
|
||||
method displayBase
|
||||
method displayServer
|
||||
{
|
||||
if (self.parent isNil) { ^nil }.
|
||||
^self.parent displayBase.
|
||||
^self.parent displayServer.
|
||||
}
|
||||
|
||||
method windowHandle
|
||||
{
|
||||
(* i assume that a widget doesn't' with a low-level window by default.
|
||||
* if a widget maps to a window, the widget class must implement the
|
||||
* windowHandle method to return the low-level window handle.
|
||||
* if it doesn't map to a window, it piggybacks on the parent's window *)
|
||||
if (self.parent isNil) { ^nil }.
|
||||
^self.parent windowHandle.
|
||||
}
|
||||
|
||||
method paint: paint_event
|
||||
{
|
||||
}
|
||||
|
||||
method realize
|
||||
{
|
||||
## super realize chaining required???
|
||||
}
|
||||
|
||||
method dispose
|
||||
{
|
||||
}
|
||||
## what should be done first? remvoe from container? should dispose be called?
|
||||
## super dispose chaining required?
|
||||
##if (self.parent notNil)
|
||||
##{
|
||||
## self.parent remove: self.
|
||||
##}
|
||||
}
|
||||
}
|
||||
|
||||
class X11.Label(X11.Widget)
|
||||
@ -151,24 +236,28 @@ class X11.Label(X11.Widget)
|
||||
method text: text
|
||||
{
|
||||
self.text := text.
|
||||
self displayOn: nil.
|
||||
if (self windowHandle notNil) { self paint: nil }
|
||||
}
|
||||
|
||||
method displayOn: grctx
|
||||
method paint: paint_event
|
||||
{
|
||||
## grctx _fillRectangle ().
|
||||
## grctx _drawText (...).
|
||||
## TODO Draw Text...
|
||||
| gc |
|
||||
System logNl: 'LABEL GC.......'.
|
||||
gc := selfns.GraphicsContext new: self.
|
||||
gc foreground: 100.
|
||||
gc drawRectangle (self.x, self.y, self.width, self.height).
|
||||
###gc.drawText (self.title)
|
||||
}
|
||||
|
||||
method realize
|
||||
{
|
||||
## if i want to use a window to represent it, it must create window here.
|
||||
## otherwise, do other works in displayOn???
|
||||
## otherwise, do other works in paint:???
|
||||
}
|
||||
|
||||
method dispose
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,7 +286,7 @@ class X11.Composite(X11.Widget)
|
||||
| link |
|
||||
if (widget parent =~ self)
|
||||
{
|
||||
selfns.Exception sinal: 'Cannot remove a foreign widget'
|
||||
selfns.Exception sinal: 'Cannot remove an unknown widget'
|
||||
}.
|
||||
|
||||
## TODO: unmap and destroy...
|
||||
@ -213,14 +302,15 @@ class X11.Composite(X11.Widget)
|
||||
|
||||
method dispose
|
||||
{
|
||||
self.children do: [:child | child dispose ]
|
||||
self.children do: [:child | child dispose ]
|
||||
}
|
||||
}
|
||||
|
||||
class X11.Shell(X11.Composite)
|
||||
{
|
||||
var(#get) title.
|
||||
var(#get,#set) displayBase.
|
||||
var(#get) title := ''.
|
||||
var(#get,#set) displayServer := nil.
|
||||
var(#get) windowHandle := nil.
|
||||
|
||||
method new: title
|
||||
{
|
||||
@ -230,7 +320,7 @@ class X11.Shell(X11.Composite)
|
||||
method title: title
|
||||
{
|
||||
self.title := title.
|
||||
if (self.realized)
|
||||
if (self.windowHandle notNil)
|
||||
{
|
||||
## set window title of this window.
|
||||
}
|
||||
@ -239,16 +329,36 @@ class X11.Shell(X11.Composite)
|
||||
method realize
|
||||
{
|
||||
| wind |
|
||||
if (self.realized) { ^self }.
|
||||
if (self.windowHandle notNil) { ^self }.
|
||||
|
||||
wind := X11 _create_window(self.displayBase, nil, self.x, self.y, self.width, self.height, self.fgcolor, self.bgcolor).
|
||||
wind := self.displayServer __create_window(nil, self.x, self.y, self.width, self.height, self.fgcolor, self.bgcolor, self).
|
||||
if (wind isError)
|
||||
{
|
||||
self.Exception signal: ('Cannot create shell ' & self.title).
|
||||
}.
|
||||
|
||||
self.children do: [:child | child realize ].
|
||||
self.realized := true.
|
||||
self.windowHandle := wind.
|
||||
|
||||
[
|
||||
self.children do: [:child | child realize ].
|
||||
] on: System.Exception do: [:ex |
|
||||
self.displayServer _destroy_window(wind).
|
||||
self.windowHandle := nil.
|
||||
ex pass
|
||||
].
|
||||
|
||||
### call displayOn: from the exposure handler...
|
||||
self paint: nil.
|
||||
}
|
||||
|
||||
method dispose
|
||||
{
|
||||
super dispose.
|
||||
if (self.windowHandle notNil)
|
||||
{
|
||||
self.displayServer _destroy_window (self.windowHandle).
|
||||
self.windowHandle := nil.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,20 +374,16 @@ extend X11
|
||||
|
||||
method __connect_to: name
|
||||
{
|
||||
| base |
|
||||
base := X11 _open_display(name).
|
||||
if (base isError) { self.Exception signal: 'cannot open display' }.
|
||||
self.display_base := base.
|
||||
if (self _open_display(name) isError)
|
||||
{
|
||||
self.Exception signal: 'cannot open display'
|
||||
}
|
||||
.
|
||||
self.display_base dump.
|
||||
}
|
||||
|
||||
method dispose
|
||||
{
|
||||
if (self.display_event notNil)
|
||||
{
|
||||
X11 _free_event.
|
||||
self.display_event := nil.
|
||||
}.
|
||||
|
||||
if (self.shell_container notNil)
|
||||
{
|
||||
self.shell_container dispose.
|
||||
@ -286,101 +392,95 @@ extend X11
|
||||
|
||||
if (self.display_base notNil)
|
||||
{
|
||||
self _close_display.
|
||||
##self.display_base := nil.
|
||||
}.
|
||||
|
||||
X11 _close_display (self.display_base).
|
||||
self.display_base := nil.
|
||||
}l
|
||||
## TODO: check if _fini_trailer is not called for some exception throwing...
|
||||
##self _fini_trailer.
|
||||
}
|
||||
|
||||
method initialize
|
||||
{
|
||||
super initialize.
|
||||
|
||||
self.shell_container := self.Composite new.
|
||||
self.display_event := self _alloc_event.
|
||||
|
||||
self.windows := System.Dictionary new: 100.
|
||||
|
||||
self.llevent := self.LLEvent new.
|
||||
self.expose_event := self.ExposeEvent new.
|
||||
self.key_event := self.KeyEvent new.
|
||||
self.mouse_event := self.MouseEvent new.
|
||||
self.mouse_wheel_event := self.MouseWheelEvent new.
|
||||
|
||||
self.shell_container := self.Composite new.
|
||||
self.window_registrar := System.Dictionary new: 100.
|
||||
|
||||
(*
|
||||
self.ll_event_blocks := System.Dictionary new.
|
||||
self.ll_event_blocks
|
||||
at: self.LLEvent.KEY_PRESS put: #__handle_key_event:;
|
||||
at: self.LLEvent.KEY_RELEASE put: #__handle_key_event:;
|
||||
at: self.LLEvent.BUTTON_PRESS put: #__handle_button_event:;
|
||||
at: self.LLEvent.BUTTON_RELEASE put: #__handle_button_event:;
|
||||
at: self.LLEvent.MOTION_NOTIFY put: #__handle_notify:;
|
||||
at: self.LLEvent.ENTER_NOTIFY put: #__handle_notify:;
|
||||
at: self.LLEvent.LEAVE_NOTIFY put: #__handle_notify:;
|
||||
at: self.LLEvent.EXPOSE put: #__handle_expose:;
|
||||
at: self.LLEvent.DESTROY_NOTIFY put: #__handle_destroy_notify:;
|
||||
at: self.LLEvent.CONFIGURE_NOTIFY put: #__handle_configure_notify:;
|
||||
at: self.LLEvent.CLIENT_MESSAGE put: #__handle_client_message:.
|
||||
|
||||
self.llevent_blocks := System.Dictionary new.
|
||||
self.llevent_blocks
|
||||
at: self.LLEventType.KEY_PRESS put: #__handle_key_event:;
|
||||
at: self.LLEventType.KEY_RELEASE put: #__handle_key_event:;
|
||||
at: self.LLEventType.BUTTON_PRESS put: #__handle_button_event:;
|
||||
at: self.LLEventType.BUTTON_RELEASE put: #__handle_button_event:;
|
||||
at: self.LLEventType.MOTION_NOTIFY put: #__handle_notify:;
|
||||
at: self.LLEventType.ENTER_NOTIFY put: #__handle_notify:;
|
||||
at: self.LLEventType.LEAVE_NOTIFY put: #__handle_notify:;
|
||||
at: self.LLEventType.EXPOSE put: #__handle_expose:;
|
||||
at: self.LLEventType.DESTROY_NOTIFY put: #__handle_destroy_notify:;
|
||||
at: self.LLEventType.CONFIGURE_NOTIFY put: #__handle_configure_notify:;
|
||||
at: self.LLEventType.CLIENT_MESSAGE put: #__handle_client_message:.
|
||||
*)
|
||||
self.ll_event_blocks := %{
|
||||
self.LLEvent.KEY_PRESS -> #__handle_key_event:,
|
||||
self.LLEvent.KEY_RELEASE -> #__handle_key_event:,
|
||||
self.LLEvent.BUTTON_PRESS -> #__handle_button_event:,
|
||||
self.LLEvent.BUTTON_RELEASE -> #__handle_button_event:,
|
||||
self.LLEvent.MOTION_NOTIFY -> #__handle_notify:,
|
||||
self.LLEvent.ENTER_NOTIFY -> #__handle_notify:,
|
||||
self.LLEvent.LEAVE_NOTIFY -> #__handle_notify:,
|
||||
self.LLEvent.EXPOSE -> #__handle_expose:,
|
||||
self.LLEvent.DESTROY_NOTIFY -> #__handle_destroy_notify:,
|
||||
self.LLEvent.CONFIGURE_NOTIFY -> #__handle_configure_notify:,
|
||||
self.LLEvent.CLIENT_MESSAGE -> #__handle_client_message:
|
||||
self.llevent_blocks := %{
|
||||
self.LLEventType.KEY_PRESS -> #__handle_key_event:,
|
||||
self.LLEventType.KEY_RELEASE -> #__handle_key_event:,
|
||||
self.LLEventType.BUTTON_PRESS -> #__handle_button_event:,
|
||||
self.LLEventType.BUTTON_RELEASE -> #__handle_button_event:,
|
||||
self.LLEventType.MOTION_NOTIFY -> #__handle_notify:,
|
||||
self.LLEventType.ENTER_NOTIFY -> #__handle_notify:,
|
||||
self.LLEventType.LEAVE_NOTIFY -> #__handle_notify:,
|
||||
self.LLEventType.EXPOSE -> #__handle_expose:,
|
||||
self.LLEventType.DESTROY_NOTIFY -> #__handle_destroy_notify:,
|
||||
self.LLEventType.CONFIGURE_NOTIFY -> #__handle_configure_notify:,
|
||||
self.LLEventType.CLIENT_MESSAGE -> #__handle_client_message:
|
||||
}.
|
||||
|
||||
}
|
||||
|
||||
method addShell: shell
|
||||
{
|
||||
if (shell displayBase isNil)
|
||||
if (shell displayServer isNil)
|
||||
{
|
||||
self.shell_container add: shell.
|
||||
shell displayBase: self.display_base.
|
||||
shell displayServer: self.
|
||||
}
|
||||
}
|
||||
|
||||
method removeShell: shell
|
||||
{
|
||||
if (shell displayBase notNil)
|
||||
if (shell displayServer notNil)
|
||||
{
|
||||
self.shell_container remove: shell.
|
||||
shell displayBase: nil.
|
||||
shell displayServer: nil.
|
||||
}
|
||||
}
|
||||
|
||||
method registerWindow: window
|
||||
{
|
||||
^self.windows at: (window windowBase) put: window.
|
||||
}
|
||||
|
||||
method removeWindow: window
|
||||
{
|
||||
^self.windows removeKey: (window windowBase)
|
||||
}
|
||||
|
||||
method enterEventLoop
|
||||
{
|
||||
if (self.event_loop_sem isNil)
|
||||
{
|
||||
self.event_loop_sem := Semaphore new.
|
||||
Processor signal: self.event_loop_sem onInput: (X11 _get_fd(self.display_base)).
|
||||
Processor signal: self.event_loop_sem onInput: (self _get_fd).
|
||||
self.event_loop_proc := [
|
||||
| event ongoing |
|
||||
| evtbuf event ongoing |
|
||||
|
||||
ongoing := true.
|
||||
while (self.shell_container childrenCount > 0)
|
||||
{
|
||||
###'Waiting for X11 event...' dump.
|
||||
'Waiting for X11 event...' dump.
|
||||
self.event_loop_sem wait.
|
||||
if (ongoing not) { break }.
|
||||
|
||||
while (self _get_event(self.display_base, self.display_event))
|
||||
while ((event := self _get_event) notNil)
|
||||
{
|
||||
if (event isError)
|
||||
{
|
||||
@ -421,15 +521,16 @@ extend X11
|
||||
|
||||
method __dispatch_event: event
|
||||
{
|
||||
(*
|
||||
| type mthname |
|
||||
|
||||
|
||||
##type := System _getUint8(event, 0).
|
||||
type := event getUint8(0).
|
||||
|
||||
mthname := self.ll_event_blocks at: (type bitAnd: 16r7F).
|
||||
mthname := self.llevent_blocks at: (type bitAnd: 16r7F).
|
||||
if (mthname isError)
|
||||
{
|
||||
(* unknown event. ignore it *)
|
||||
('IGNORING UNKNOWN LL-EVENT TYPE ' & type asString) dump.
|
||||
}
|
||||
else
|
||||
@ -437,6 +538,7 @@ extend X11
|
||||
^self perform (mthname, event).
|
||||
##^self perform: mthname with: event.
|
||||
}
|
||||
*)
|
||||
}
|
||||
|
||||
method __handle_notify: type
|
||||
|
Reference in New Issue
Block a user