     window>>
     [ gtk_grab_remove ] [ GDK_LEFT_PTR set-cursor ] bi ;
 
-M: window-handle select-gl-context ( handle -- )
-    window>>
-    [ gtk_widget_get_gl_window ] [ gtk_widget_get_gl_context ] bi
-    gdk_gl_drawable_make_current drop ;
-
-M: window-handle flush-gl-context ( handle -- )
-    window>> gtk_widget_get_gl_window
-    gdk_gl_drawable_swap_buffers ;
+! Misc.
 
 M: gtk-ui-backend beep
     gdk_beep ;

    win "factor" "Factor" [ utf8 string>alien ] bi@
    gtk_window_set_wmclass
    
    world setup-gl drop

    win gtk_widget_realize
    win world window-controls>> configure-window-controls
    
    win im configure-im
    win connect-signals

    win gtk_widget_show_all ;


        swap >>im-context
        swap >>window ;

: connect-signal-with-data ( object signal-name callback data -- )
    [ utf8 string>alien ] 2dip g_signal_connect drop ;

: connect-signal ( object signal-name callback -- )
    f connect-signal-with-data ;

! Clipboards

TUPLE: gtk-clipboard handle ;

C: <gtk-clipboard> gtk-clipboard

M: gtk-clipboard clipboard-contents
    [
        handle>> gtk_clipboard_wait_for_text
        [ &g_free utf8 alien>string ] [ f ] if*
    ] with-destructors ;

M: gtk-clipboard set-clipboard-contents
    swap [ handle>> ] [ utf8 string>alien ] bi*
    -1 gtk_clipboard_set_text ;

: init-clipboard ( -- )
    selection "PRIMARY"
    clipboard "CLIPBOARD"
    [
        utf8 string>alien gdk_atom_intern_static_string
        gtk_clipboard_get <gtk-clipboard> swap set-global
    ] 2bi@ ;

! IO events

: io-source-prepare ( source timeout -- ? )
    2drop f ;

: io-source-check ( source -- ? )
    poll_fds>> 0 g_slist_nth_data GPollFD memory>struct
    revents>> 0 = not ;

: io-source-dispatch ( source callback user_data -- ? )
     3drop
     0 mx get wait-for-events
     yield t ;

CONSTANT: poll-fd-events
    flags{
        G_IO_IN
        G_IO_OUT
        G_IO_PRI
        G_IO_ERR
        G_IO_HUP
        G_IO_NVAL
    }

: create-poll-fd ( -- poll-fd )
    GPollFD malloc-struct &free
        mx get fd>> >>fd
        poll-fd-events >>events ;

HOOK: init-io-event-source io-backend ( -- )

M: f init-io-event-source ;
M: c-io-backend init-io-event-source ;

M: object init-io-event-source
    GSourceFuncs malloc-struct &free
        [ io-source-prepare ] GSourceFuncsPrepareFunc >>prepare
        [ io-source-check ] GSourceFuncsCheckFunc >>check
        [ io-source-dispatch ] GSourceFuncsDispatchFunc >>dispatch
    GSource heap-size g_source_new &g_source_unref
    [ create-poll-fd g_source_add_poll ]
    [ f g_source_attach drop ] bi ;

SYMBOL: next-timeout

: set-timeout*-value ( alien value -- )
    swap 0 set-alien-signed-4 ; inline

: timeout-prepare ( source timeout* -- ? )
    nip next-timeout get-global nano-count [-]
    [ 1,000,000 /i set-timeout*-value ] keep 0 = ;

: timeout-check ( source -- ? )
    drop next-timeout get-global nano-count [-] 0 = ;

: timeout-dispatch ( source callback user_data -- ? )
    3drop sleep-time [ 1,000,000,000 ] unless* nano-count +
    next-timeout set-global
    yield t ;

: init-timeout ( -- )
    GSourceFuncs malloc-struct &free
        [ timeout-prepare ] GSourceFuncsPrepareFunc >>prepare
        [ timeout-check ] GSourceFuncsCheckFunc >>check
        [ timeout-dispatch ] GSourceFuncsDispatchFunc >>dispatch
    GSource heap-size g_source_new &g_source_unref
    f g_source_attach drop
    nano-count next-timeout set-global ;

! User input

CONSTANT: events-mask
    flags{
