USING: kernel io alien alien.c-types namespaces threads arrays sequences assocs math vars combinators.lib x11.constants x11.events x11.xlib mortar slot-accessors geom.rect ; IN: x ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SYMBOL: SYMBOL: ! SYMBOL: dpy VAR: dpy { "ptr" "name" "default-screen" "default-root" "default-gc" "black-pixel" "white-pixel" "colormap" "window-table" } accessors define-independent-class "create" !( name -- display ) [ new-empty swap >>name dup $name dup [ string>char-alien ] [ ] if XOpenDisplay dup [ >>ptr ] [ "XOpenDisplay error" throw ] if dup $ptr XDefaultScreen >>default-screen dup $ptr XDefaultRootWindow dupd new >>default-root dup $ptr over $default-screen XDefaultGC >>default-gc dup $ptr over $default-screen XBlackPixel >>black-pixel dup $ptr over $default-screen XWhitePixel >>white-pixel dup $ptr over $default-screen XDefaultColormap >>colormap H{ } clone >>window-table [ <- start-event-loop ] in-thread ] add-class-method { "id" } accessors drop DEFER: check-window-table { "add-to-window-table" !( display window -- ) [ dup $id rot $window-table set-at ] "remove-from-window-table" !( display window -- ) [ $id swap $window-table delete-at ] "next-event" !( display event -- display event ) [ over $ptr over XNextEvent drop ] "events-queued" !( display mode -- n ) [ >r $ptr r> XEventsQueued ] "concurrent-next-event" !( display event -- display event ) [ over QueuedAfterFlush <-- events-queued 0 > [ <-- next-event ] [ 100 sleep <-- concurrent-next-event ] if ] "event-loop" !( display event -- ) [ <-- concurrent-next-event 2dup >r >r dup XAnyEvent-window rot $window-table at dup [ <- handle-event ] [ 2drop ] if r> r> <-- event-loop ] "start-event-loop" !( display -- ) [ "XEvent" <-- event-loop ] "flush" !( display -- display ) [ dup $ptr XFlush drop ] "pointer-window" !( display -- window ) [ dup $ptr over $default-root $id 0 0 dup >r 0 0 0 0 0 XQueryPointer drop r> *Window new check-window-table ] } add-methods ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! { "dpy" "id" } accessors define-independent-class : create-window ( -- window ) new-empty <- init-window ; : create-window-from-id ( dpy id -- window ) new ; : check-window-table ( window -- window ) dup $id over $dpy $window-table at swap or ; "init-window" !( window -- window ) [ dpy get >>dpy dpy get $ptr dpy get $default-root $id 0 0 100 100 0 dpy get $black-pixel dpy get $white-pixel XCreateSimpleWindow >>id ] add-method ! new-empty <- init "raw" !( window -- dpy-ptr id ) [ dup $dpy $ptr swap $id ] add-method "move" !( window point -- window ) [ >r dup <- raw r> first2 XMoveWindow drop ] add-method "set-x" !( window x -- window ) [ over <- y 2array <-- move ] add-method "set-y" !( window y -- window ) [ over <- x swap 2array <-- move ] add-method "flush" !( window -- window ) [ dup $dpy <- flush drop ] add-method ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! 3 - Window Functions ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! 3.3 - Creating Windows "destroy" !( window -- window ) [ dup <- raw XDestroyWindow drop ] add-method "map" !( window -- window ) [ dup <- raw XMapWindow drop ] add-method "map-subwindows" !( window -- window ) [ dup <- raw XMapSubwindows drop ] add-method "unmap" !( window -- window ) [ dup <- raw XUnmapWindow drop ] add-method "unmap-subwindows" !( window -- window ) [ dup <- raw XUnmapSubwindows drop ] add-method ! 3.7 - Configuring Windows "resize" !( window size -- window ) [ >r dup <- raw r> first2 XResizeWindow drop ] add-method "set-width" !( window width -- window ) [ over <- height 2array <-- resize ] add-method "set-height" !( window height -- window ) [ over <- width swap 2array <-- resize ] add-method "set-border-width" !( window n -- window ) [ >r dup <- raw r> XSetWindowBorderWidth drop ] add-method ! 3.8 Changing Window Stacking Order "raise" !( window -- window ) [ dup <- raw XRaiseWindow drop ] add-method "lower" !( window -- window ) [ dup <- raw XLowerWindow drop ] add-method ! 3.9 - Changing Window Attributes ! : change-window-attributes ( valuemask attr window -- ) ! -rot >r >r <- raw r> r> XChangeWindowAttributes drop ; "change-attributes" !( window valuemask attr -- window ) [ >r >r dup <- raw r> r> XChangeWindowAttributes drop ] add-method DEFER: lookup-color "set-background" !( window color -- window ) [ >r dup <- raw r> lookup-color XSetWindowBackground drop ] add-method "set-gravity" !( window gravity -- window ) [ CWWinGravity swap "XSetWindowAttributes" tuck set-XSetWindowAttributes-win_gravity <--- change-attributes ] add-method ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! 4 - Window Information Functions ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! 4.1 - Obtaining Window Information { "children" !( window -- seq ) [ <- raw 0 0 f 0 2dup >r >r XQueryTree drop r> r> swap *void* swap *uint c-uint-array> [ dpy get swap new ] map ] "parent" !( window -- parent ) [ dup $dpy >r dup $dpy $ptr swap $id 0 0 dup >r f 0 XQueryTree drop r> *Window r> swap new check-window-table ] "size" !( window -- size ) [ <- raw 0 0 0 0 0 2dup 2array >r 0 0 XGetGeometry drop r> [ *uint ] map ] "width" !( window -- width ) [ <- size first ] "height" !( window -- height ) [ <- size second ] "position" !( window -- position ) [ <- raw 0 0 0 2dup 2array >r 0 0 0 0 XGetGeometry drop r> [ *int ] map ] "x" !( window -- x ) [ <- position first ] "y" !( window -- y ) [ <- position second ] "as-rect" !( window -- rect ) [ dup <- position swap <- size new ] "attributes" !( window -- XWindowAttributes ) [ <- raw "XWindowAttributes" dup >r XGetWindowAttributes drop r> ] "map-state" !( window -- state ) [ <- attributes XWindowAttributes-map_state ] "mapped?" !( window -- ? ) [ <- map-state IsUnmapped = not ] } add-methods ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! : get-atom-name ( atom -- name ) dpy get $ptr swap XGetAtomName ; : intern-atom ( atom-name only-if-exists? -- atom ) dpy get $ptr -rot XInternAtom ; : lookup-color ( name -- pixel ) dpy get $ptr dpy get $colormap rot "XColor" dup >r "XColor" XLookupColor drop dpy get $ptr dpy get $colormap r> dup >r XAllocColor drop r> XColor-pixel ; ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! 8 - Graphics Functions ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! "clear" !( window -- window ) [ dup <- raw XClearWindow drop ] add-method "draw-string" !( window gc pos string -- ) [ >r >r >r <- raw r> $ptr r> [ >fixnum ] map first2 r> dup length XDrawString drop ] add-method ! "draw-string" ! !( window gc pos string -- ) ! [ >r >r >r <- raw r> $ptr r> [ >fixnum ] map first2 r> dup length ! XDrawString drop ] ! add-method "draw-line" !( window gc a b -- ) [ >r >r >r <- raw r> $ptr r> first2 r> first2 XDrawLine drop ] add-method "draw-rect" !( window gc rect -- ) [ 3dup dup <- top-left swap <- top-right <---- draw-line 3dup dup <- top-right swap <- bottom-right <---- draw-line 3dup dup <- bottom-left swap <- bottom-right <---- draw-line dup <- top-left swap <- bottom-left <---- draw-line ] add-method ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! 9 - Window and Session Manager Functions ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! "reparent" !( window parent -- window ) [ >r dup <- raw r> $id 0 0 XReparentWindow drop ] add-method "add-to-save-set" !( window -- window ) [ dup <- raw XAddToSaveSet drop ] add-method ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! 10 - Events ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! : XButtonEvent-root-position ( event -- position ) dup XButtonEvent-x_root swap XButtonEvent-y_root 2array ; : XMotionEvent-root-position ( event -- position ) dup XMotionEvent-x_root swap XMotionEvent-y_root 2array ; ! Utility words for XConfigureRequestEvent : XConfigureRequestEvent-position ( XConfigureRequestEvent -- position ) dup XConfigureRequestEvent-x swap XConfigureRequestEvent-y 2array ; : XConfigureRequestEvent-size ( XConfigureRequestEvent -- size ) dup XConfigureRequestEvent-width swap XConfigureRequestEvent-height 2array ; : bit-test ( a b -- t-or-f ) bitand 0 = not ; : CWX? ( XConfigureRequestEvent -- bool ) XConfigureRequestEvent-value_mask CWX bit-test ; : CWY? ( XConfigureRequestEvent -- bool ) XConfigureRequestEvent-value_mask CWY bit-test ; : CWWidth? ( XConfigureRequestEvent -- bool ) XConfigureRequestEvent-value_mask CWWidth bit-test ; : CWHeight? ( XConfigureRequestEvent -- bool ) XConfigureRequestEvent-value_mask CWHeight bit-test ; ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! 11 - Event Handling Functions ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! "select-input" !( window mask -- window ) [ >r dup <- raw r> XSelectInput drop ] add-method ! 11.8 - Handling Protocol Errors SYMBOL: error-handler-quot : error-handler-callback ( -- xt ) "void" { "Display*" "XErrorEvent*" } "cdecl" [ error-handler-quot get call ] alien-callback ; : set-error-handler ( quot -- ) error-handler-quot set error-handler-callback XSetErrorHandler drop ; : install-default-error-handler ( -- ) [ "X11 : error-handler called" print flush ] set-error-handler ; ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! 12 - Input Device Functions ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! 12.2 - Keyboard Grabbing : grab-key ( keycode modifiers grab-window owner-events pointer-mode keyboard-mode -- ) >r >r >r <- raw >r -rot r> r> r> r> XGrabKey drop ; ! 12.5 - Controlling Input Focus "set-input-focus" !( window revert-to time -- window ) [ >r >r dup <- raw r> r> XSetInputFocus drop ] add-method : get-input-focus ( -- window ) dpy> $ptr 0 dup >r 0 XGetInputFocus drop r> *Window dpy> swap create-window-from-id check-window-table ; ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! 14 - Inter-Client Communication Functions ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! "fetch-name" !( window -- name-or-f ) [ <- raw f dup >r XFetchName drop r> dup *void* alien-address 0 = [ drop f ] [ *char* ] if ] add-method ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! 16 - Application Utility Functions ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! 16.1 - Using Keyboard Utility Functions ! this should go in xlib.factor USING: alien.syntax ; FUNCTION: KeyCode XKeysymToKeycode ( Display* display, KeySym keysym ) ; FUNCTION: KeySym XKeycodeToKeysym ( Display* display, KeyCode keycode, int index ) ; FUNCTION: char* XKeysymToString ( KeySym keysym ) ; : keysym-to-keycode ( keysym -- keycode ) dpy get $ptr swap XKeysymToKeycode ; USE: strings : lookup-string* ( event -- keysym string ) 10 "char" dup >r 10 0 dup >r f XLookupString r> *KeySym swap r> swap c-char-array> >string ; : lookup-string ( event -- string ) lookup-string* nip ; : lookup-keysym ( event -- keysym ) lookup-string* drop ; ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!7 : event-to-keysym ( event index -- keysym ) >r dup XKeyEvent-display swap XKeyEvent-keycode r> XKeycodeToKeysym ; : keysym-to-string ( keysym -- string ) XKeysymToString ; : key-event-to-string ( event index -- str ) event-to-keysym keysym-to-string ; ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! Misc ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! : no-modifiers ( -- mask ) 0 ; : control-alt ( -- mask ) ControlMask Mod1Mask bitor ; : alt ( -- mask ) Mod1Mask ; : True 1 ; : False 0 ; "send-client-message" !( window message-type data -- window ) [ "XClientMessageEvent" tuck set-XClientMessageEvent-data0 tuck set-XClientMessageEvent-message_type over $id over set-XClientMessageEvent-window ClientMessage over set-XClientMessageEvent-type 32 over set-XClientMessageEvent-format CurrentTime over set-XClientMessageEvent-data1 >r dup <- raw False NoEventMask r> XSendEvent drop ] add-method