Sending GdkEvents to Gtk Widget
Hi, Is it possible to send GdkEvents to a GtkWidget from the application? Currently I've a GIOChannel which is listening to a socket and the GSource is attached to the Glib main loop. g_type_init(); g_thread_init(NULL); gdk_threads_init(); gdk_threads_enter(); gtk_init(NULL, NULL); channel = g_io_channel_unix_new (fd); g_io_channel_set_encoding (channel, NULL, NULL); g_io_channel_set_buffered (channel, FALSE); source = g_io_create_watch (channel, G_IO_IN); g_source_set_priority (source, G_PRIORITY_DEFAULT); g_source_set_can_recurse (source, TRUE); g_source_set_callback (source, (GSourceFunc) event_handler, NULL, NULL); g_source_attach (source, NULL); g_source_unref (source); g_io_channel_unref(channel); gtk_main(); gdk_threads_leave(); GdkEvents (Keyboard events) are passed from say another process by writing to the socket fd. Glib calls the callback event_handler for data available to read. The event_handler callback reads the GdkEvent passed by another process and calls gtk_main_do_event to pass the event to the widget. But this doesn't work and the application freezes. I use gdk_threads_enter and gdk_threads_leave in the callback and before gtk_main for making gtk thread aware as the callback comes from Glib. Kindly help me in providing a mechanism to pass GdkEvents from the top. If this is not possible, please explain why. The main purpose for which I need this is I'm using GtkWebKit and I send Tab key event to make the focus move to the next element in the Webview. Events are being fed from another process. Kind regards, Bharath ___ gtk-list mailing list gtk-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-list
Re: Sending GdkEvents to Gtk Widget
Hi Andy, I couldn't understand the meaning of serializeEvent. But still I simply tried the following in the socket source callback from GLib. GdkEvent event; memset(event, 0, sizeof(GdkEvent)); event.key.type = GDK_KEY_PRESS; event.key.keyval = GDK_Tab; event.key.send_event = TRUE; gdk_threads_enter(); printf(Sending Tab event to gtk_idle_add_full\n); gtk_idle_add_full(G_PRIORITY_DEFAULT, (GSourceFunc)gtk_main_do_event, NULL, event, NULL); gdk_threads_leave(); This also lead to the same behaviour. The WebKit Gtk main window freezed from responding for further events. I also tried replacing gtk_idle_add_full with g_idle_add_full. Still same behaviour. Please help me if i'm missing something. Kind regards, Bharath On Mon, Jul 12, 2010 at 12:33 PM, Andy Stewart lazycat.mana...@gmail.comwrote: Hi Bharathwaaj, I'm a developer of gtk2hs (Haskell binding to gtk+). I have fix same problem (WebKit widget and GdkEvent) at Haskell side. ( https://patch-tag.com/r/AndyStewart/gtk-serialized-event/snapshot/current/content/pretty/Graphics/UI/Gtk/Gdk/SerializedEvent.hsc ) This is screenshot : http://farm5.static.flickr.com/4080/4758242386_5230d3d54d_b.jpg Though i use Haskell, but i can explain how to pass GdkEvent from one process to another. Below are step: 1) Serialize GdkEvent at *server* process. 2) Then send SerializeEvent over the network 3) When *client* process receive SerializeEvent from network, re-build GdkEvent. 4) Then you can use gtk_main_do_event propagate same event on current focus widget, or use gtk_widget_event propagate event on specify widget. Only trick is you need use idle_add_full wrap gtk_main_do_event to make sure gtk_main_do_event running in *main thread* and not *listen event thread*. Hope above will help you. :) Cheers, -- Andy Bharathwaaj Srinivasan bharathwaa...@gmail.com writes: Hi, Is it possible to send GdkEvents to a GtkWidget from the application? Currently I've a GIOChannel which is listening to a socket and the GSource is attached to the Glib main loop. g_type_init(); g_thread_init(NULL); gdk_threads_init(); gdk_threads_enter(); gtk_init(NULL, NULL); channel = g_io_channel_unix_new (fd); g_io_channel_set_encoding (channel, NULL, NULL); g_io_channel_set_buffered (channel, FALSE); source = g_io_create_watch (channel, G_IO_IN); g_source_set_priority (source, G_PRIORITY_DEFAULT); g_source_set_can_recurse (source, TRUE); g_source_set_callback (source, (GSourceFunc) event_handler, NULL, NULL); g_source_attach (source, NULL); g_source_unref (source); g_io_channel_unref(channel); gtk_main(); gdk_threads_leave(); GdkEvents (Keyboard events) are passed from say another process by writing to the socket fd. Glib calls the callback event_handler for data available to read. The event_handler callback reads the GdkEvent passed by another process and calls gtk_main_do_event to pass the event to the widget. But this doesn't work and the application freezes. I use gdk_threads_enter and gdk_threads_leave in the callback and before gtk_main for making gtk thread aware as the callback comes from Glib. Kindly help me in providing a mechanism to pass GdkEvents from the top. If this is not possible, please explain why. The main purpose for which I need this is I'm using GtkWebKit and I send Tab key event to make the focus move to the next element in the Webview. Events are being fed from another process. Kind regards, Bharath ___ gtk-list mailing list gtk-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-list ___ gtk-list mailing list gtk-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-list ___ gtk-list mailing list gtk-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-list
Re: Sending GdkEvents to Gtk Widget
Hi Andy, Thank you very much for your patient reply. I had actually filled the GdkWindow field. But while copy pasting line by line, it somehow got missed. :P Now it is solved. The problem was, I was blocking the callback function without returning it to GLib! Since mine was kinda minimal test program, I had written an infinite while loop in the GSource callback function to call gtk_main_do_event without returning the GLib callback. How silly! :( Also i didn't add idle_add_full. But directly called gtk_main_do_event and it worked, because the callback comes from the same g main loop which gtk is running. I just added the gdk_threads_enter/leave calls before calling gtk_main_do_event. Actually, in my case there is no gtk involved in the server. I get a platform specific event which I've to remap to GdkEvent to be passed to the browser. Thank you once again! Cheers, Bharath On Mon, Jul 12, 2010 at 9:49 PM, Andy Stewart lazycat.mana...@gmail.comwrote: Hi Bharathwaaj, Bharathwaaj Srinivasan bharathwaa...@gmail.com writes: Hi Andy, I couldn't understand the meaning of serializeEvent. Because it's Haskell. :) I will explain at below. But still I simply tried the following in the socket source callback from GLib. GdkEvent event; memset(event, 0, sizeof(GdkEvent)); event.key.type = GDK_KEY_PRESS; event.key.keyval = GDK_Tab; event.key.send_event = TRUE; This is wrong, you should get field value from event that return by signal key_press_event, and not build those filed by yourself. Then you can send *all* GdkEvent to another process, and not just Tab key. Here is C structure of GdkEventKey: typedef struct { GdkEventType type; GdkWindow *window; gint8 send_event; guint32 time; guint state; guint keyval; gint length; gchar *string; guint16 hardware_keycode; guint8 group; guint is_modifier : 1; } GdkEventKey; On *server* process, you should hang some function on singal key_press_event, then you can get keyPress event when you typing something at server side. Then you need pick-up public field from keyPress event. Example: ... singalEvent is get in key_press_event signal ... ... serialize_event_type = signalEvent.key.type serialize_event_keyval = signalEvent.key.keyval serialize_event_send_event = signalEvent.key.send_event ... Note, you need serialize *all* public field in GdkEventKey except *GdkWindow* field. Because, when you send event to *client* process, you want propagate event in *client* process, so you need *client* process widget GdkWindow and not *server* one. After you serialize event value, you need send to network, below i explain how to handle at client side. gdk_threads_enter(); printf(Sending Tab event to gtk_idle_add_full\n); gtk_idle_add_full(G_PRIORITY_DEFAULT, (GSourceFunc)gtk_main_do_event, NULL, event, NULL); gdk_threads_leave(); This also lead to the same behaviour. The WebKit Gtk main window freezed from responding for further events. Because you haven't set field GdkWindow of GdkEventKey, it's 0 by your memset. When you call gtk_main_do_event, gtk_main_do_event will lookup GdkWindow field to decide which widget need receive event, since GdkWindow field is 0, your *client* process will freezed. So client should do like this. 1) When your *client* receive serialize event from network, then use below code to fill all flied except *GdkWindow* field: GdkEvent event; memset(event, 0, sizeof(GdkEvent)); ... event.key.type = serialize_event_type event.key.keyval = serialize_event_keyval event.key.send_event = serialize_event_send_event ... 2) Then fill *GdkWindow* field with client widget. You need get GdkWindow pointer from WebKit widget. widget_window_ptr = webkitWidget.window Then fill event GdkWindow field with webkit GdkWindow pointer. event.key.window = widget_window_ptr That's all. Cheers, -- Andy I also tried replacing gtk_idle_add_full with g_idle_add_full. Still same behaviour. Please help me if i'm missing something. Kind regards, Bharath On Mon, Jul 12, 2010 at 12:33 PM, Andy Stewart lazycat.mana...@gmail.com wrote: Hi Bharathwaaj, I'm a developer of gtk2hs (Haskell binding to gtk+). I have fix same problem (WebKit widget and GdkEvent) at Haskell side. ( https://patch-tag.com/r/AndyStewart/gtk-serialized-event/snapshot/current/content/pretty/Graphics/UI/Gtk/Gdk/ SerializedEvent.hsc) This is screenshot : http://farm5.static.flickr.com/4080/4758242386_5230d3d54d_b.jpg Though i use Haskell, but i can explain how to pass GdkEvent from one process to another. Below are step: 1) Serialize GdkEvent at *server* process. 2) Then send SerializeEvent over the network 3) When *client