factor/basis/ui/x11/x11.factor

267 lines
7.8 KiB
Factor
Raw Normal View History

2008-07-11 14:46:59 -04:00
! Copyright (C) 2005, 2008 Eduardo Cavazos and Slava Pestov
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
2008-07-11 14:46:59 -04:00
USING: accessors alien alien.c-types arrays ui ui.gadgets
ui.gestures ui.backend ui.clipboards ui.gadgets.worlds ui.render
assocs kernel math namespaces opengl sequences strings x11.xlib
2008-04-21 00:05:12 -04:00
x11.events x11.xim x11.glx x11.clipboard x11.constants
x11.windows io.encodings.string io.encodings.ascii
2008-04-05 20:15:35 -04:00
io.encodings.utf8 combinators debugger command-line qualified
2008-07-11 19:34:43 -04:00
math.vectors classes.tuple opengl.gl threads math.geometry.rect ;
2008-04-05 20:15:35 -04:00
QUALIFIED: system
2007-09-20 18:09:08 -04:00
IN: ui.x11
2008-04-02 20:44:01 -04:00
SINGLETON: x11-ui-backend
2007-09-20 18:09:08 -04:00
2008-06-11 22:14:20 -04:00
: XA_NET_WM_NAME ( -- atom ) "_NET_WM_NAME" x-atom ;
2007-09-20 18:09:08 -04:00
TUPLE: x11-handle window glx xic ;
2007-09-20 18:09:08 -04:00
C: <x11-handle> x11-handle
M: world expose-event nip relayout ;
M: world configure-event
over configured-loc over (>>window-loc)
swap configured-dim over (>>dim)
2007-09-20 18:09:08 -04:00
! In case dimensions didn't change
relayout-1 ;
: modifiers
{
{ S+ HEX: 1 }
{ C+ HEX: 4 }
{ A+ HEX: 8 }
} ;
: key-codes
H{
{ HEX: FF08 "BACKSPACE" }
{ HEX: FF09 "TAB" }
{ HEX: FF0D "RET" }
{ HEX: FF8D "ENTER" }
{ HEX: FF1B "ESC" }
{ HEX: FFFF "DELETE" }
{ HEX: FF50 "HOME" }
{ HEX: FF51 "LEFT" }
{ HEX: FF52 "UP" }
{ HEX: FF53 "RIGHT" }
{ HEX: FF54 "DOWN" }
{ HEX: FF55 "PAGE_UP" }
{ HEX: FF56 "PAGE_DOWN" }
{ HEX: FF57 "END" }
{ HEX: FF58 "BEGIN" }
{ HEX: FFBE "F1" }
{ HEX: FFBF "F2" }
{ HEX: FFC0 "F3" }
{ HEX: FFC1 "F4" }
{ HEX: FFC2 "F5" }
{ HEX: FFC3 "F6" }
{ HEX: FFC4 "F7" }
{ HEX: FFC5 "F8" }
{ HEX: FFC6 "F9" }
} ;
: key-code ( keysym -- keycode action? )
dup key-codes at [ t ] [ 1string f ] ?if ;
: event-modifiers ( event -- seq )
XKeyEvent-state modifiers modifier ;
: key-down-event>gesture ( event world -- string gesture )
dupd
2008-08-31 02:42:30 -04:00
handle>> x11-handle-xic lookup-string
2007-09-20 18:09:08 -04:00
>r swap event-modifiers r> key-code <key-down> ;
M: world key-down-event
[ key-down-event>gesture ] keep world-focus
[ send-gesture ] keep swap [ user-input ] [ 2drop ] if ;
: key-up-event>gesture ( event -- gesture )
dup event-modifiers swap 0 XLookupKeysym key-code <key-up> ;
M: world key-up-event
>r key-up-event>gesture r> world-focus send-gesture drop ;
: mouse-event>gesture ( event -- modifiers button loc )
dup event-modifiers over XButtonEvent-button
rot mouse-event-loc ;
M: world button-down-event
>r mouse-event>gesture >r <button-down> r> r>
send-button-down ;
M: world button-up-event
>r mouse-event>gesture >r <button-up> r> r>
send-button-up ;
: mouse-event>scroll-direction ( event -- pair )
2007-10-10 02:16:42 -04:00
XButtonEvent-button {
{ 4 { 0 -1 } }
{ 5 { 0 1 } }
{ 6 { -1 0 } }
{ 7 { 1 0 } }
} at ;
2007-09-20 18:09:08 -04:00
M: world wheel-event
>r dup mouse-event>scroll-direction swap mouse-event-loc r>
send-wheel ;
M: world enter-event motion-event ;
M: world leave-event 2drop forget-rollover ;
M: world motion-event
>r dup XMotionEvent-x swap XMotionEvent-y 2array r>
move-hand fire-motion ;
M: world focus-in-event
nip
2008-08-31 02:42:30 -04:00
dup handle>> x11-handle-xic XSetICFocus focus-world ;
2007-09-20 18:09:08 -04:00
M: world focus-out-event
nip
2008-08-31 02:42:30 -04:00
dup handle>> x11-handle-xic XUnsetICFocus unfocus-world ;
2007-09-20 18:09:08 -04:00
M: world selection-notify-event
2008-08-31 02:42:30 -04:00
[ handle>> x11-handle-window selection-from-event ] keep
2007-09-20 18:09:08 -04:00
world-focus user-input ;
: supported-type? ( atom -- ? )
{ "UTF8_STRING" "STRING" "TEXT" }
2008-01-09 17:36:30 -05:00
[ x-atom = ] with contains? ;
2007-09-20 18:09:08 -04:00
: clipboard-for-atom ( atom -- clipboard )
{
{ [ dup XA_PRIMARY = ] [ drop selection get ] }
{ [ dup XA_CLIPBOARD = ] [ drop clipboard get ] }
2008-04-11 13:54:33 -04:00
[ drop <clipboard> ]
2007-09-20 18:09:08 -04:00
} cond ;
: encode-clipboard ( string type -- bytes )
2008-04-20 06:15:46 -04:00
XSelectionRequestEvent-target
XA_UTF8_STRING = utf8 ascii ? encode ;
2007-09-20 18:09:08 -04:00
: set-selection-prop ( evt -- )
dpy get swap
[ XSelectionRequestEvent-requestor ] keep
[ XSelectionRequestEvent-property ] keep
[ XSelectionRequestEvent-target ] keep
>r 8 PropModeReplace r>
[
XSelectionRequestEvent-selection
clipboard-for-atom x-clipboard-contents
] keep encode-clipboard dup length XChangeProperty drop ;
M: world selection-request-event
drop dup XSelectionRequestEvent-target {
{ [ dup supported-type? ] [ drop dup set-selection-prop send-notify-success ] }
{ [ dup "TARGETS" x-atom = ] [ drop dup set-targets-prop send-notify-success ] }
{ [ dup "TIMESTAMP" x-atom = ] [ drop dup set-timestamp-prop send-notify-success ] }
2008-04-11 13:54:33 -04:00
[ drop send-notify-failure ]
2007-09-20 18:09:08 -04:00
} cond ;
2007-11-24 16:29:13 -05:00
M: x11-ui-backend (close-window) ( handle -- )
2007-09-20 18:09:08 -04:00
dup x11-handle-xic XDestroyIC
dup x11-handle-glx destroy-glx
x11-handle-window dup unregister-window
destroy-window ;
M: world client-event
2007-11-24 16:29:13 -05:00
swap close-box? [ ungraft ] [ drop ] if ;
2007-09-20 18:09:08 -04:00
: gadget-window ( world -- )
dup window-loc>> over rect-dim glx-window
over "Factor" create-xic <x11-handle>
2007-09-20 18:09:08 -04:00
2dup x11-handle-window register-window
2008-08-31 02:42:30 -04:00
swap (>>handle) ;
2007-09-20 18:09:08 -04:00
: wait-event ( -- event )
QueuedAfterFlush events-queued 0 > [
next-event dup
None XFilterEvent zero? [ drop wait-event ] unless
] [
2008-02-25 17:48:11 -05:00
ui-wait wait-event
2007-09-20 18:09:08 -04:00
] if ;
2008-05-08 17:58:13 -04:00
M: x11-ui-backend do-events
2007-09-20 18:09:08 -04:00
wait-event dup XAnyEvent-window window dup
[ [ 2dup handle-event ] assert-depth ] when 2drop ;
: x-clipboard@ ( gadget clipboard -- prop win )
x-clipboard-atom swap
2008-08-31 02:42:30 -04:00
find-world handle>> x11-handle-window ;
2007-09-20 18:09:08 -04:00
M: x-clipboard copy-clipboard
[ x-clipboard@ own-selection ] keep
set-x-clipboard-contents ;
M: x-clipboard paste-clipboard
2008-08-31 02:42:30 -04:00
>r find-world handle>> x11-handle-window
2007-09-20 18:09:08 -04:00
r> x-clipboard-atom convert-selection ;
: init-clipboard ( -- )
XA_PRIMARY <x-clipboard> selection set-global
XA_CLIPBOARD <x-clipboard> clipboard set-global ;
: set-title-old ( dpy window string -- )
dup [ 127 <= ] all? [ XStoreName drop ] [ 3drop ] if ;
: set-title-new ( dpy window string -- )
>r
XA_NET_WM_NAME XA_UTF8_STRING 8 PropModeReplace
2008-03-05 20:12:40 -05:00
r> utf8 encode dup length XChangeProperty drop ;
2007-09-20 18:09:08 -04:00
M: x11-ui-backend set-title ( string world -- )
2008-08-31 02:42:30 -04:00
handle>> x11-handle-window swap dpy get -rot
2007-09-20 18:09:08 -04:00
3dup set-title-old set-title-new ;
M: x11-ui-backend set-fullscreen* ( ? world -- )
2008-08-31 02:42:30 -04:00
handle>> x11-handle-window "XClientMessageEvent" <c-object>
tuck set-XClientMessageEvent-window
swap _NET_WM_STATE_ADD _NET_WM_STATE_REMOVE ?
over set-XClientMessageEvent-data0
ClientMessage over set-XClientMessageEvent-type
dpy get over set-XClientMessageEvent-display
"_NET_WM_STATE" x-atom over set-XClientMessageEvent-message_type
32 over set-XClientMessageEvent-format
"_NET_WM_STATE_FULLSCREEN" x-atom over set-XClientMessageEvent-data1
>r dpy get root get 0 SubstructureNotifyMask r> XSendEvent drop ;
2007-09-20 18:09:08 -04:00
2007-11-24 16:29:13 -05:00
M: x11-ui-backend (open-window) ( world -- )
2007-09-20 18:09:08 -04:00
dup gadget-window
2008-08-31 02:42:30 -04:00
handle>> x11-handle-window dup set-closable map-window ;
2007-09-20 18:09:08 -04:00
2008-02-21 00:13:31 -05:00
M: x11-ui-backend raise-window* ( world -- )
2008-08-31 02:42:30 -04:00
handle>> [
2007-09-20 18:09:08 -04:00
dpy get swap x11-handle-window XRaiseWindow drop
] when* ;
M: x11-ui-backend select-gl-context ( handle -- )
dpy get swap
dup x11-handle-window swap x11-handle-glx glXMakeCurrent
[ "Failed to set current GLX context" throw ] unless ;
M: x11-ui-backend flush-gl-context ( handle -- )
dpy get swap x11-handle-window glXSwapBuffers ;
2007-09-20 18:09:08 -04:00
M: x11-ui-backend ui ( -- )
[
f [
[
2008-05-08 17:58:13 -04:00
stop-after-last-window? on
2007-09-20 18:09:08 -04:00
init-clipboard
start-ui
event-loop
] with-xim
] with-x
] ui-running ;
M: x11-ui-backend beep ( -- )
2008-06-11 22:22:35 -04:00
dpy get 100 XBell drop ;
2008-04-02 20:44:01 -04:00
x11-ui-backend ui-backend set-global
2007-09-20 18:09:08 -04:00
2008-04-05 20:15:35 -04:00
[ "DISPLAY" system:os-env "ui" "listener" ? ]
2007-09-20 18:09:08 -04:00
main-vocab-hook set-global