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 manatee gmail com> wrote:
Hi Bharathwaaj,

Bharathwaaj Srinivasan <bharathwaaj s 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 manatee 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* 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 <bharathwaaj s 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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]