From 17d0874360b084dfcec3c27cdbfdf3459c6e864f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Br=C3=BCschweiler?= Date: Thu, 10 Jun 2010 00:16:31 +0200 Subject: [PATCH 1/3] ui.backend.gtk: preliminary input methods support --- basis/ui/backend/gtk/gtk.factor | 67 ++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/basis/ui/backend/gtk/gtk.factor b/basis/ui/backend/gtk/gtk.factor index 9acae5e7a5..d9caec5699 100644 --- a/basis/ui/backend/gtk/gtk.factor +++ b/basis/ui/backend/gtk/gtk.factor @@ -9,12 +9,13 @@ sequences strings system threads ui ui.backend ui.clipboards ui.event-loop ui.gadgets ui.gadgets.private ui.gadgets.worlds ui.gestures ui.pixel-formats ui.pixel-formats.private ui.private glib.ffi gobject.ffi gtk.ffi gdk.ffi gdk.gl.ffi gtk.gl.ffi ; +RENAME: windows ui.private => ui:windows IN: ui.backend.gtk SINGLETON: gtk-ui-backend TUPLE: handle ; -TUPLE: window-handle < handle window fullscreen? ; +TUPLE: window-handle < handle window fullscreen? im-context ; : ( window -- window-handle ) [ window-handle new ] dip >>window ; @@ -174,25 +175,36 @@ CONSTANT: action-key-codes :: on-key-press ( sender event user-data -- result ) sender window :> world - event GdkEventKey memory>struct :> ev - ev key-event>gesture :> gesture - gesture world propagate-key-gesture - ev keyval>> gdk_keyval_to_unicode 1string dup - gesture valid-input? - [ world user-input ] [ drop ] if + world handle>> im-context>> :> im-context + im-context event gtk_im_context_filter_keypress + [ + event GdkEventKey memory>struct :> ev + ev key-event>gesture :> gesture + gesture world propagate-key-gesture + ev keyval>> gdk_keyval_to_unicode 1string dup + gesture valid-input? + [ world user-input ] [ drop ] if + ] unless t ; -: on-key-release ( sender event user-data -- result ) - drop swap [ - GdkEventKey memory>struct +:: on-key-release ( sender event user-data -- result ) + sender window :> world + world handle>> im-context>> event gtk_im_context_filter_keypress + [ + event GdkEventKey memory>struct key-event>gesture - ] dip window propagate-key-gesture t ; + world propagate-key-gesture + ] unless t ; : on-focus-in ( sender event user-data -- result ) - 2drop window focus-world t ; + 2drop window [ focus-world ] + [ handle>> im-context>> gtk_im_context_focus_in ] bi + f ; : on-focus-out ( sender event user-data -- result ) - 2drop window unfocus-world t ; + 2drop window [ unfocus-world ] + [ handle>> im-context>> gtk_im_context_focus_out ] bi + f ; : on-expose ( sender event user-data -- result ) 2drop window relayout t ; @@ -289,6 +301,17 @@ M: gtk-ui-backend (with-ui) ] with-destructors ] ui-running ; +: im-context>window ( im-context -- world ) + ui:windows get-global + [ second handle>> im-context>> = ] with find nip second ; + +:: on-commit ( im-context string' user-data -- ) + im-context im-context>window :> world + string' utf8 alien>string :> string + f string f :> gesture + gesture world propagate-key-gesture + string world user-input ; + : connect-signal ( object signal-name callback -- ) [ utf8 string>alien ] dip f f 0 g_signal_connect_data drop ; @@ -323,6 +346,10 @@ M: gtk-ui-backend (with-ui) win "delete-event" [ on-delete yield ] GtkWidget:delete-event connect-signal ; +:: connect-im-signals ( im-context -- ) + im-context "commit" [ on-commit yield ] + GtkIMContext:commit connect-signal ; + CONSTANT: window-controls>decor-flags H{ { close-button 0 } @@ -375,9 +402,14 @@ CONSTANT: window-controls>func-flags M:: gtk-ui-backend (open-window) ( world -- ) GTK_WINDOW_TOPLEVEL gtk_window_new :> win + gtk_im_multicontext_new :> im-context + + im-context f gtk_im_context_set_use_preedit - world win [ >>handle drop ] - [ register-window ] 2bi + win im-context >>im-context + world handle<< + + world win register-window win world [ window-loc>> auto-position ] [ dim>> first2 gtk_window_set_default_size ] 2bi @@ -385,14 +417,15 @@ M:: gtk-ui-backend (open-window) ( world -- ) world setup-gl drop win connect-signals + im-context connect-im-signals win gtk_widget_realize win world window-controls>> configure-window-controls - + win gtk_widget_show_all ; M: gtk-ui-backend (close-window) ( handle -- ) - window>> [ unregister-window ] [ gtk_widget_destroy ] bi + window>> [ gtk_widget_destroy ] [ unregister-window ] bi event-loop? [ gtk_main_quit ] unless ; M: gtk-ui-backend set-title From 5f9929c97f29f6987212f27fecc99e8682cdb785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Br=C3=BCschweiler?= Date: Thu, 10 Jun 2010 22:35:08 +0200 Subject: [PATCH 2/3] ui.backend.gtk: notify input methods of cursor locations --- basis/gdk/ffi/ffi.factor | 2 +- basis/ui/backend/gtk/gtk.factor | 82 +++++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 26 deletions(-) diff --git a/basis/gdk/ffi/ffi.factor b/basis/gdk/ffi/ffi.factor index 5be53b7544..d67f61f585 100644 --- a/basis/gdk/ffi/ffi.factor +++ b/basis/gdk/ffi/ffi.factor @@ -23,7 +23,7 @@ GdkEventScroll GdkEventMotion GdkEventExpose GdkEventVisibility GdkEventCrossing GdkEventFocus GdkEventConfigure GdkEventProperty GdkEventSelection GdkEventDND GdkEventProximity GdkEventClient GdkEventNoExpose GdkEventWindowState GdkEventSetting -GdkEventOwnerChange GdkEventGrabBroken ; +GdkEventOwnerChange GdkEventGrabBroken GdkRectangle ; GIR: vocab:gdk/Gdk-2.0.gir diff --git a/basis/ui/backend/gtk/gtk.factor b/basis/ui/backend/gtk/gtk.factor index d9caec5699..9146732e55 100644 --- a/basis/ui/backend/gtk/gtk.factor +++ b/basis/ui/backend/gtk/gtk.factor @@ -2,13 +2,15 @@ ! See http://factorcode.org/license.txt for BSD license. USING: accessors alien.accessors alien.c-types alien.data alien.enums alien.strings arrays ascii assocs classes.struct -combinators.short-circuit command-line destructors +combinators.short-circuit command-line destructors gdk.ffi +gdk.gl.ffi glib.ffi gobject.ffi gtk.ffi gtk.gl.ffi io.backend.unix.multiplexers io.encodings.utf8 io.thread kernel -libc literals locals math math.bitwise math.order namespaces -sequences strings system threads ui ui.backend ui.clipboards -ui.event-loop ui.gadgets ui.gadgets.private ui.gadgets.worlds -ui.gestures ui.pixel-formats ui.pixel-formats.private ui.private -glib.ffi gobject.ffi gtk.ffi gdk.ffi gdk.gl.ffi gtk.gl.ffi ; +libc literals locals math math.bitwise math.order math.vectors +namespaces sequences strings system threads ui ui.backend +ui.clipboards ui.event-loop ui.gadgets ui.gadgets.editors +ui.gadgets.line-support ui.gadgets.private ui.gadgets.worlds +ui.gestures ui.pixel-formats ui.pixel-formats.private +ui.private ; RENAME: windows ui.private => ui:windows IN: ui.backend.gtk @@ -17,8 +19,10 @@ SINGLETON: gtk-ui-backend TUPLE: handle ; TUPLE: window-handle < handle window fullscreen? im-context ; -: ( window -- window-handle ) - [ window-handle new ] dip >>window ; +: ( window im-context -- window-handle ) + window-handle new + swap >>im-context + swap >>window ; TUPLE: gtk-clipboard handle ; @@ -128,10 +132,29 @@ CONSTANT: action-key-codes : mouse-event>gesture ( event -- modifiers button loc ) [ event-modifiers ] [ button>> ] [ event-loc ] tri ; +: gadget-location ( gadget -- loc ) + [ loc>> ] [ + parent>> [ gadget-location ] [ { 0 0 } ] if* + ] bi v+ ; + +: focusable-editor ( world -- editor/f ) + focusable-child dup editor? [ drop f ] unless ; + +: get-cursor-location ( editor -- GdkRectangle ) + [ [ gadget-location ] [ caret-loc ] bi v+ first2 ] + [ line-height ] bi 0 swap GdkRectangle ; + +: update-im-cursor-location ( world -- ) + dup focusable-editor [ + [ handle>> im-context>> ] [ get-cursor-location ] bi* + gtk_im_context_set_cursor_location + ] [ drop ] if* ; + : on-motion ( sender event user-data -- result ) - drop swap - [ GdkEventMotion memory>struct event-loc ] dip window - move-hand fire-motion t ; + drop swap [ + [ GdkEventMotion memory>struct event-loc ] dip window + move-hand fire-motion + ] [ window update-im-cursor-location ] bi t ; : on-enter ( sender event user-data -- result ) on-motion ; @@ -155,7 +178,8 @@ CONSTANT: action-key-codes drop swap [ GdkEventScroll memory>struct [ scroll-direction ] [ event-loc ] bi - ] dip window send-scroll t ; + ] dip window + [ send-scroll ] [ update-im-cursor-location ] bi t ; : key-sym ( event -- sym action? ) keyval>> dup action-key-codes at @@ -185,7 +209,7 @@ CONSTANT: action-key-codes gesture valid-input? [ world user-input ] [ drop ] if ] unless - t ; + world update-im-cursor-location t ; :: on-key-release ( sender event user-data -- result ) sender window :> world @@ -194,16 +218,19 @@ CONSTANT: action-key-codes event GdkEventKey memory>struct key-event>gesture world propagate-key-gesture - ] unless t ; + ] unless + world update-im-cursor-location t ; : on-focus-in ( sender event user-data -- result ) 2drop window [ focus-world ] - [ handle>> im-context>> gtk_im_context_focus_in ] bi + [ handle>> im-context>> gtk_im_context_focus_in ] + [ update-im-cursor-location ] tri f ; : on-focus-out ( sender event user-data -- result ) 2drop window [ unfocus-world ] - [ handle>> im-context>> gtk_im_context_focus_out ] bi + [ handle>> im-context>> gtk_im_context_focus_out ] + [ update-im-cursor-location ] tri f ; : on-expose ( sender event user-data -- result ) @@ -310,7 +337,8 @@ M: gtk-ui-backend (with-ui) string' utf8 alien>string :> string f string f :> gesture gesture world propagate-key-gesture - string world user-input ; + string world user-input + world update-im-cursor-location ; : connect-signal ( object signal-name callback -- ) [ utf8 string>alien ] dip f f 0 g_signal_connect_data drop ; @@ -406,8 +434,7 @@ M:: gtk-ui-backend (open-window) ( world -- ) im-context f gtk_im_context_set_use_preedit - win im-context >>im-context - world handle<< + win im-context world handle<< world win register-window @@ -422,10 +449,14 @@ M:: gtk-ui-backend (open-window) ( world -- ) win gtk_widget_realize win world window-controls>> configure-window-controls + im-context win gtk_widget_get_window + gtk_im_context_set_client_window + win gtk_widget_show_all ; M: gtk-ui-backend (close-window) ( handle -- ) - window>> [ gtk_widget_destroy ] [ unregister-window ] bi + [ im-context>> f gtk_im_context_set_client_window ] + [ window>> [ gtk_widget_destroy ] [ unregister-window ] bi ] bi event-loop? [ gtk_main_quit ] unless ; M: gtk-ui-backend set-title @@ -433,10 +464,12 @@ M: gtk-ui-backend set-title gtk_window_set_title ; M: gtk-ui-backend (set-fullscreen) - [ handle>> ] dip [ >>fullscreen? ] keep - [ window>> ] dip - [ gtk_window_fullscreen ] - [ gtk_window_unfullscreen ] if ; + [ + [ handle>> ] dip [ >>fullscreen? ] keep + [ window>> ] dip + [ gtk_window_fullscreen ] + [ gtk_window_unfullscreen ] if + ] [ drop update-im-cursor-location ] 2bi ; M: gtk-ui-backend (fullscreen?) handle>> fullscreen?>> ; @@ -488,4 +521,3 @@ M: gtk-clipboard set-clipboard-contents gtk-ui-backend ui-backend set-global [ "ui.tools" ] main-vocab-hook set-global - From 4ce4b2c257a5a9dc5362f5109f68bee0e2fc1785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Br=C3=BCschweiler?= Date: Fri, 11 Jun 2010 19:33:28 +0200 Subject: [PATCH 3/3] ui.backend.gtk: add surrounding signal handler for input methods untested, as i don't think my IM is using this feature --- basis/ui/backend/gtk/gtk.factor | 58 +++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/basis/ui/backend/gtk/gtk.factor b/basis/ui/backend/gtk/gtk.factor index 9146732e55..1b417633f3 100644 --- a/basis/ui/backend/gtk/gtk.factor +++ b/basis/ui/backend/gtk/gtk.factor @@ -2,15 +2,15 @@ ! See http://factorcode.org/license.txt for BSD license. USING: accessors alien.accessors alien.c-types alien.data alien.enums alien.strings arrays ascii assocs classes.struct -combinators.short-circuit command-line destructors gdk.ffi -gdk.gl.ffi glib.ffi gobject.ffi gtk.ffi gtk.gl.ffi -io.backend.unix.multiplexers io.encodings.utf8 io.thread kernel -libc literals locals math math.bitwise math.order math.vectors -namespaces sequences strings system threads ui ui.backend -ui.clipboards ui.event-loop ui.gadgets ui.gadgets.editors -ui.gadgets.line-support ui.gadgets.private ui.gadgets.worlds -ui.gestures ui.pixel-formats ui.pixel-formats.private -ui.private ; +combinators combinators.short-circuit command-line destructors +documents gdk.ffi gdk.gl.ffi glib.ffi gobject.ffi gtk.ffi +gtk.gl.ffi io.backend.unix.multiplexers io.encodings.utf8 +io.thread kernel libc literals locals math math.bitwise +math.order math.vectors namespaces sequences strings system +threads ui ui.backend ui.clipboards ui.event-loop ui.gadgets +ui.gadgets.editors ui.gadgets.line-support ui.gadgets.private +ui.gadgets.worlds ui.gestures ui.pixel-formats +ui.pixel-formats.private ui.private ; RENAME: windows ui.private => ui:windows IN: ui.backend.gtk @@ -328,18 +328,38 @@ M: gtk-ui-backend (with-ui) ] with-destructors ] ui-running ; -: im-context>window ( im-context -- world ) +: im-context>world ( im-context -- world ) ui:windows get-global [ second handle>> im-context>> = ] with find nip second ; :: on-commit ( im-context string' user-data -- ) - im-context im-context>window :> world + im-context im-context>world :> world string' utf8 alien>string :> string f string f :> gesture gesture world propagate-key-gesture string world user-input world update-im-cursor-location ; +:: on-retrieve-surrounding ( im-context user-data -- ? ) + im-context im-context>world focusable-editor + [| editor | + editor editor-caret first2 :> ( x y ) + im-context + y editor editor-line utf8 string>alien + -1 x + gtk_im_context_set_surrounding t + ] [ f ] if* ; + +:: on-delete-surrounding ( im-context offset n user-data -- ? ) + im-context im-context>world :> world + world focusable-editor [| editor | + editor editor-caret first2 :> ( x y ) + x offset + y [ 2array ] [ [ n + ] dip 2array ] 2bi + editor remove-doc-range + world update-im-cursor-location + t + ] [ f ] if* ; + : connect-signal ( object signal-name callback -- ) [ utf8 string>alien ] dip f f 0 g_signal_connect_data drop ; @@ -374,9 +394,19 @@ M: gtk-ui-backend (with-ui) win "delete-event" [ on-delete yield ] GtkWidget:delete-event connect-signal ; -:: connect-im-signals ( im-context -- ) - im-context "commit" [ on-commit yield ] - GtkIMContext:commit connect-signal ; +: connect-im-signals ( im-context -- ) + { + [ + "commit" [ on-commit yield ] + GtkIMContext:commit connect-signal + ] [ + "retrieve-surrounding" [ on-retrieve-surrounding yield ] + GtkIMContext:retrieve-surrounding connect-signal + ] [ + "delete-surrounding" [ on-delete-surrounding yield ] + GtkIMContext:delete-surrounding connect-signal + ] + } cleave ; CONSTANT: window-controls>decor-flags H{