         f f gtk_gl_init
         init-clipboard
         start-ui
-        f io-thread-running? set-global
+        stop-io-thread
         [
             init-io-event-source
             init-timeout

    win "delete-event" [ on-delete yield ]
    GtkWidget:delete-event connect-signal ;

: on-retrieve-surrounding ( im-context user-data -- ? )
    window focusable-editor [| im-context editor |
        editor editor-caret first2 :> ( x y )
        im-context
        y editor editor-line utf8 string>alien
        -1 x
        gtk_im_context_set_surrounding t
    ] [ drop f ] if* ;

:: on-delete-surrounding ( im-context offset n user-data -- ? )
    user-data window :> 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* ;

: on-commit ( sender str user_data -- )
    [ drop ] [ utf8 alien>string ] [ window ] tri*
    [ user-input ]
    [ [ f swap key-down boa ] dip handle-key-gesture ] 2bi ;

! has to be called before the window signal handler
: im-on-key-event ( sender event user-data -- result )
    [ drop ] 2dip swap gtk_im_context_filter_keypress ;

: im-on-focus-in ( sender event user-data -- result )
    2drop window
    [ handle>> im-context>> gtk_im_context_focus_in ]
    [ update-im-cursor-location ] bi f ;

: im-on-focus-out ( sender event user-data -- result )
    2drop window
    [ handle>> im-context>> gtk_im_context_focus_out ]
    [ update-im-cursor-location ] bi f ;

: im-on-motion ( sender event user-data -- result )
    2drop window update-im-cursor-location f ;

: im-on-destroy ( sender user-data -- result )
    nip [ f gtk_im_context_set_client_window ]
    [ g_object_unref ] bi f ;

:: configure-im ( win im -- )
    im win gtk_widget_get_window gtk_im_context_set_client_window
    im f gtk_im_context_set_use_preedit
    
    im "commit" [ on-commit yield ]
    GtkIMContext:commit win connect-signal-with-data

: mouse-event>gesture ( event -- modifiers button loc )
    [ event-modifiers ] [ button>> ] [ event-loc ] tri ;

: on-motion ( sender event user-data -- result )
    drop swap
    [ GdkEventMotion memory>struct event-loc ] dip window
