         ] with-destructors
     ] ui-running ;
 
+: connect-signal-with-data ( object signal-name callback data -- )
+    [ utf8 string>alien ] 2dip f 0 g_signal_connect_data drop ;
+
 : connect-signal ( object signal-name callback -- )
-    [ utf8 string>alien ] dip f f 0 g_signal_connect_data drop ;
+    f connect-signal-with-data ;
 
 :: connect-signals ( win -- )
     win events-mask [ enum>number ] [ bitor ] map-reduce

        [ scroll-direction ] [ event-loc ] bi
    ] dip window send-scroll t ;

: key-sym ( event -- sym action? )
    keyval>> dup action-key-codes at
    [ t ] [ gdk_keyval_to_unicode 1string f ] ?if ;

: key-event>gesture ( event -- modifiers sym action? )
    [ event-modifiers ] [ key-sym ] bi ;

: valid-input? ( string gesture -- ? )
    over empty? [ 2drop f ] [
        mods>> { f { S+ } } member? [
            [ { [ 127 = not ] [ CHAR: \s >= ] } 1&& ] all?
        ] [
            [ { [ 127 = not ] [ CHAR: \s >= ] [ alpha? not ] } 1&& ] all?
        ] if
    ] if ;

:: on-key-press ( sender event user-data -- result )
    sender window :> world
    event GdkEventKey memory>struct :> ev
    ev key-event>gesture <key-down> :> gesture
    gesture world propagate-key-gesture
    ev keyval>> gdk_keyval_to_unicode 1string dup
    gesture valid-input?
    [ world user-input ] [ drop ] if
    t ;

: on-key-release ( sender event user-data -- result )
    drop swap [
        GdkEventKey memory>struct
        key-event>gesture <key-up>
    ] dip window propagate-key-gesture t ;

: on-focus-in ( sender event user-data -- result )
    2drop window focus-world t ;

        f t GDK_GL_RGBA_TYPE enum>number gtk_widget_set_gl_capability
    ] with-world-pixel-format ;

: auto-position ( win loc -- )
    dup { 0 0 } = [
        drop dup window topmost-window =
        GTK_WIN_POS_CENTER GTK_WIN_POS_NONE ?
