added more X11 code related to GC handling

This commit is contained in:
hyunghwan.chung 2017-06-29 15:04:35 +00:00
parent a2877ac905
commit d0b38926d4
5 changed files with 518 additions and 174 deletions

View File

@ -7,10 +7,6 @@ class X11(Object) from 'x11'
## definition struct x11_t defined in _x11.h ## definition struct x11_t defined in _x11.h
## --------------------------------------------------------------------- ## ---------------------------------------------------------------------
var display_base := nil. var display_base := nil.
var expose_event.
var key_event.
var mouse_event.
var mouse_wheel_event.
## ===================================================================== ## =====================================================================
var shell_container := nil. var shell_container := nil.
@ -24,16 +20,21 @@ class X11(Object) from 'x11'
method(#primitive) _get_fd. method(#primitive) _get_fd.
method(#primitive) _get_llevent(llevent). method(#primitive) _get_llevent(llevent).
method(#primitive) _create_window(parent_window, x, y, width, height, fgcolor, bgcolor). method(#primitive) _create_window(parent_window_handle, x, y, width, height, fgcolor, bgcolor).
method(#primitive) _destroy_window(window). method(#primitive) _destroy_window(window_handle).
##method(#primitive) _fill_rectangle(window, gc, x, y, width, height). method(#primitive) _create_gc (window_handle).
method(#primitive) _draw_rectangle(window, gc, x, y, width, height). 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 __create_window(parent_window, x, y, width, height, fgcolor, bgcolor, owner) 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 |
w := self _create_window(parent_window, x, y, width, height, fgcolor, bgcolor). w := self _create_window(parent_window_handle, x, y, width, height, fgcolor, bgcolor).
if (w notError) { self.window_registrar at: w put: owner }. if (w notError) { self.window_registrar at: w put: owner }.
^w ^w
} }
@ -141,16 +142,41 @@ class X11.ExposeEvent(X11.Event)
## --------------------------------------------------------------------------- ## ---------------------------------------------------------------------------
## X11 Context ## X11 Context
## --------------------------------------------------------------------------- ## ---------------------------------------------------------------------------
class X11.GraphicsContext(Object) 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) widget := nil, gcHandle := nil.
var(#get,#set) var(#get,#set)
foreground := 0, foreground := 0,
background := 0, background := 1,
lineWidth := 1, lineWidth := 1,
lineStyle := 0, lineStyle := X11.GCLineStyle.SOLID,
fillStyle := 0. fillStyle := X11.GCFillStyle.SOLID,
fontName := nil.
var fontPtr := nil.
method(#class) new
{
self messageProhibited: #new.
}
method(#class) new: widget method(#class) new: widget
{ {
@ -160,20 +186,47 @@ class X11.GraphicsContext(Object)
method __make_gc_on: widget method __make_gc_on: widget
{ {
| gc | | gc |
widget displayServer dump.
widget windowHandle dump.
gc := widget displayServer _create_gc (widget windowHandle). gc := widget displayServer _create_gc (widget windowHandle).
if (gc isError) { selfns.Exception signal: 'Cannot create a graphics context' }. if (gc isError) { selfns.Exception signal: 'Cannot create a graphics context' }.
self.gcHandle := gc. self.gcHandle := gc.
self.widget := widget. 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) method fillRectangle(x, y, width, height)
{ {
^self.widget displayServer _fill_rectangle (self.widget windowHandle, self.gcHandle, x, y, width, height). ^self.widget displayServer _fill_rectangle (self.widget windowHandle, self.gcHandle, x, y, width, height).
} }
method drawRectangle(x, y, width, height) method drawString(x, y, string)
{ {
^self.widget displayServer _draw_rectangle (self.widget windowHandle, self.gcHandle, x, y, width, height). ^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'
}
}
} }
} }
@ -183,44 +236,71 @@ class X11.GraphicsContext(Object)
class X11.Widget(Object) class X11.Widget(Object)
{ {
var(#get) windowHandle := nil.
var(#get,#set) var(#get,#set)
parent := nil, parent := nil,
x := 0, x := 0,
y := 0, y := 0,
width := 0, width := 0,
height := 0, height := 0,
fgcolor := 0, fgcolor := 16r1188FF,
bgcolor := 0, bgcolor := 0,
realized := false. realized := false.
method displayServer method displayServer
{ {
if (self.parent isNil) { ^nil }. if (self.parent isNil) { ^nil }.
^self.parent displayServer. ^self.parent displayServer.
} }
method windowHandle method parentWindowHandle
{ {
(* 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 }. if (self.parent isNil) { ^nil }.
^self.parent windowHandle. ^self.parent windowHandle.
} }
method realize
method realize { }
method dispose
{ {
'Widget dispose XXXXXXXXXXXXXX' dump. | 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 onPaintEvent: paint_event
{ {
System logNl: 'Widget...... onPaintEvent YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY.'.
} }
method onButtonEvent: event method onButtonEvent: event
@ -232,6 +312,7 @@ class X11.Widget(Object)
} }
} }
class X11.Label(X11.Widget) class X11.Label(X11.Widget)
{ {
var(#get) text := ''. var(#get) text := ''.
@ -242,20 +323,9 @@ class X11.Label(X11.Widget)
if (self windowHandle notNil) { self onPaintEvent: nil } if (self windowHandle notNil) { self onPaintEvent: nil }
} }
method onPaintEvent: paint_event
{
| 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 method realize
{ {
## if i want to use a window to represent it, it must create window here. super realize.
## otherwise, do other works in onPaintEvent:???
} }
method dispose method dispose
@ -263,6 +333,25 @@ System logNl: 'LABEL GC.......'.
'Label dispose XXXXXXXXXXXXXX' dump. 'Label dispose XXXXXXXXXXXXXX' dump.
super dispose. super dispose.
} }
method onPaintEvent: paint_event
{
| gc |
System logNl: 'LABEL GC...... onPaintEvent YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY.'.
gc := selfns.GC new: self.
[
gc foreground: self.fgcolor;
fontName: '-misc-fixed-medium-r-normal-ko-18-120-100-100-c-180-iso10646-1';
apply.
gc drawRectangle (0, 0, self.width - 1, self.height - 1).
##gc fillRectangle (0, 0, self.width, self.height).
##gc drawLine (0, y, CTRLWIDE, y).
##gc drawLine (0, y + CHIGH + 4, CTRLWIDE, Y+CHIGH+4).
gc drawString(10, 10, self.text).
] ensure: [ gc dispose ]
}
} }
class X11.Composite(X11.Widget) class X11.Composite(X11.Widget)
@ -303,13 +392,33 @@ class X11.Composite(X11.Widget)
^self.children size ^self.children size
} }
method realize
{
super realize.
[
self.children do: [:child | child realize ].
] on: System.Exception do: [:ex |
self dispose.
ex pass
].
}
method dispose method dispose
{ {
'Composite dispose XXXXXXXXXXXXXX' dump. 'Composite dispose XXXXXXXXXXXXXX' dump.
super dispose.
self.children do: [:child | self.children do: [:child |
child dispose. child dispose.
self remove: child. 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.
] ]
} }
} }
@ -318,13 +427,16 @@ class X11.Shell(X11.Composite)
{ {
var(#get) title := ''. var(#get) title := ''.
var(#get,#set) displayServer := nil. var(#get,#set) displayServer := nil.
var(#get) windowHandle := nil.
method new: title method new: title
{ {
self.title := title. self.title := title.
} }
#### TODO:
#### redefine x:, y:, width:, height: to return actual geometry values...
####
method title: title method title: title
{ {
self.title := title. self.title := title.
@ -336,51 +448,16 @@ class X11.Shell(X11.Composite)
method realize method realize
{ {
| wind | 'SHELL REALIZE XXXXXXXXXXX' dump.
super realize.
if (self.windowHandle notNil) { ^self }.
if (self.displayServer isNil)
{
## not added to a display server.
X11.Exception signal: 'Cannot realize a shell not added to a display server'
}.
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.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 onPaintEvent: nil.
} }
method dispose method dispose
{ {
'Shell dispose XXXXXXXXXXXXXX' dump. 'Shell dispose XXXXXXXXXXXXXX' dump.
if (self.displayServer notNil)
{
if (self.windowHandle notNil)
{
super dispose. super dispose.
self.displayServer __destroy_window (self.windowHandle).
self.windowHandle := nil.
}.
self.displayServer removeShell: self. self.displayServer removeShell: self.
} }
}
method onCloseEvent method onCloseEvent
{ {
@ -404,8 +481,7 @@ extend X11
if (self _open_display(name) isError) if (self _open_display(name) isError)
{ {
self.Exception signal: 'cannot open display' self.Exception signal: 'cannot open display'
} }.
.
self.display_base dump. self.display_base dump.
} }
@ -420,7 +496,7 @@ extend X11
if (self.display_base notNil) if (self.display_base notNil)
{ {
self _close_display. self _close_display.
##self.display_base := nil. self.display_base := nil.
}. }.
} }
@ -428,11 +504,6 @@ extend X11
{ {
super initialize. super initialize.
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.shell_container := self.Composite new.
self.window_registrar := System.Dictionary new: 100. self.window_registrar := System.Dictionary new: 100.
@ -519,11 +590,13 @@ extend X11
}. }.
}. }.
'CLOSING X11 EVENT LOOP' dump.
Processor unsignal: self.event_loop_sem. Processor unsignal: self.event_loop_sem.
self.event_loop_sem := nil. self.event_loop_sem := nil.
self dispose. self dispose.
'CLOSING X11 EVENT LOOP' dump.
] fork. ] fork.
} }
} }
@ -561,7 +634,6 @@ extend X11
^nil ^nil
}. }.
(llevent window asString) dump.
^self perform (mthname, llevent, widget). ^self perform (mthname, llevent, widget).
} }
@ -571,6 +643,7 @@ extend X11
method __handle_expose: llevent on: widget method __handle_expose: llevent on: widget
{ {
widget onPaintEvent: llevent
} }
method __handle_button_event: event on: widget method __handle_button_event: event on: widget
@ -583,6 +656,7 @@ extend X11
method __handle_configure_notify: event on: widget method __handle_configure_notify: event on: widget
{ {
widget onPaintEvent: event.
} }
method __handle_client_message: event on: widget method __handle_client_message: event on: widget
@ -609,6 +683,7 @@ class MyObject(Object)
method main1 method main1
{ {
| comp1 |
self.disp1 := X11 new. self.disp1 := X11 new.
self.disp2 := X11 new. self.disp2 := X11 new.
@ -617,7 +692,7 @@ class MyObject(Object)
shell3 := (X11.Shell new title: 'Shell 3'). shell3 := (X11.Shell new title: 'Shell 3').
shell1 x: 10; y: 20; width: 100; height: 100. shell1 x: 10; y: 20; width: 500; height: 500.
shell2 x: 200; y: 200; width: 200; height: 200. shell2 x: 200; y: 200; width: 200; height: 200.
shell3 x: 500; y: 200; width: 200; height: 200. shell3 x: 500; y: 200; width: 200; height: 200.
@ -625,7 +700,16 @@ class MyObject(Object)
self.disp1 addShell: shell2. self.disp1 addShell: shell2.
self.disp2 addShell: shell3. self.disp2 addShell: shell3.
self.shell1 add: (X11.Label new text: 'xxxxxxxx'). 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: '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.Label new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
self.shell2 add: (X11.Label new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
self.shell3 add: (X11.Label new text: 'crayon'; x: 90; y: 90; width: 100; height: 100).
self.shell1 realize. self.shell1 realize.
self.shell2 realize. self.shell2 realize.
self.shell3 realize. self.shell3 realize.

View File

@ -92,6 +92,7 @@
# include <unistd.h> # include <unistd.h>
# include <fcntl.h> # include <fcntl.h>
# include <locale.h>
# if defined(USE_THREAD) # if defined(USE_THREAD)
# include <pthread.h> # include <pthread.h>
@ -1758,6 +1759,11 @@ int main (int argc, char* argv[])
} }
#endif #endif
if (!setlocale (LC_ALL, ""))
{
fprintf (stderr, "Warning: setlocale() error. carrying on.\n");
}
memset (&vmprim, 0, MOO_SIZEOF(vmprim)); memset (&vmprim, 0, MOO_SIZEOF(vmprim));
vmprim.dl_open = dl_open; vmprim.dl_open = dl_open;
vmprim.dl_close = dl_close; vmprim.dl_close = dl_close;

View File

@ -276,9 +276,13 @@
typedef char moo_bch_t; typedef char moo_bch_t;
typedef int moo_bci_t; typedef int moo_bci_t;
#define MOO_SIZEOF_BCH_T MOO_SIZEOF_CHAR
#define MOO_SIZEOF_BCI_T MOO_SIZEOF_INT
typedef moo_uint16_t moo_uch_t; /* TODO ... wchar_t??? */ typedef moo_uint16_t moo_uch_t; /* TODO ... wchar_t??? */
typedef moo_int32_t moo_uci_t; typedef moo_int32_t moo_uci_t;
#define MOO_SIZEOF_UCH_T 2
#define MOO_SIZEOF_UCI_T 4
typedef moo_uint8_t moo_oob_t; typedef moo_uint8_t moo_oob_t;

View File

@ -38,13 +38,6 @@
#define MC MOO_METHOD_CLASS #define MC MOO_METHOD_CLASS
#define MI MOO_METHOD_INSTANCE #define MI MOO_METHOD_INSTANCE
typedef struct x11_win_t x11_win_t;
struct x11_win_t
{
Display* disp;
Window wind;
};
typedef struct x11_llevent_t* oop_x11_llevent_t; typedef struct x11_llevent_t* oop_x11_llevent_t;
struct x11_llevent_t struct x11_llevent_t
{ {
@ -54,16 +47,41 @@ struct x11_llevent_t
moo_oop_t x, y, width, height; moo_oop_t x, y, width, height;
}; };
typedef struct x11_gc_t* oop_x11_gc_t;
struct x11_gc_t
{
MOO_OBJ_HEADER;
moo_oop_t widget;
moo_oop_t gc_handle;
moo_oop_t foreground;
moo_oop_t background;
moo_oop_t line_width;
moo_oop_t line_style;
moo_oop_t fill_style;
moo_oop_t font_name;
moo_oop_t font_ptr;
};
typedef struct x11_widget_t* oop_x11_widget_t;
struct x11_widget_t
{
MOO_OBJ_HEADER;
moo_oop_t window_handle; /* SmallInteger */
moo_oop_t parent;
/* more fields below */
};
typedef struct x11_t* oop_x11_t; typedef struct x11_t* oop_x11_t;
struct x11_t struct x11_t
{ {
MOO_OBJ_HEADER; MOO_OBJ_HEADER;
moo_oop_t display; /* SMPTR of Display */ moo_oop_t display; /* SMPTR of Display */
moo_oop_t expose_event;
moo_oop_t key_event;
moo_oop_t mouse_event;
/* in fact, there are more fields */ /* in fact, there are more fields */
}; };
@ -75,8 +93,6 @@ struct x11_trailer_t
Atom wm_delete_window; Atom wm_delete_window;
}; };
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif

View File

@ -27,6 +27,7 @@
#include "_x11.h" #include "_x11.h"
#include <moo-utl.h> #include <moo-utl.h>
#include <X11/Xutil.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
@ -37,6 +38,38 @@ struct x11_modctx_t
moo_oop_class_t x11_class; moo_oop_class_t x11_class;
}; };
/* TODO: bchars_to_xchar2bstr??? */
static XChar2b* uchars_to_xchar2bstr (moo_t* moo, const moo_uch_t* inptr, moo_oow_t inlen, moo_oow_t* outlen)
{
moo_uch_t uch;
const moo_uch_t* endptr;
XChar2b* outbuf, * outptr;
outbuf = moo_allocmem (moo, (inlen + 1) * MOO_SIZEOF(*outptr));
if (!outbuf) return MOO_NULL;
outptr = outbuf;
endptr = inptr + inlen;
while (inptr < endptr)
{
uch = *inptr++;
#if (MOO_SIZEOF_UCH_T > 2)
if (uch > 0xFFFF) uc = 0xFFFD; /* unicode replacement character */
#endif
outptr->byte1 = (uch >> 8) & 0xFF;
outptr->byte2 = uch & 0xFF;
outptr++;
}
outptr->byte1 = 0;
outptr->byte2 = 0;
if (outlen) *outlen = outptr - outbuf;
return outbuf;
}
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
static moo_pfrc_t pf_open_display (moo_t* moo, moo_ooi_t nargs) static moo_pfrc_t pf_open_display (moo_t* moo, moo_ooi_t nargs)
{ {
@ -181,7 +214,8 @@ static moo_pfrc_t pf_get_llevent (moo_t* moo, moo_ooi_t nargs)
e->window = MOO_SMOOI_TO_OOP(0); e->window = MOO_SMOOI_TO_OOP(0);
/* if the following is going to trigger GC directly or indirectly, /* if the following is going to trigger GC directly or indirectly,
* e must be proteced with moo_pushtmp() first */ * e must be proteced with moo_pushtmp().
* also x11, tr must be refetched from the stack. */
switch (event->type) switch (event->type)
{ {
@ -197,11 +231,39 @@ static moo_pfrc_t pf_get_llevent (moo_t* moo, moo_ooi_t nargs)
case Expose: case Expose:
{ {
XRectangle rect;
rect.x = event->xexpose.x;
rect.y = event->xexpose.y;
rect.width = event->xexpose.width;
rect.height = event->xexpose.height;
if (XCheckWindowEvent (disp, event->xexpose.window, ExposureMask, event))
{
Region reg;
/* merge all expose events in the event queue */
reg = XCreateRegion ();
XUnionRectWithRegion (&rect, reg, reg);
do
{
rect.x = event->xexpose.x;
rect.y = event->xexpose.y;
rect.width = event->xexpose.width;
rect.height = event->xexpose.height;
XUnionRectWithRegion (&rect, reg, reg);
}
while (XCheckWindowEvent (disp, event->xexpose.window, ExposureMask, event));
XClipBox (reg, &rect);
XDestroyRegion (reg);
}
e->window = MOO_SMOOI_TO_OOP(event->xexpose.window); e->window = MOO_SMOOI_TO_OOP(event->xexpose.window);
e->x = MOO_SMOOI_TO_OOP(event->xexpose.x); e->x = MOO_SMOOI_TO_OOP(rect.x);
e->y = MOO_SMOOI_TO_OOP(event->xexpose.y); e->y = MOO_SMOOI_TO_OOP(rect.y);
e->width = MOO_SMOOI_TO_OOP(event->xexpose.width); e->width = MOO_SMOOI_TO_OOP(rect.width);
e->height = MOO_SMOOI_TO_OOP(event->xexpose.height); e->height = MOO_SMOOI_TO_OOP(rect.height);
break; break;
} }
@ -255,7 +317,7 @@ static moo_pfrc_t pf_create_window (moo_t* moo, moo_ooi_t nargs)
einval: einval:
MOO_DEBUG0 (moo, "<x11.create_window> Invalid parameters\n"); MOO_DEBUG0 (moo, "<x11.create_window> Invalid parameters\n");
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL);
goto done; return MOO_PF_SUCCESS;
} }
tr = moo_getobjtrailer (moo, (moo_oop_t)x11, MOO_NULL); tr = moo_getobjtrailer (moo, (moo_oop_t)x11, MOO_NULL);
@ -268,19 +330,17 @@ static moo_pfrc_t pf_create_window (moo_t* moo, moo_ooi_t nargs)
scrn = DefaultScreen (disp); scrn = DefaultScreen (disp);
parent = RootWindow (disp, scrn); parent = RootWindow (disp, scrn);
} }
else if (!MOO_OOP_IS_SMOOI(a0)) goto einval;
else else
{ {
moo_oow_t tmpoow;
XWindowAttributes wa; XWindowAttributes wa;
if (moo_inttooow(moo, a0, &tmpoow) <= 0) goto einval;
parent = tmpoow; parent = MOO_OOP_TO_SMOOI(a0);
XGetWindowAttributes (disp, parent, &wa); XGetWindowAttributes (disp, parent, &wa);
MOO_ASSERT (moo, XRootWindowOfScreen(wa.screen) == parent);
scrn = XScreenNumberOfScreen(wa.screen); scrn = XScreenNumberOfScreen(wa.screen);
} }
attrs.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask; /* TODO: accept it as a parameter??? */ attrs.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | ExposureMask/* | StructureNotifyMask*/; /* TODO: accept it as a parameter??? */
attrs.border_pixel = BlackPixel (disp, scrn); /* TODO: use a6 */ attrs.border_pixel = BlackPixel (disp, scrn); /* TODO: use a6 */
attrs.background_pixel = WhitePixel (disp, scrn);/* TODO: use a7 */ attrs.background_pixel = WhitePixel (disp, scrn);/* TODO: use a7 */
@ -299,7 +359,7 @@ static moo_pfrc_t pf_create_window (moo_t* moo, moo_ooi_t nargs)
if (!wind) if (!wind)
{ {
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ESYSERR); MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ESYSERR);
goto done; return MOO_PF_SUCCESS;
} }
if (parent == RootWindow(disp, scrn)) if (parent == RootWindow(disp, scrn))
@ -307,19 +367,18 @@ static moo_pfrc_t pf_create_window (moo_t* moo, moo_ooi_t nargs)
XSetWMProtocols (disp, wind, &tr->wm_delete_window, 1); XSetWMProtocols (disp, wind, &tr->wm_delete_window, 1);
} }
a0 = moo_oowtoint (moo, wind); /*if (!MOO_IN_SMOOI_RANGE ((moo_ooi_t)wind))*/
if (!a0) if (wind > MOO_SMOOI_MAX)
{ {
MOO_STACK_SETRETTOERRNUM (moo, nargs); XDestroyWindow (disp, wind);
goto done; MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ERANGE);
return MOO_PF_SUCCESS;
} }
/* TODO: remvoe this */ XMapWindow (disp, wind);
XMapWindow (disp, wind); XFlush (disp);
XFlush (disp);
MOO_STACK_SETRET (moo, nargs, a0); MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(wind));
done:
return MOO_PF_SUCCESS; return MOO_PF_SUCCESS;
} }
@ -328,12 +387,10 @@ static moo_pfrc_t pf_destroy_window (moo_t* moo, moo_ooi_t nargs)
oop_x11_t x11; oop_x11_t x11;
moo_oop_t a0; moo_oop_t a0;
moo_oow_t wind;
x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs); x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs);
a0 = MOO_STACK_GETARG(moo, nargs, 0); /* window - Integer (Window) */ a0 = MOO_STACK_GETARG(moo, nargs, 0); /* window - Integer (Window) */
if (moo_inttooow(moo, a0, &wind) <= 0) if (!MOO_OOP_IS_SMOOI(a0))
{ {
MOO_DEBUG0 (moo, "<x11.destroy_window> Invalid parameters\n"); MOO_DEBUG0 (moo, "<x11.destroy_window> Invalid parameters\n");
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL);
@ -341,11 +398,13 @@ static moo_pfrc_t pf_destroy_window (moo_t* moo, moo_ooi_t nargs)
else else
{ {
Display* disp; Display* disp;
Window wind;
disp = MOO_OOP_TO_SMPTR(x11->display); disp = MOO_OOP_TO_SMPTR(x11->display);
XUnmapWindow (disp, (Window)wind); wind = MOO_OOP_TO_SMOOI(a0);
XDestroyWindow (disp, (Window)wind);
XFlush (disp); /* TODO: is XFlush() needed here? */ XUnmapWindow (disp, wind);
XDestroyWindow (disp, wind);
MOO_STACK_SETRETTORCV (moo, nargs); MOO_STACK_SETRETTORCV (moo, nargs);
} }
@ -355,96 +414,269 @@ XFlush (disp); /* TODO: is XFlush() needed here? */
static moo_pfrc_t pf_create_gc (moo_t* moo, moo_ooi_t nargs) static moo_pfrc_t pf_create_gc (moo_t* moo, moo_ooi_t nargs)
{ {
Display* disp; Display* disp;
moo_oow_t wind; Window wind;
GC gc;
XWindowAttributes wa;
oop_x11_t x11; oop_x11_t x11;
moo_oop_t a0; moo_oop_t a0;
x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs); x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs);
disp = MOO_OOP_TO_SMPTR(x11); disp = MOO_OOP_TO_SMPTR(x11->display);
a0 = MOO_STACK_GETARG(moo, nargs, 0); /* parent window - Integer or nil (Window) */ a0 = MOO_STACK_GETARG(moo, nargs, 0); /* Window - SmallInteger */
if (moo_inttooow(moo, a0, &wind) <= 0) if (!MOO_OOP_IS_SMOOI(a0))
{ {
MOO_DEBUG0 (moo, "<x11.create_gc> Invalid parameters\n"); MOO_DEBUG0 (moo, "<x11.create_gc> Invalid parameters\n");
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL);
return MOO_PF_SUCCESS;
} }
else
{
GC gc;
/* TODO: copy from default GC(DefaultGC...) explicitly??? */ wind = MOO_OOP_TO_SMOOI(a0);
gc = XCreateGC (disp, wind, 0, MOO_NULL); gc = XCreateGC (disp, wind, 0, MOO_NULL);
if (!MOO_IN_SMPTR_RANGE(gc)) if (!MOO_IN_SMPTR_RANGE(gc))
{ {
MOO_DEBUG0 (moo, "<x11.create_gc> GC pointer not in small pointer range\n"); MOO_DEBUG0 (moo, "<x11.create_gc> GC pointer not in small pointer range\n");
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ERANGE); MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ERANGE);
} return MOO_PF_SUCCESS;
else
{
MOO_STACK_SETRET (moo, nargs, MOO_SMPTR_TO_OOP(gc));
}
} }
/* XGetWindowAttributes (disp, wind, &wa);
XCopyGC (disp, DefaultGC(disp, XScreenNumberOfScreen(wa.screen)), GCForeground | GCBackground | GCLineWidth | GCLineStyle, gc);*/
MOO_STACK_SETRET (moo, nargs, MOO_SMPTR_TO_OOP(gc));
return MOO_PF_SUCCESS; return MOO_PF_SUCCESS;
} }
static moo_pfrc_t pf_destroy_gc (moo_t* moo, moo_ooi_t nargs) static moo_pfrc_t pf_destroy_gc (moo_t* moo, moo_ooi_t nargs)
{ {
oop_x11_t x11; oop_x11_t x11;
moo_oop_t a0; oop_x11_gc_t gc;
Display* disp;
x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs); x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs);
a0 = MOO_STACK_GETARG(moo, nargs, 1); /* GC */ gc = (oop_x11_gc_t)MOO_STACK_GETARG(moo, nargs, 0); /* GC object */
if (!MOO_OOP_IS_SMPTR(a0)) disp = MOO_OOP_TO_SMPTR(x11->display);
if (MOO_OOP_IS_SMPTR(gc->font_ptr))
{ {
MOO_DEBUG0 (moo, "<x11.destroy_gc> Invalid parameters\n"); XFreeFont (disp, MOO_OOP_TO_SMPTR(gc->font_ptr));
gc->font_ptr = moo->_nil;
}
if (MOO_OOP_IS_SMPTR(gc->gc_handle))
{
XFreeGC (disp, MOO_OOP_TO_SMPTR(gc->gc_handle));
gc->gc_handle= moo->_nil;
}
MOO_STACK_SETRETTORCV (moo, nargs);
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_apply_gc (moo_t* moo, moo_ooi_t nargs)
{
oop_x11_t x11;
oop_x11_gc_t a0;
Display* disp;
GC gc;
unsigned long int mask = 0;
XGCValues v;
x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs);
a0 = (oop_x11_gc_t)MOO_STACK_GETARG(moo, nargs, 0);
/* TODO check if a0 is an instance of X11.GC */
if (!MOO_OOP_IS_SMPTR(a0->gc_handle))
{
MOO_DEBUG0 (moo, "<x11.apply_gc> Invalid parameters\n");
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL);
return MOO_PF_SUCCESS;
}
disp = MOO_OOP_TO_SMPTR(x11->display);
gc = MOO_OOP_TO_SMPTR(a0->gc_handle);
if (MOO_OBJ_IS_CHAR_POINTER(a0->font_name) && MOO_OBJ_GET_SIZE(a0->font_name) > 0)
{
XFontStruct* font;
/* TODO: .... use font_name */
font = XLoadQueryFont (disp, "-misc-fixed-medium-r-normal-ko-18-120-100-100-c-180-iso10646-1");
if (font)
{
if (!MOO_IN_SMPTR_RANGE(font))
{
MOO_DEBUG0 (moo, "<x11.apply_gc> Font pointer not in small pointer range\n");
XFreeFont (disp, font);
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ERANGE);
return MOO_PF_SUCCESS;
} }
else else
{ {
Display* disp; XSetFont (disp, gc, font->fid);
GC gc; if (MOO_OOP_IS_SMPTR(a0->font_ptr)) XFreeFont (disp, MOO_OOP_TO_SMPTR(a0->font_ptr));
a0->font_ptr = MOO_SMPTR_TO_OOP(font);
disp = MOO_OOP_TO_SMPTR(x11->display);
gc = MOO_OOP_TO_SMPTR(a0);
XFreeGC (disp, gc);
MOO_STACK_SETRETTORCV (moo, nargs);
} }
}
else
{
MOO_DEBUG2 (moo, "<x11.apply_gc> Cannot laod font - %.*js\n", MOO_OBJ_GET_SIZE(a0->font_name), MOO_OBJ_GET_CHAR_SLOT(a0->font_name));
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ESYSERR);
return MOO_PF_SUCCESS;
}
}
/* TODO: accept mask as an option parameter. then only apply fields that matches this given mask */
if (MOO_OOP_IS_SMOOI(a0->foreground))
{
mask |= GCForeground;
v.foreground = MOO_OOP_TO_SMOOI(a0->foreground);
}
if (MOO_OOP_IS_SMOOI(a0->background))
{
mask |= GCBackground;
v.background = MOO_OOP_TO_SMOOI(a0->background);
}
if (MOO_OOP_IS_SMOOI(a0->line_width))
{
mask |= GCLineWidth;
v.line_width = MOO_OOP_TO_SMOOI(a0->line_width);
}
if (MOO_OOP_IS_SMOOI(a0->line_style))
{
mask |= GCLineStyle;
v.line_style = MOO_OOP_TO_SMOOI(a0->line_style);
}
if (MOO_OOP_IS_SMOOI(a0->fill_style))
{
mask |= GCFillStyle;
v.fill_style = MOO_OOP_TO_SMOOI(a0->fill_style);
}
XChangeGC (disp, gc, mask, &v);
MOO_STACK_SETRETTORCV (moo, nargs);
return MOO_PF_SUCCESS; return MOO_PF_SUCCESS;
} }
static moo_pfrc_t pf_draw_rectangle (moo_t* moo, moo_ooi_t nargs) static moo_pfrc_t pf_draw_rectangle (moo_t* moo, moo_ooi_t nargs)
{ {
oop_x11_t x11;
Display* disp; Display* disp;
moo_oow_t wind, gc;
moo_oop_t a0, a1, a2, a3, a4, a5; moo_oop_t a0, a1, a2, a3, a4, a5;
a0 = MOO_STACK_GETARG(moo, nargs, 0); /* Window */ x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs);
a1 = MOO_STACK_GETARG(moo, nargs, 1); /* GC */ disp = MOO_OOP_TO_SMPTR(x11->display);
a0 = MOO_STACK_GETARG(moo, nargs, 0); /* Window - SmallInteger */
a1 = MOO_STACK_GETARG(moo, nargs, 1); /* GC - SMPTR */
a2 = MOO_STACK_GETARG(moo, nargs, 2); /* x - SmallInteger */ a2 = MOO_STACK_GETARG(moo, nargs, 2); /* x - SmallInteger */
a3 = MOO_STACK_GETARG(moo, nargs, 3); /* y - SmallInteger */ a3 = MOO_STACK_GETARG(moo, nargs, 3); /* y - SmallInteger */
a4 = MOO_STACK_GETARG(moo, nargs, 4); /* width - SmallInteger */ a4 = MOO_STACK_GETARG(moo, nargs, 4); /* width - SmallInteger */
a5 = MOO_STACK_GETARG(moo, nargs, 5); /* height - SmallInteger */ a5 = MOO_STACK_GETARG(moo, nargs, 5); /* height - SmallInteger */
if (!MOO_OOP_IS_SMOOI(a2) || !MOO_OOP_IS_SMOOI(a3) || if (!MOO_OOP_IS_SMOOI(a0) || !MOO_OOP_IS_SMPTR(a1) ||
!MOO_OOP_IS_SMOOI(a4) || !MOO_OOP_IS_SMOOI(a5) || !MOO_OOP_IS_SMOOI(a2) || !MOO_OOP_IS_SMOOI(a3) ||
moo_inttooow(moo, a0, &wind) <= 0 || !MOO_OOP_IS_SMOOI(a4) || !MOO_OOP_IS_SMOOI(a5))
moo_inttooow(moo, a1, &gc) <= 0)
{ {
MOO_DEBUG0 (moo, "<x11.draw_rectangle> Invalid parameters\n"); MOO_DEBUG0 (moo, "<x11.draw_rectangle> Invalid parameters\n");
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL); MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL);
return MOO_PF_SUCCESS; return MOO_PF_SUCCESS;
} }
disp = MOO_OOP_TO_SMPTR(MOO_STACK_GETRCV(moo,nargs)); XDrawRectangle (disp, (Window)MOO_OOP_TO_SMOOI(a0), (GC)MOO_OOP_TO_SMPTR(a1),
XDrawRectangle (disp, (Window)wind, (GC)gc,
MOO_OOP_TO_SMOOI(a2), MOO_OOP_TO_SMOOI(a3), MOO_OOP_TO_SMOOI(a2), MOO_OOP_TO_SMOOI(a3),
MOO_OOP_TO_SMOOI(a4), MOO_OOP_TO_SMOOI(a5)); MOO_OOP_TO_SMOOI(a4), MOO_OOP_TO_SMOOI(a5));
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_fill_rectangle (moo_t* moo, moo_ooi_t nargs)
{
oop_x11_t x11;
Display* disp;
moo_oop_t a0, a1, a2, a3, a4, a5;
x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs);
disp = MOO_OOP_TO_SMPTR(x11->display);
a0 = MOO_STACK_GETARG(moo, nargs, 0); /* Window - SmallInteger */
a1 = MOO_STACK_GETARG(moo, nargs, 1); /* GC - SMPTR */
a2 = MOO_STACK_GETARG(moo, nargs, 2); /* x - SmallInteger */
a3 = MOO_STACK_GETARG(moo, nargs, 3); /* y - SmallInteger */
a4 = MOO_STACK_GETARG(moo, nargs, 4); /* width - SmallInteger */
a5 = MOO_STACK_GETARG(moo, nargs, 5); /* height - SmallInteger */
if (!MOO_OOP_IS_SMOOI(a0) || !MOO_OOP_IS_SMPTR(a1) ||
!MOO_OOP_IS_SMOOI(a2) || !MOO_OOP_IS_SMOOI(a3) ||
!MOO_OOP_IS_SMOOI(a4) || !MOO_OOP_IS_SMOOI(a5))
{
MOO_DEBUG0 (moo, "<x11.fill_rectangle> Invalid parameters\n");
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL);
return MOO_PF_SUCCESS;
}
XFillRectangle (disp, (Window)MOO_OOP_TO_SMOOI(a0), (GC)MOO_OOP_TO_SMPTR(a1),
MOO_OOP_TO_SMOOI(a2), MOO_OOP_TO_SMOOI(a3),
MOO_OOP_TO_SMOOI(a4), MOO_OOP_TO_SMOOI(a5));
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_draw_string (moo_t* moo, moo_ooi_t nargs)
{
oop_x11_t x11;
oop_x11_gc_t gc;
moo_oop_t a1, a2, a3;
Display* disp;
XChar2b* stptr;
moo_oow_t stlen;
int ascent = 0;
x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs);
disp = MOO_OOP_TO_SMPTR(x11->display);
gc = (oop_x11_gc_t)MOO_STACK_GETARG(moo, nargs, 0); /* GC object */
a1 = MOO_STACK_GETARG(moo, nargs, 1); /* x - SmallInteger */
a2 = MOO_STACK_GETARG(moo, nargs, 2); /* y - SmallInteger */
a3 = MOO_STACK_GETARG(moo, nargs, 3); /* string */
/* TODO: check if gc is an instance of X11.GC */
if (!MOO_OOP_IS_SMOOI(a1) || !MOO_OOP_IS_SMOOI(a2) ||
!MOO_OBJ_IS_CHAR_POINTER(a3))
{
MOO_DEBUG0 (moo, "<x11.draw_string> Invalid parameters\n");
MOO_STACK_SETRETTOERROR (moo, nargs, MOO_EINVAL);
return MOO_PF_SUCCESS;
}
/* TODO: draw string chunk by chunk to avoid memory allocation in uchars_to_xchars2bstr */
stptr = uchars_to_xchar2bstr (moo, MOO_OBJ_GET_CHAR_SLOT(a3), MOO_OBJ_GET_SIZE(a3), &stlen);
if (!stptr)
{
MOO_DEBUG0 (moo, "<x11.draw_string> Error in converting a string\n");
MOO_STACK_SETRETTOERRNUM (moo, nargs);
return MOO_PF_SUCCESS;
}
if (MOO_OOP_IS_SMPTR(gc->font_ptr))
{
int direction, descent;
XCharStruct overall;
XTextExtents16 (MOO_OOP_TO_SMPTR(gc->font_ptr), stptr, stlen, &direction, &ascent, &descent, &overall);
}
XDrawString16 (disp, (Window)MOO_OOP_TO_SMOOI(((oop_x11_widget_t)gc->widget)->window_handle), MOO_OOP_TO_SMPTR(gc->gc_handle),
MOO_OOP_TO_SMOOI(a1), MOO_OOP_TO_SMOOI(a2) + ascent, stptr, stlen);
moo_freemem (moo, stptr);
return MOO_PF_SUCCESS; return MOO_PF_SUCCESS;
} }
@ -452,17 +684,19 @@ static moo_pfrc_t pf_draw_rectangle (moo_t* moo, moo_ooi_t nargs)
static moo_pfinfo_t x11_pfinfo[] = static moo_pfinfo_t x11_pfinfo[] =
{ {
{ MI, { '_','a','p','p','l','y','_','g','c','\0' }, 0, { pf_apply_gc, 1, 1 } },
{ MI, { '_','c','l','o','s','e','_','d','i','s','p','l','a','y','\0' }, 0, { pf_close_display, 0, 0 } }, { MI, { '_','c','l','o','s','e','_','d','i','s','p','l','a','y','\0' }, 0, { pf_close_display, 0, 0 } },
{ MI, { '_','c','r','e','a','t','e','_','g','c','\0' }, 0, { pf_create_gc, 1, 1 } }, { MI, { '_','c','r','e','a','t','e','_','g','c','\0' }, 0, { pf_create_gc, 1, 1 } },
{ MI, { '_','c','r','e','a','t','e','_','w','i','n','d','o','w','\0' }, 0, { pf_create_window, 7, 7 } }, { MI, { '_','c','r','e','a','t','e','_','w','i','n','d','o','w','\0' }, 0, { pf_create_window, 7, 7 } },
{ MI, { '_','d','e','s','t','r','o','y','_','g','c','\0' }, 0, { pf_destroy_gc, 1, 1 } }, { MI, { '_','d','e','s','t','r','o','y','_','g','c','\0' }, 0, { pf_destroy_gc, 1, 1 } },
{ MI, { '_','d','e','s','t','r','o','y','_','w','i','n','d','o','w','\0' }, 0, { pf_destroy_window, 1, 1 } }, { MI, { '_','d','e','s','t','r','o','y','_','w','i','n','d','o','w','\0' }, 0, { pf_destroy_window, 1, 1 } },
{ MI, { '_','d','r','a','w','_','r','e','c','t','a','n','g','l','e','\0' }, 0, { pf_draw_rectangle, 6, 6 } }, { MI, { '_','d','r','a','w','_','r','e','c','t','a','n','g','l','e','\0' }, 0, { pf_draw_rectangle, 6, 6 } },
//{ MI, { '_','f','i','l','l','_','r','e','c','t','a','n','g','l','e','\0' }, 0, { pf_fill_rectangle, 6, 6 } }, { MI, { '_','d','r','a','w','_','s','t','r','i','n','g','\0' }, 0, { pf_draw_string, 4, 4 } },
{ MI, { '_','f','i','l','l','_','r','e','c','t','a','n','g','l','e','\0' }, 0, { pf_fill_rectangle, 6, 6 } },
{ MI, { '_','g','e','t','_','f','d','\0' }, 0, { pf_get_fd, 0, 0 } }, { MI, { '_','g','e','t','_','f','d','\0' }, 0, { pf_get_fd, 0, 0 } },
{ MI, { '_','g','e','t','_','l','l','e','v','e','n','t','\0'}, 0, { pf_get_llevent, 1, 1 } }, { MI, { '_','g','e','t','_','l','l','e','v','e','n','t','\0'}, 0, { pf_get_llevent, 1, 1 } },
{ MI, { '_','o','p','e','n','_','d','i','s','p','l','a','y','\0' }, 0, { pf_open_display, 0, 1 } } { MI, { '_','o','p','e','n','_','d','i','s','p','l','a','y','\0' }, 0, { pf_open_display, 0, 1 } }
}; };
static int x11_import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class) static int x11_import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)