From 7600d42c7cb5ccd91f1da694e8196fc8f57cba7d Mon Sep 17 00:00:00 2001 From: Peng Huang Date: Sun, 29 Mar 2009 13:44:25 +0800 Subject: [PATCH] Use gtk key snooper to get the key events. --- client/gtk2/ibusimcontext.c | 89 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 12 deletions(-) diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c index b542bd3..f99e60a 100644 --- a/client/gtk2/ibusimcontext.c +++ b/client/gtk2/ibusimcontext.c @@ -32,6 +32,7 @@ struct _IBusIMContext { /* instance members */ GtkIMContext *slave; GdkWindow *client_window; + GdkWindow *event_window; /* enabled */ gboolean enable; @@ -62,6 +63,7 @@ static guint _signal_preedit_end_id = 0; static guint _signal_delete_surrounding_id = 0; static guint _signal_retrieve_surrounding_id = 0; static GQuark _q_ibus_im_context = 0; +static gboolean _use_key_snooper = TRUE; /* functions prototype */ static void ibus_im_context_class_init (IBusIMContextClass *klass); @@ -81,6 +83,10 @@ static void ibus_im_context_get_preedit_string static void ibus_im_context_set_client_window (GtkIMContext *context, GdkWindow *client); + +static void ibus_im_context_set_event_window + (IBusIMContext *ibusimcontext, + GdkWindow *client); static void ibus_im_context_set_cursor_location (GtkIMContext *context, GdkRectangle *area); @@ -175,6 +181,30 @@ ibus_im_context_new (void) return obj; } +static gint +_key_snooper_cb (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data) +{ + GdkWindow *gdkwindow; + GtkIMContext *imcontext; + + if (!_use_key_snooper) + return 0; + + gdkwindow = gtk_widget_get_window (widget); + + if (gdkwindow == NULL) + return 0; + + imcontext = (GtkIMContext *) g_object_get_qdata ((GObject *) gdkwindow, _q_ibus_im_context); + + if (imcontext == NULL) + return 0; + + return gtk_im_context_filter_keypress (imcontext, event); +} + static void ibus_im_context_class_init (IBusIMContextClass *klass) { @@ -218,6 +248,10 @@ ibus_im_context_class_init (IBusIMContextClass *klass) g_assert (_signal_retrieve_surrounding_id != 0); _q_ibus_im_context = g_quark_from_static_string ("IBusIMContext"); + + if (_use_key_snooper) { + gtk_key_snooper_install (_key_snooper_cb, NULL); + } } static void @@ -227,6 +261,7 @@ ibus_im_context_init (GObject *obj) IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (obj); ibusimcontext->client_window = NULL; + ibusimcontext->event_window = NULL; // Init ibus status ibusimcontext->enable = FALSE; @@ -300,13 +335,12 @@ ibus_im_context_finalize (GObject *obj) ibus_object_destroy ((IBusObject *)ibusimcontext->ibuscontext); } - g_object_unref (ibusimcontext->slave); + ibus_im_context_set_client_window ((GtkIMContext *)ibusimcontext, NULL); + ibus_im_context_set_event_window (ibusimcontext, NULL); - if (ibusimcontext->client_window) { - if (g_object_steal_qdata ((GObject *) ibusimcontext->client_window, _q_ibus_im_context) == ibusimcontext) { - g_object_unref (ibusimcontext); - } - g_object_unref (ibusimcontext->client_window); + if (ibusimcontext->slave) { + g_object_unref (ibusimcontext->slave); + ibusimcontext->slave = NULL; } // release preedit @@ -322,13 +356,17 @@ ibus_im_context_finalize (GObject *obj) static gboolean ibus_im_context_filter_keypress (GtkIMContext *context, - GdkEventKey *event) + GdkEventKey *event) { g_return_val_if_fail (context != NULL, FALSE); g_return_val_if_fail (IBUS_IS_IM_CONTEXT (context), FALSE); IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (context); + if (event->window != ibusimcontext->client_window && event->window != ibusimcontext->event_window) { + ibus_im_context_set_event_window (ibusimcontext, event->window); + } + if (ibusimcontext->ibuscontext && ibusimcontext->has_focus) { /* If context does not have focus, ibus will process key event in sync mode. * It is a workaround for increase search in treeview. @@ -454,7 +492,7 @@ ibus_im_context_get_preedit_string (GtkIMContext *context, static void -ibus_im_context_set_client_window (GtkIMContext *context, GdkWindow *client) +ibus_im_context_set_client_window (GtkIMContext *context, GdkWindow *client) { g_return_if_fail (context != NULL); g_return_if_fail (IBUS_IS_IM_CONTEXT (context)); @@ -462,20 +500,47 @@ ibus_im_context_set_client_window (GtkIMContext *context, GdkWindow *client) IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (context); if (ibusimcontext->client_window) { - if (g_object_steal_qdata ((GObject *) ibusimcontext->client_window, _q_ibus_im_context) == ibusimcontext) { - g_object_unref (ibusimcontext); + if (g_object_get_qdata ((GObject *) ibusimcontext->client_window, _q_ibus_im_context) == ibusimcontext) { + g_object_set_qdata ((GObject *) ibusimcontext->client_window, _q_ibus_im_context, NULL); } g_object_unref (ibusimcontext->client_window); } + ibus_im_context_set_event_window (ibusimcontext, NULL); + if (client) { g_object_ref (client); - g_object_ref (context); + g_object_ref (ibusimcontext); g_object_set_qdata_full ((GObject *) client, _q_ibus_im_context, context, g_object_unref); } ibusimcontext->client_window = client; - gtk_im_context_set_client_window (ibusimcontext->slave, client); + + if (ibusimcontext->slave) + gtk_im_context_set_client_window (ibusimcontext->slave, client); +} + +static void +ibus_im_context_set_event_window (IBusIMContext *ibusimcontext, GdkWindow *window) +{ + if (ibusimcontext->event_window) { + if (g_object_get_qdata ((GObject *) ibusimcontext->event_window, _q_ibus_im_context) == ibusimcontext) { + g_object_set_qdata ((GObject *) ibusimcontext->event_window, _q_ibus_im_context, NULL); + } + g_object_unref (ibusimcontext->event_window); + ibusimcontext->event_window = NULL; + } + + if (window == ibusimcontext->client_window) + window = NULL; + + if (window != NULL) { + g_object_ref (window); + g_object_ref (ibusimcontext); + g_object_set_qdata_full ((GObject *) window, _q_ibus_im_context, ibusimcontext, g_object_unref); + } + + ibusimcontext->event_window = window; } static void -- 2.7.4