removed the containing subdir
This commit is contained in:
886
kernel/X11.moo
Normal file
886
kernel/X11.moo
Normal file
@ -0,0 +1,886 @@
|
||||
#include "Moo.moo".
|
||||
|
||||
interface X11able
|
||||
{
|
||||
method(#dual) abc.
|
||||
method(#dual,#liberal) def(x, y).
|
||||
}
|
||||
interface X11able2
|
||||
{
|
||||
method(#dual) abc2.
|
||||
method(#dual) def.
|
||||
}
|
||||
|
||||
interface X11able3
|
||||
{
|
||||
method(#dual) class.
|
||||
}
|
||||
|
||||
class QQQ(Object)
|
||||
{
|
||||
}
|
||||
|
||||
extend QQQ [X11able]
|
||||
{
|
||||
|
||||
method(#dual) abc { ^nil }
|
||||
method(#dual,#liberal) def(x, z) { ^nil }
|
||||
}
|
||||
|
||||
class X11(Object) [X11able,selfns.X11able3] 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 window_registry. // all windows registered
|
||||
|
||||
var event_loop_sem, event_loop_proc.
|
||||
var llevent_blocks.
|
||||
var event_loop_exit_req := false.
|
||||
|
||||
|
||||
method(#dual) abc { ^nil }
|
||||
method(#dual,#liberal) def(x, z) { ^nil }
|
||||
//#method(#dual) abc3 { ^nil }
|
||||
|
||||
interface X11able3
|
||||
{
|
||||
method(#dual) abc55.
|
||||
}
|
||||
|
||||
class Exception(System.Exception)
|
||||
{
|
||||
}
|
||||
|
||||
class Point(Object)
|
||||
{
|
||||
var(#get,#set) x := 0, y := 0.
|
||||
}
|
||||
|
||||
class Dimension(Object)
|
||||
{
|
||||
var(#get,#set) width := 0, height := 0.
|
||||
}
|
||||
|
||||
class Rectangle(Object)
|
||||
{
|
||||
var(#get,#set)
|
||||
x := 0,
|
||||
y := 0,
|
||||
width := 0,
|
||||
height := 0.
|
||||
}
|
||||
|
||||
extend Point
|
||||
{
|
||||
method print
|
||||
{
|
||||
x dump.
|
||||
y dump.
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: TODO: compiler enhancement
|
||||
class X11(Object)
|
||||
{
|
||||
class Rectangl(Object)
|
||||
{
|
||||
}
|
||||
}
|
||||
class XRect(X11.X11.Rectangl) -> X11 in X11.Rectangl is not the inner X11. as long as a period is found, the search begins at top.
|
||||
{
|
||||
}
|
||||
----> should i support soemthign like ::X11.Rectangle and X11.Rectangle? ::X11.Rectangle alwasy from the top???
|
||||
-----> or .X11.Rectangle -> to start search from the current name space???
|
||||
*/
|
||||
|
||||
method(#primitive,#liberal) _open_display(name).
|
||||
method(#primitive) _close_display.
|
||||
method(#primitive) _get_fd.
|
||||
method(#primitive) _get_llevent(llevent).
|
||||
|
||||
method(#primitive) _create_window(parent_window_handle, x, y, width, height, fgcolor, bgcolor).
|
||||
method(#primitive) _destroy_window(window_handle).
|
||||
|
||||
method(#primitive) _create_gc (window_handle).
|
||||
method(#primitive) _destroy_gc (gc). // note this one accepts a GC object.
|
||||
method(#primitive) _apply_gc (gc). // note this one accepts a GC object, not a GC handle.
|
||||
|
||||
method(#primitive) _draw_rectangle(window_handle, gc_handle, x, y, width, height).
|
||||
method(#primitive) _fill_rectangle(window_handle, gc_handle, x, y, width, height).
|
||||
method(#primitive) _draw_string(gc, x, y, string).
|
||||
|
||||
method __create_window(parent_window_handle, x, y, width, height, fgcolor, bgcolor, owner)
|
||||
{
|
||||
| w |
|
||||
w := self _create_window(parent_window_handle, x, y, width, height, fgcolor, bgcolor).
|
||||
if (w notError) { self.window_registry at: w put: owner }.
|
||||
^w
|
||||
}
|
||||
|
||||
method __destroy_window(window_handle)
|
||||
{
|
||||
| w |
|
||||
//#('DESTROY ' & window_handle asString) dump.
|
||||
w := self _destroy_window(window_handle).
|
||||
if (w notError) { self.window_registry removeKey: window_handle }
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Event
|
||||
// ---------------------------------------------------------------------------
|
||||
pooldic X11.LLEventType
|
||||
{
|
||||
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,
|
||||
DESTROY_NOTIFY := 17,
|
||||
CONFIGURE_NOTIFY := 22,
|
||||
CLIENT_MESSAGE := 33,
|
||||
|
||||
SHELL_CLOSE := 65537
|
||||
}
|
||||
|
||||
class X11.LLEvent(Object)
|
||||
{
|
||||
var(#get) type := 0, window := 0, x := 0, y := 0, width := 0, height := 0.
|
||||
}
|
||||
|
||||
class X11.Event(Object)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
class X11.KeyEvent(X11.Event)
|
||||
{
|
||||
}
|
||||
|
||||
pooldic X11.MouseButton
|
||||
{
|
||||
LEFT := 1,
|
||||
MIDDLE := 2,
|
||||
RIGHT := 3
|
||||
}
|
||||
|
||||
class X11.MouseEvent(X11.Event)
|
||||
{
|
||||
var(#get,#set)
|
||||
x := 0,
|
||||
y := 0,
|
||||
button := 0. // X11.MouseButton
|
||||
}
|
||||
|
||||
class X11.MouseWheelEvent(X11.Event)
|
||||
{
|
||||
var(#get,#set)
|
||||
x := 0,
|
||||
y := 0,
|
||||
amount := 0.
|
||||
}
|
||||
|
||||
class X11.ExposeEvent(X11.Event)
|
||||
{
|
||||
var(#get,#set)
|
||||
x := 0,
|
||||
y := 0,
|
||||
width := 0,
|
||||
height := 0.
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// X11 Context
|
||||
// ---------------------------------------------------------------------------
|
||||
pooldic X11.GCLineStyle
|
||||
{
|
||||
SOLID := 0,
|
||||
ON_OFF_DASH := 1,
|
||||
DOUBLE_DASH := 2
|
||||
}
|
||||
|
||||
pooldic X11.GCFillStyle
|
||||
{
|
||||
SOLID := 0,
|
||||
TILED := 1,
|
||||
STIPPLED := 2,
|
||||
OPAQUE_STIPPLED := 3
|
||||
}
|
||||
|
||||
class X11.GC(Object)
|
||||
{
|
||||
// note these fields must match the x11_gc_t structure defined in _x11.h
|
||||
|
||||
var(#get) widget := nil, gcHandle := nil.
|
||||
|
||||
var(#get,#set)
|
||||
foreground := 0,
|
||||
background := 1,
|
||||
lineWidth := 1,
|
||||
lineStyle := X11.GCLineStyle.SOLID,
|
||||
fillStyle := X11.GCFillStyle.SOLID,
|
||||
fontName := nil.
|
||||
|
||||
var fontPtr := nil.
|
||||
var fontSet := nil.
|
||||
|
||||
method(#class) new
|
||||
{
|
||||
self messageProhibited: #new.
|
||||
}
|
||||
|
||||
method(#class) new: widget
|
||||
{
|
||||
^(super new) __make_gc_on: widget
|
||||
}
|
||||
|
||||
method __make_gc_on: widget
|
||||
{
|
||||
| gc |
|
||||
widget displayServer dump.
|
||||
widget windowHandle dump.
|
||||
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 drawRectangle(x, y, width, height)
|
||||
{
|
||||
^self.widget displayServer _draw_rectangle (self.widget windowHandle, self.gcHandle, x, y, width, height).
|
||||
}
|
||||
|
||||
method fillRectangle(x, y, width, height)
|
||||
{
|
||||
^self.widget displayServer _fill_rectangle (self.widget windowHandle, self.gcHandle, x, y, width, height).
|
||||
}
|
||||
|
||||
method drawString(x, y, string)
|
||||
{
|
||||
^self.widget displayServer _draw_string (self, x, y, string).
|
||||
}
|
||||
|
||||
method dispose
|
||||
{
|
||||
if (self.gcHandle notNil)
|
||||
{
|
||||
self.widget displayServer _destroy_gc(self).
|
||||
self.gcHandle := nil.
|
||||
}.
|
||||
}
|
||||
|
||||
method apply
|
||||
{
|
||||
if (self.gcHandle notNil)
|
||||
{
|
||||
if (self.widget displayServer _apply_gc (self) isError)
|
||||
{
|
||||
X11.Exception signal: "Cannot apply GC settings"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// X11 Widgets
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class X11.Widget(Object)
|
||||
{
|
||||
var(#get) windowHandle := nil.
|
||||
|
||||
var(#get,#set)
|
||||
parent := nil,
|
||||
x := 0,
|
||||
y := 0,
|
||||
width := 0,
|
||||
height := 0,
|
||||
fgcolor := 16r1188FF,
|
||||
bgcolor := 0,
|
||||
realized := false.
|
||||
|
||||
method displayServer
|
||||
{
|
||||
if (self.parent isNil) { ^nil }.
|
||||
^self.parent displayServer.
|
||||
}
|
||||
|
||||
method parentWindowHandle
|
||||
{
|
||||
if (self.parent isNil) { ^nil }.
|
||||
^self.parent windowHandle.
|
||||
}
|
||||
|
||||
method realize
|
||||
{
|
||||
| disp wind |
|
||||
|
||||
if (self.windowHandle notNil) { ^self }.
|
||||
|
||||
disp := self displayServer.
|
||||
if (disp isNil)
|
||||
{
|
||||
X11.Exception signal: "Cannot realize a widget not added to a display server"
|
||||
}.
|
||||
|
||||
wind := disp __create_window(self parentWindowHandle, self.x, self.y, self.width, self.height, self.fgcolor, self.bgcolor, self).
|
||||
if (wind isError)
|
||||
{
|
||||
self.Exception signal: "Cannot create widget window".
|
||||
}.
|
||||
|
||||
self.windowHandle := wind.
|
||||
}
|
||||
|
||||
|
||||
method dispose
|
||||
{
|
||||
| disp |
|
||||
|
||||
'Widget dispose XXXXXXXXXXXXXX' dump.
|
||||
disp := self displayServer.
|
||||
if (disp notNil)
|
||||
{
|
||||
if (self.windowHandle notNil)
|
||||
{
|
||||
disp __destroy_window (self.windowHandle).
|
||||
self.windowHandle := nil.
|
||||
}.
|
||||
}
|
||||
}
|
||||
|
||||
method onPaintEvent: paint_event
|
||||
{
|
||||
}
|
||||
|
||||
method onMouseButtonEvent: event
|
||||
{
|
||||
}
|
||||
|
||||
method onKeyEvent: event
|
||||
{
|
||||
}
|
||||
|
||||
method onCloseEvent
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class X11.Label(X11.Widget)
|
||||
{
|
||||
var(#get) text := ''.
|
||||
|
||||
method text: text
|
||||
{
|
||||
self.text := text.
|
||||
if (self windowHandle notNil) { self onPaintEvent: nil }
|
||||
}
|
||||
|
||||
method realize
|
||||
{
|
||||
super realize.
|
||||
}
|
||||
|
||||
method dispose
|
||||
{
|
||||
'Label dispose XXXXXXXXXXXXXX' dump.
|
||||
super dispose.
|
||||
}
|
||||
|
||||
method onPaintEvent: paint_event
|
||||
{
|
||||
| gc |
|
||||
|
||||
gc := selfns.GC new: self.
|
||||
[
|
||||
gc foreground: self.bgcolor;
|
||||
fontName: '-misc-fixed-medium-r-normal-ko-18-120-100-100-c-180-iso10646-1';
|
||||
apply.
|
||||
gc fillRectangle (0, 0, self.width, self.height).
|
||||
|
||||
gc foreground: self.fgcolor; apply.
|
||||
gc drawRectangle (0, 0, self.width - 1, self.height - 1).
|
||||
|
||||
gc drawString(10, 10, self.text).
|
||||
] ensure: [ gc dispose ]
|
||||
}
|
||||
}
|
||||
|
||||
class X11.Button(X11.Label)
|
||||
{
|
||||
method onMouseButtonEvent: llevent
|
||||
{
|
||||
| type x |
|
||||
type := llevent type.
|
||||
if (type == X11.LLEventType.BUTTON_PRESS)
|
||||
{
|
||||
x := self.fgcolor.
|
||||
self.fgcolor := self.bgcolor.
|
||||
self.bgcolor := x.
|
||||
self onPaintEvent: llevent.
|
||||
}
|
||||
elif (type == X11.LLEventType.BUTTON_RELEASE)
|
||||
{
|
||||
x := self.fgcolor.
|
||||
self.fgcolor := self.bgcolor.
|
||||
self.bgcolor := x.
|
||||
self onPaintEvent: llevent.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class X11.Composite(X11.Widget)
|
||||
{
|
||||
var children.
|
||||
|
||||
method initialize
|
||||
{
|
||||
self.children := LinkedList new.
|
||||
}
|
||||
|
||||
method add: widget
|
||||
{
|
||||
if (widget parent notNil)
|
||||
{
|
||||
selfns.Exception signal: "Cannot add an already added widget".
|
||||
}.
|
||||
|
||||
self.children addLast: widget.
|
||||
widget parent: self.
|
||||
}
|
||||
|
||||
method remove: widget
|
||||
{
|
||||
| link |
|
||||
// see the dispose: function about the following condition checks
|
||||
// commented out
|
||||
//if (widget parent notNil)
|
||||
//{
|
||||
// if (widget parent ~~ self)
|
||||
// {
|
||||
// selfns.Exception signal: "Cannot remove an unknown widget"
|
||||
// }.
|
||||
link := self.children findIdenticalLink: widget.
|
||||
self.children removeLink: link.
|
||||
widget parent: nil.
|
||||
//}.
|
||||
}
|
||||
|
||||
method childrenCount
|
||||
{
|
||||
^self.children size
|
||||
}
|
||||
|
||||
method realize
|
||||
{
|
||||
super realize.
|
||||
[
|
||||
self.children do: [:child | child realize ].
|
||||
] on: System.Exception do: [:ex |
|
||||
self dispose.
|
||||
ex pass
|
||||
].
|
||||
}
|
||||
|
||||
method dispose
|
||||
{
|
||||
self.children do: [:child |
|
||||
child dispose.
|
||||
|
||||
// some children(e.g. Shell) may remove itself from the parent.
|
||||
// after disposal, the parent is reset to nil. so make a check
|
||||
// before calling the removal method.
|
||||
// if the check is made here, the remove: method doesn't need
|
||||
// to check if the child is valid. see the lines commented out
|
||||
// in the method.
|
||||
if (child parent == self) { self remove: child }.
|
||||
].
|
||||
super dispose.
|
||||
}
|
||||
|
||||
method onPaintEvent: event
|
||||
{
|
||||
super onPaintEvent: event.
|
||||
self.children do: [:child |
|
||||
// TODO: adjust event relative to each child...
|
||||
child onPaintEvent: event.
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
class X11.Shell(X11.Composite)
|
||||
{
|
||||
var(#get) title := ''.
|
||||
var(#get,#set) displayServer := nil.
|
||||
|
||||
method new: title
|
||||
{
|
||||
self.title := title.
|
||||
}
|
||||
|
||||
//// TODO:
|
||||
//// redefine x:, y:, width:, height: to return actual geometry values...
|
||||
////
|
||||
|
||||
method title: title
|
||||
{
|
||||
self.title := title.
|
||||
if (self.windowHandle notNil)
|
||||
{
|
||||
// set window title of this window.
|
||||
}
|
||||
}
|
||||
|
||||
method realize
|
||||
{
|
||||
'SHELL REALIZE XXXXXXXXXXX' dump.
|
||||
super realize.
|
||||
}
|
||||
|
||||
method dispose
|
||||
{
|
||||
'Shell dispose XXXXXXXXXXXXXX' dump.
|
||||
super dispose.
|
||||
self.displayServer removeShell: self.
|
||||
}
|
||||
|
||||
method onCloseEvent
|
||||
{
|
||||
'ON CLOSE EVENT .............' dump.
|
||||
self dispose.
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// X11 server
|
||||
// ---------------------------------------------------------------------------
|
||||
extend X11
|
||||
{
|
||||
method(#class) new
|
||||
{
|
||||
^(super new) __connect_to: nil.
|
||||
}
|
||||
|
||||
method __connect_to: name
|
||||
{
|
||||
if (self _open_display(name) isError)
|
||||
{
|
||||
self.Exception signal: 'cannot open display'
|
||||
}.
|
||||
self.display_base dump.
|
||||
}
|
||||
|
||||
method isConnected
|
||||
{
|
||||
^self.display_base notNil
|
||||
}
|
||||
|
||||
method dispose
|
||||
{
|
||||
if (self.shell_container notNil)
|
||||
{
|
||||
self.shell_container dispose.
|
||||
self.shell_container := nil.
|
||||
}.
|
||||
|
||||
if (self.display_base notNil)
|
||||
{
|
||||
self _close_display.
|
||||
self.display_base := nil.
|
||||
}.
|
||||
}
|
||||
|
||||
method initialize
|
||||
{
|
||||
super initialize.
|
||||
|
||||
self.shell_container := self.Composite new.
|
||||
self.window_registry := System.Dictionary new: 100.
|
||||
|
||||
/*
|
||||
|
||||
self.llevent_blocks := System.Dictionary new.
|
||||
self.llevent_blocks
|
||||
at: self.LLEventType.KEY_PRESS put: #__handle_key_event:on:;
|
||||
at: self.LLEventType.KEY_RELEASE put: #__handle_key_event:on:;
|
||||
at: self.LLEventType.BUTTON_PRESS put: #__handle_button_event:on:;
|
||||
at: self.LLEventType.BUTTON_RELEASE put: #__handle_button_event:on:;
|
||||
at: self.LLEventType.MOTION_NOTIFY put: #__handle_notify:on:;
|
||||
at: self.LLEventType.ENTER_NOTIFY put: #__handle_notify:on:;
|
||||
at: self.LLEventType.LEAVE_NOTIFY put: #__handle_notify:on:;
|
||||
at: self.LLEventType.EXPOSE put: #__handle_expose:on:;
|
||||
at: self.LLEventType.DESTROY_NOTIFY put: #__handle_destroy_notify:on:;
|
||||
at: self.LLEventType.CONFIGURE_NOTIFY put: #__handle_configure_notify:on:;
|
||||
at: self.LLEventType.CLIENT_MESSAGE put: #__handle_client_message:on:.
|
||||
*/
|
||||
self.llevent_blocks := ##{
|
||||
self.LLEventType.KEY_PRESS -> #__handle_key_event:on:,
|
||||
self.LLEventType.KEY_RELEASE -> #__handle_key_event:on:,
|
||||
self.LLEventType.BUTTON_PRESS -> #__handle_button_event:on:,
|
||||
self.LLEventType.BUTTON_RELEASE -> #__handle_button_event:on:,
|
||||
self.LLEventType.MOTION_NOTIFY -> #__handle_notify:on:,
|
||||
self.LLEventType.ENTER_NOTIFY -> #__handle_notify:on:,
|
||||
self.LLEventType.LEAVE_NOTIFY -> #__handle_notify:on:,
|
||||
self.LLEventType.EXPOSE -> #__handle_expose:on:,
|
||||
self.LLEventType.DESTROY_NOTIFY -> #__handle_destroy_notify:on:,
|
||||
self.LLEventType.CONFIGURE_NOTIFY -> #__handle_configure_notify:on:,
|
||||
self.LLEventType.CLIENT_MESSAGE -> #__handle_client_message:on:,
|
||||
self.LLEventType.SHELL_CLOSE -> #__handle_shell_close:on:
|
||||
}.
|
||||
}
|
||||
|
||||
method addShell: shell
|
||||
{
|
||||
if (shell displayServer isNil)
|
||||
{
|
||||
self.shell_container add: shell.
|
||||
shell displayServer: self.
|
||||
}
|
||||
}
|
||||
|
||||
method removeShell: shell
|
||||
{
|
||||
if (shell displayServer notNil)
|
||||
{
|
||||
self.shell_container remove: shell.
|
||||
shell displayServer: nil.
|
||||
}
|
||||
}
|
||||
|
||||
method enterEventLoop
|
||||
{
|
||||
if (self.event_loop_sem isNil)
|
||||
{
|
||||
self.event_loop_sem := Semaphore new.
|
||||
self.event_loop_sem signalOnInput: (self _get_fd).
|
||||
self.event_loop_proc := [
|
||||
[
|
||||
| llevtbuf llevent |
|
||||
|
||||
self.event_loop_exit_req := false.
|
||||
llevtbuf := X11.LLEvent new.
|
||||
while (self.shell_container childrenCount > 0)
|
||||
{
|
||||
'Waiting for X11 event...' dump.
|
||||
if (self.event_loop_exit_req) { break }.
|
||||
self.event_loop_sem wait.
|
||||
if (self.event_loop_exit_req) { break }.
|
||||
|
||||
while ((llevent := self _get_llevent(llevtbuf)) notNil)
|
||||
{
|
||||
if (llevent isError)
|
||||
{
|
||||
//System logNl: ('Error while getting a event from server ' & self.cid asString).
|
||||
self.event_loop_exit_req := true.
|
||||
break.
|
||||
}
|
||||
else
|
||||
{
|
||||
self __dispatch_llevent: llevent.
|
||||
}.
|
||||
}.
|
||||
}.
|
||||
] ensure: [
|
||||
'CLOSING X11 EVENT LOOP' dump.
|
||||
//self.event_loop_sem signal. // in case the process is suspended in self.event_loop_sem wait.
|
||||
self.event_loop_sem unsignal.
|
||||
// TODO: LOOK HERE FOR RACE CONDITION with exitEventLoop.
|
||||
self.event_loop_sem := nil.
|
||||
self.event_loop_proc := nil.
|
||||
|
||||
[ self dispose ] on: Exception do: [:ex | ("WARNING: dispose failure...." & ex messageText) dump ].
|
||||
]
|
||||
] newProcess.
|
||||
|
||||
self.event_loop_proc resume.
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
// TOOD: exitEventLoop to terminate the whole process by force or
|
||||
// requestToExit to signal process after having set a flag?
|
||||
// what is better?
|
||||
method exitEventLoop
|
||||
{
|
||||
if (self.event_loop_sem notNil)
|
||||
{
|
||||
// TODO: handle race-condition with the part maked 'LOOK HERE FOR RACE CONDITION'
|
||||
self.event_loop_proc terminate.
|
||||
self.event_loop_proc := nil.
|
||||
self.event_loop_sem := nil.
|
||||
}
|
||||
}
|
||||
|
||||
method requestToExit
|
||||
{
|
||||
self.event_loop_exit_req := true.
|
||||
if (self.event_loop_sem notNil) { self.event_loop_sem signal }.
|
||||
}
|
||||
/////////////////////////////////////////
|
||||
|
||||
method __dispatch_llevent: llevent
|
||||
{
|
||||
| widget mthname |
|
||||
|
||||
widget := self.window_registry at: llevent window ifAbsent: [
|
||||
System logNl: 'Event on unknown widget - ' & (llevent window asString).
|
||||
^nil
|
||||
].
|
||||
|
||||
mthname := self.llevent_blocks at: llevent type ifAbsent: [
|
||||
System logNl: 'Unknown event type ' & (llevent type asString).
|
||||
^nil
|
||||
].
|
||||
|
||||
^self perform(mthname, llevent, widget).
|
||||
}
|
||||
|
||||
method __handle_notify: llevent on: widget
|
||||
{
|
||||
}
|
||||
|
||||
method __handle_expose: llevent on: widget
|
||||
{
|
||||
widget onPaintEvent: llevent
|
||||
}
|
||||
|
||||
method __handle_button_event: llevent on: widget
|
||||
{
|
||||
widget onMouseButtonEvent: llevent
|
||||
}
|
||||
|
||||
method __handle_destroy_notify: event on: widget
|
||||
{
|
||||
}
|
||||
|
||||
method __handle_configure_notify: event on: widget
|
||||
{
|
||||
widget onPaintEvent: event.
|
||||
}
|
||||
|
||||
method __handle_client_message: event on: widget
|
||||
{
|
||||
widget close: event.
|
||||
}
|
||||
|
||||
method __handle_key_event: llevent on: widget
|
||||
{
|
||||
widget onKeyEvent: llevent
|
||||
}
|
||||
|
||||
method __handle_shell_close: llevent on: widget
|
||||
{
|
||||
widget onCloseEvent.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Fx(Object)
|
||||
{
|
||||
var(#class) X := 20.
|
||||
var x.
|
||||
|
||||
method initialize
|
||||
{
|
||||
self.X := self.X + 1.
|
||||
self.x := self.X.
|
||||
self addToBeFinalized.
|
||||
}
|
||||
|
||||
method finalize
|
||||
{
|
||||
System logNl: ('Greate... FX instance finalized' & self.x asString).
|
||||
}
|
||||
}
|
||||
|
||||
class MyObject(Object)
|
||||
{
|
||||
var disp1, disp2, shell1, shell2, shell3.
|
||||
var on_sig.
|
||||
|
||||
method initialize
|
||||
{
|
||||
self.on_sig := [:sig |
|
||||
self.disp1 requestToExit.
|
||||
self.disp2 requestToExit.
|
||||
].
|
||||
}
|
||||
|
||||
method main1
|
||||
{
|
||||
| comp1 |
|
||||
|
||||
self.disp1 := X11 new.
|
||||
self.disp2 := X11 new.
|
||||
|
||||
shell1 := (X11.Shell new title: 'Shell 1').
|
||||
shell2 := (X11.Shell new title: 'Shell 2').
|
||||
|
||||
shell3 := (X11.Shell new title: 'Shell 3').
|
||||
|
||||
shell1 x: 10; y: 20; width: 500; height: 500.
|
||||
shell2 x: 200; y: 200; width: 200; height: 200.
|
||||
shell3 x: 500; y: 200; width: 200; height: 200.
|
||||
|
||||
self.disp1 addShell: shell1.
|
||||
self.disp1 addShell: shell2.
|
||||
self.disp2 addShell: shell3.
|
||||
|
||||
comp1 := X11.Composite new x: 10; y: 10; width: 400; height: 500.
|
||||
self.shell1 add: comp1.
|
||||
|
||||
comp1 add: (X11.Label new text: '간다'; width: 100; height: 100).
|
||||
//comp1 add: (X11.Label new text: 'Going'; width: 100; height: 100).
|
||||
comp1 add: (X11.Label new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
|
||||
// self.shell1 add: (X11.Label new text: 'xxxxxxxx'; width: 100; height: 100).
|
||||
self.shell1 add: (X11.Button new text: '크레용crayon'; x: 90; y: 90; width: 100; height: 100).
|
||||
//self.shell1 add: (X11.Button new text: 'CRAYON crayon'; x: 90; y: 90; width: 100; height: 100).
|
||||
|
||||
self.shell2 add: (X11.Button new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
|
||||
self.shell3 add: (X11.Button new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
|
||||
self.shell1 realize.
|
||||
self.shell2 realize.
|
||||
self.shell3 realize.
|
||||
|
||||
System installSignalHandler: self.on_sig.
|
||||
|
||||
self.disp1 enterEventLoop. // this is not a blocking call. it spawns another process.
|
||||
self.disp2 enterEventLoop.
|
||||
|
||||
comp1 := Fx new.
|
||||
Fx new.
|
||||
comp1 := Fx new.
|
||||
Fx new.
|
||||
|
||||
while (self.disp1 isConnected or self.disp2 isConnected) { System sleepForSecs: 1 }.
|
||||
}
|
||||
|
||||
/*
|
||||
method exitEventLoops
|
||||
{
|
||||
if (self.disp2 notNil) { self.disp2 exitEventLoop }.
|
||||
if (self.disp1 notNil) { self.disp1 exitEventLoop }.
|
||||
}
|
||||
*/
|
||||
|
||||
method(#class) main
|
||||
{
|
||||
// this method returns immediately while having forked two processes with X11 event loops.
|
||||
^self new main1
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user