From a1f880ae4c346d154a7777462db8208556c60309 Mon Sep 17 00:00:00 2001 From: Huang Peng Date: Wed, 16 Jul 2008 16:53:51 +0800 Subject: [PATCH] Separate ic. --- gtk2/ibusim.c | 34 +++-- gtk2/ibusimclient.c | 386 +++++++++++++++++++++++---------------------------- gtk2/ibusimclient.h | 38 ++--- gtk2/ibusimcontext.c | 180 ++++++++++++++++-------- gtk2/ibusimcontext.h | 36 ++++- 5 files changed, 374 insertions(+), 300 deletions(-) diff --git a/gtk2/ibusim.c b/gtk2/ibusim.c index 2445fc1..12de459 100644 --- a/gtk2/ibusim.c +++ b/gtk2/ibusim.c @@ -9,7 +9,7 @@ * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public @@ -22,47 +22,51 @@ #include #include #include "ibusimclient.h" -#include "ibusimcontext.h" #define IBUS_LOCALDIR "" static const GtkIMContextInfo ibus_im_info = { - "ibus", - "The Input Bus", - "ibus", - IBUS_LOCALDIR, - "" + "ibus", + "The Input Bus", + "ibus", + IBUS_LOCALDIR, + "" }; static const GtkIMContextInfo * info_list[] = { - &ibus_im_info + &ibus_im_info }; +IBusIMClient *_client = NULL; + void im_module_init (GTypeModule *type_module) { - ibus_im_client_register_type(type_module); - ibus_im_context_register_type(type_module); + ibus_im_client_register_type(type_module); + ibus_im_context_register_type(type_module); + + _client = ibus_im_client_new (); } void im_module_exit (void) { + g_object_unref (_client); } GtkIMContext * im_module_create (const gchar *context_id) { - if (strcmp (context_id, "ibus") == 0) - return ibus_im_context_new (); - return NULL; + if (strcmp (context_id, "ibus") == 0) + return ibus_im_client_create_im_context (_client); + return NULL; } void im_module_list (const GtkIMContextInfo ***contexts, int *n_contexts) { - *contexts = info_list; - *n_contexts = G_N_ELEMENTS (info_list); + *contexts = info_list; + *n_contexts = G_N_ELEMENTS (info_list); } diff --git a/gtk2/ibusimclient.c b/gtk2/ibusimclient.c index 3f93158..7d5e542 100644 --- a/gtk2/ibusimclient.c +++ b/gtk2/ibusimclient.c @@ -52,38 +52,25 @@ struct _IBusIMClientPrivate { #ifdef HAVE_INOTIFY /* inotify */ gint inotify_wd; - GIOChannel *inotify_channel; + GIOChannel *inotify_channel; guint inotify_source; #endif - DBusConnection *ibus; - gboolean enable; + DBusConnection *ibus; - GtkIMContext *context; - gchar *ic; - - /* preedit status */ - gchar *preedit_string; - PangoAttrList *preedit_attrs; - gint preedit_cursor; - gboolean preedit_show; + GHashTable *ic_table; + GList *contexts; }; /* functions prototype */ -static void ibus_im_client_class_init (IBusIMClientClass *klass); -static void ibus_im_client_init (IBusIMClient *client); -static void ibus_im_client_finalize (GObject *obj); - -static void ibus_im_client_commit_string(IBusIMClient *client, - const gchar *string); -static void ibus_im_client_update_preedit - (IBusIMClient *client, - const gchar *string, - PangoAttrList *attrs, - gint cursor_pos, - gboolean show); - -static void ibus_im_client_sync_hotkeys (IBusIMClient *client); +static void ibus_im_client_class_init (IBusIMClientClass *klass); +static void ibus_im_client_init (IBusIMClient *client); +static void ibus_im_client_finalize (GObject *obj); + +static const gchar * + _ibus_im_client_create_input_context + (IBusIMClient *client); + static gboolean _ibus_call_with_reply_and_block (DBusConnection *connection, const gchar *method, @@ -103,25 +90,28 @@ static gboolean _dbus_call_with_reply_and_block const gchar *path, const gchar *iface, const char *method, - int first_arg_type, + int first_arg_type, ...); +static GtkIMContext * + _ibus_client_ic_to_context (IBusIMClient *client, + const gchar *ic); /* callback functions */ static DBusHandlerResult _ibus_im_client_message_filter_cb - (DBusConnection *connection, - DBusMessage *message, - void *user_data); + (DBusConnection *connection, + DBusMessage *message, + void *user_data); -static void _dbus_name_owner_changed_cb (DBusGProxy *proxy, - const gchar *name, - const gchar *old_name, - const gchar *new_name, - IBusIMClient *client); +static void _dbus_name_owner_changed_cb + (DBusGProxy *proxy, + const gchar *name, + const gchar *old_name, + const gchar *new_name, + IBusIMClient *client); static GType ibus_type_im_client = 0; static GtkObjectClass *parent_class = NULL; -static IBusIMClient *_client = NULL; static gboolean has_focus = FALSE; @@ -157,21 +147,15 @@ ibus_im_client_register_type (GTypeModule *type_module) } } - IBusIMClient * -ibus_im_client_get_client (void) +ibus_im_client_new (void) { - if (_client == NULL) { - _client = IBUS_IM_CLIENT(g_object_new (IBUS_TYPE_IM_CLIENT, NULL)); - g_object_ref_sink (_client); - } - else { - g_object_ref (_client); - } + IBusIMClient *client; - return _client; -} + client = IBUS_IM_CLIENT(g_object_new (IBUS_TYPE_IM_CLIENT, NULL)); + return client; +} static void ibus_im_client_class_init (IBusIMClientClass *klass) @@ -221,7 +205,6 @@ _ibus_im_client_reinit_imm (IBusIMClient *client) return; } - ibus_im_client_sync_hotkeys (client); g_debug ("new imm %s", dbus_g_proxy_get_bus_name (priv->imm)); } #endif @@ -289,45 +272,69 @@ _ibus_im_client_ibus_open (IBusIMClient *client) return; } dbus_connection_setup_with_g_main (priv->ibus, NULL); - const gchar *app_name = g_get_application_name (); - gchar *ic = NULL; - _ibus_call_with_reply_and_block (priv->ibus, "CreateInputContext", - DBUS_TYPE_STRING, &app_name, - DBUS_TYPE_INVALID, - DBUS_TYPE_STRING, &ic, - DBUS_TYPE_INVALID); - priv->ic = g_strdup (ic); + + GList *p; + for (p = priv->contexts; p != NULL; p = g_list_next (p)) { + IBusIMContext *ctx = IBUS_IM_CONTEXT (p->data); + const gchar *ic = _ibus_im_client_create_input_context (client); + ibus_im_context_set_ic (ctx, ic); + } } static void _ibus_im_client_ibus_close (IBusIMClient *client) { - DBusError error; - IBusIMClientPrivate *priv = client->priv; + GList *p; + for (p = priv->contexts; p != NULL; p = g_list_next (p)) { + IBusIMContext *ctx = IBUS_IM_CONTEXT (p->data); + ibus_im_context_set_ic (ctx, NULL); + } + + g_hash_table_remove_all (priv->ic_table); + if (priv->ibus) { dbus_connection_close (priv->ibus); dbus_connection_unref (priv->ibus); priv->ibus = NULL; } +} - if (priv->preedit_string) { - g_free (priv->preedit_string); - priv->preedit_string = NULL; - } +IBusIMContext * +ibus_im_client_create_im_context (IBusIMClient *client) +{ + IBusIMContext *context; + IBusIMClientPrivate *priv = client->priv; - if (priv->preedit_attrs) { - pango_attr_list_unref (priv->preedit_attrs); - priv->preedit_attrs = NULL; - } + context = IBUS_IM_CONTEXT (ibus_im_context_new ()); + priv->contexts = g_list_append (priv->contexts, context); - if (priv->context) { - g_signal_emit_by_name (priv->context, "preedit-changed"); + const gchar *ic = _ibus_im_client_create_input_context (client); + ibus_im_context_set_ic (context, ic); + if (ic) { + g_hash_table_insert (priv->ic_table, (gpointer)g_strdup (ic), context); } + return context; +} + +static const gchar * +_ibus_im_client_create_input_context (IBusIMClient *client) +{ + IBusIMClientPrivate *priv = client->priv; + + if (priv->ibus == NULL) + return NULL; - priv->enable = FALSE; + const gchar *app_name = g_get_application_name (); + gchar *ic = NULL; + _ibus_call_with_reply_and_block (priv->ibus, "CreateInputContext", + DBUS_TYPE_STRING, &app_name, + DBUS_TYPE_INVALID, + DBUS_TYPE_STRING, &ic, + DBUS_TYPE_INVALID); + return ic; } #ifdef HAVE_INOTIFY @@ -385,12 +392,8 @@ ibus_im_client_init (IBusIMClient *obj) priv = G_TYPE_INSTANCE_GET_PRIVATE (client, IBUS_TYPE_IM_CLIENT, IBusIMClientPrivate); client->priv = priv; - priv->context = NULL; - - priv->preedit_string = NULL; - priv->preedit_attrs = NULL; - priv->preedit_cursor = 0; - priv->enable = FALSE; + priv->ic_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + priv->contexts = NULL; watch_path = g_strdup_printf ("/tmp/ibus-%s", g_get_user_name ()); @@ -513,54 +516,31 @@ ibus_im_client_finalize (GObject *obj) } -void -ibus_im_client_set_im_context (IBusIMClient *client, GtkIMContext *context) -{ - IBusIMClientPrivate *priv = client->priv; - priv->context = context; -} - -GtkIMContext * -ibus_im_client_get_im_context (IBusIMClient *client) -{ - IBusIMClientPrivate *priv = client->priv; - return priv->context; -} - static void -ibus_im_client_commit_string (IBusIMClient *client, const gchar *string) +ibus_im_client_commit_string (IBusIMClient *client, const gchar *ic, const gchar *string) { IBusIMClientPrivate *priv = client->priv; + IBusIMContext *context = g_hash_table_lookup (priv->ic_table, (gpointer)ic); - if (priv->context) { - g_signal_emit_by_name (priv->context, "commit", string); + if (context == NULL) { + g_debug ("Can not find context assocate with ic(%s)", ic); + return; } + g_signal_emit_by_name (G_OBJECT (context), "commit", string); } static void -ibus_im_client_update_preedit (IBusIMClient *client, const gchar *string, +ibus_im_client_update_preedit (IBusIMClient *client, const gchar *ic, const gchar *string, PangoAttrList *attrs, gint cursor_pos, gboolean show) { IBusIMClientPrivate *priv = client->priv; - if (priv->preedit_string) { - g_free (priv->preedit_string); - } - priv->preedit_string = g_strdup (string); - - if (priv->preedit_attrs) { - pango_attr_list_unref (priv->preedit_attrs); - } - - priv->preedit_attrs = attrs; - if (attrs) { - pango_attr_list_ref (priv->preedit_attrs); - } + IBusIMContext *context = g_hash_table_lookup (priv->ic_table, (gpointer)ic); - priv->preedit_cursor = cursor_pos; - priv->preedit_show = show; - if (priv->context) { - g_signal_emit_by_name (priv->context, "preedit-changed"); + if (context == NULL) { + g_debug ("Can not find context assocate with ic(%s)", ic); + return; } + ibus_im_context_update_preedit (context, string, attrs, cursor_pos, show); } static void @@ -580,11 +560,12 @@ _ibus_signal_commit_string_handler (DBusConnection *connection, DBusMessage *mes dbus_error_free (&error); } else { - if (g_strcmp0 (priv->ic, ic) != 0) { - g_warning ("ic is wrong!"); + IBusIMContext *context = g_hash_table_lookup (priv->ic_table, (gpointer)ic); + if (context == NULL) { + g_debug ("Can not find context assocate with ic(%s)", ic); return; } - ibus_im_client_commit_string (client, string); + ibus_im_context_commit_string (context, string); } } @@ -616,11 +597,6 @@ _ibus_signal_update_preedit_handler (DBusConnection *connection, DBusMessage *me dbus_message_iter_get_basic (&iter, &ic); dbus_message_iter_next (&iter); - if (g_strcmp0 (priv->ic, ic) != 0) { - g_warning ("ic is wrong!"); - return; - } - type = dbus_message_iter_get_arg_type (&iter); if (type != DBUS_TYPE_STRING) { g_warning ("The 2nd argument of UpdatePreedit signal must be a String"); @@ -717,7 +693,14 @@ _ibus_signal_update_preedit_handler (DBusConnection *connection, DBusMessage *me dbus_message_iter_get_basic (&iter, &show); dbus_message_iter_next (&iter); - ibus_im_client_update_preedit (client, string, attrs, cursor, show); + { + IBusIMContext *context = g_hash_table_lookup (priv->ic_table, (gpointer)ic); + if (context == NULL) { + g_debug ("Can not find context assocate with ic(%s)", ic); + return; + } + ibus_im_context_update_preedit (context, string, attrs, cursor, show); + } pango_attr_list_unref (attrs); } @@ -765,7 +748,25 @@ static void _ibus_signal_enabled_handler (DBusConnection *connection, DBusMessage *message, IBusIMClient *client) { DEBUG_FUNCTION_IN; - client->priv->enable = TRUE; + /* Handle CommitString signal */ + IBusIMClientPrivate *priv = client->priv; + DBusError error = {0}; + gchar *ic = NULL; + + if (!dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &ic, + DBUS_TYPE_INVALID)) { + g_warning ("%s", error.message); + dbus_error_free (&error); + } + else { + IBusIMContext *context = g_hash_table_lookup (priv->ic_table, (gpointer)ic); + if (context == NULL) { + g_debug ("Can not find context assocate with ic(%s)", ic); + return; + } + ibus_im_context_enable (context); + } } @@ -773,8 +774,28 @@ static void _ibus_signal_disabled_handler (DBusConnection *connection, DBusMessage *message, IBusIMClient *client) { DEBUG_FUNCTION_IN; - client->priv->enable = FALSE; + /* Handle CommitString signal */ + IBusIMClientPrivate *priv = client->priv; + DBusError error = {0}; + gchar *ic = NULL; + + if (!dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &ic, + DBUS_TYPE_INVALID)) { + g_warning ("%s", error.message); + dbus_error_free (&error); + } + else { + IBusIMContext *context = g_hash_table_lookup (priv->ic_table, (gpointer)ic); + if (context == NULL) { + g_debug ("Can not find context assocate with ic(%s)", ic); + return; + } + ibus_im_context_disable (context); + } } + + static DBusHandlerResult _ibus_im_client_message_filter_cb (DBusConnection *connection, DBusMessage *message, void *user_data) { @@ -1048,9 +1069,11 @@ _ibus_filter_keypress_reply_cb (DBusPendingCall *pending, void *user_data) } gboolean -ibus_im_client_filter_keypress (IBusIMClient *client, GdkEventKey *event) +ibus_im_client_filter_keypress (IBusIMClient *client, IBusIMContext *context, GdkEventKey *event) { IBusIMClientPrivate *priv = client->priv; + gchar *ic = ibus_im_context_get_ic (context); + g_return_val_if_fail (ic != NULL, FALSE); guint state = event->state & GDK_MODIFIER_MASK; gboolean is_press = event->type == GDK_KEY_PRESS; @@ -1065,7 +1088,7 @@ ibus_im_client_filter_keypress (IBusIMClient *client, GdkEventKey *event) _ibus_filter_keypress_reply_cb, gdk_event_copy ((GdkEvent *)event), (DBusFreeFunction)gdk_event_free, - DBUS_TYPE_STRING, &priv->ic, + DBUS_TYPE_STRING, &ic, DBUS_TYPE_UINT32, &event->keyval, DBUS_TYPE_BOOLEAN, &is_press, DBUS_TYPE_UINT32, &state, @@ -1077,96 +1100,62 @@ ibus_im_client_filter_keypress (IBusIMClient *client, GdkEventKey *event) void -ibus_im_client_focus_in (IBusIMClient *client) +ibus_im_client_focus_in (IBusIMClient *client, IBusIMContext *context) { IBusIMClientPrivate *priv = client->priv; + gchar *ic = ibus_im_context_get_ic (context); + g_return_if_fail (ic != NULL); + /* Call IBus FocusIn method */ - _ibus_call_with_reply_and_block (client->priv->ibus, + _ibus_call_with_reply_and_block (priv->ibus, "FocusIn", - DBUS_TYPE_STRING, &priv->ic, + DBUS_TYPE_STRING, &ic, DBUS_TYPE_INVALID, DBUS_TYPE_INVALID); } void -ibus_im_client_focus_out (IBusIMClient *client) +ibus_im_client_focus_out (IBusIMClient *client, IBusIMContext *context) { IBusIMClientPrivate *priv = client->priv; + gchar *ic = ibus_im_context_get_ic (context); + g_return_if_fail (ic != NULL); + /* Call IBus FocusOut method */ - _ibus_call_with_reply_and_block (client->priv->ibus, + _ibus_call_with_reply_and_block (priv->ibus, "FocusOut", - DBUS_TYPE_STRING, &priv->ic, + DBUS_TYPE_STRING, &ic, DBUS_TYPE_INVALID, DBUS_TYPE_INVALID); } void -ibus_im_client_reset (IBusIMClient *client) +ibus_im_client_reset (IBusIMClient *client, IBusIMContext *context) { IBusIMClientPrivate *priv = client->priv; + gchar *ic = ibus_im_context_get_ic (context); + g_return_if_fail (ic != NULL); + /* Call IBus Reset method */ - _ibus_call_with_reply_and_block (client->priv->ibus, + _ibus_call_with_reply_and_block (priv->ibus, "Reset", - DBUS_TYPE_STRING, &priv->ic, + DBUS_TYPE_STRING, &ic, DBUS_TYPE_INVALID, DBUS_TYPE_INVALID); } - -gboolean -ibus_im_client_get_preedit_string ( - IBusIMClient *client, - gchar **str, - PangoAttrList **attrs, - gint *cursor_pos -) -{ - IBusIMClientPrivate *priv = client->priv; - - if (!priv->preedit_show) { - if (str) *str = g_strdup (""); - if (attrs) *attrs = pango_attr_list_new (); - if (cursor_pos) *cursor_pos = 0; - return TRUE; - } - - if (str) { - *str = g_strdup (priv->preedit_string ? priv->preedit_string: ""); - } - - if (attrs) { - if (priv->preedit_attrs) { - *attrs = pango_attr_list_ref (priv->preedit_attrs); - } - else { - *attrs = pango_attr_list_new (); - } - } - - if (cursor_pos) { - *cursor_pos = priv->preedit_cursor; - } - - return TRUE; -} - - void -ibus_im_client_set_client_window (IBusIMClient *client, GdkWindow *window) -{ - IBusIMClientPrivate *priv = client->priv; -} - -void -ibus_im_client_set_cursor_location (IBusIMClient *client, GdkRectangle *area) +ibus_im_client_set_cursor_location (IBusIMClient *client, IBusIMContext *context, GdkRectangle *area) { IBusIMClientPrivate *priv = client->priv; + gchar *ic = ibus_im_context_get_ic (context); + g_return_if_fail (ic != NULL); _ibus_call_with_reply_and_block (client->priv->ibus, "SetCursorLocation", - DBUS_TYPE_STRING, &priv->ic, + DBUS_TYPE_STRING, &ic, DBUS_TYPE_INT32, &area->x, DBUS_TYPE_INT32, &area->y, DBUS_TYPE_INT32, &area->width, @@ -1176,43 +1165,22 @@ ibus_im_client_set_cursor_location (IBusIMClient *client, GdkRectangle *area) } -gboolean -ibus_im_client_is_enabled (IBusIMClient *client) -{ - return (client->priv->ibus != NULL) && (client->priv->enable); -} - -static void -ibus_im_client_sync_hotkeys (IBusIMClient *client) +void +ibus_im_client_release_im_context (IBusIMClient *client, IBusIMContext *context) { - GError *error; - gchar **hotkeys = NULL; - gint i; - IBusIMClientPrivate *priv = client->priv; -#if 0 - g_return_if_fail (priv->imm != NULL); - - error = NULL; - if (!dbus_g_proxy_call (priv->imm, "get_hotkeys", &error, - G_TYPE_INVALID, - G_TYPE_STRV, &hotkeys, - G_TYPE_INVALID)) { - if (error) { - g_warning ("%s", error->message); - g_error_free (error); - } - return; - } + gchar *ic = ibus_im_context_get_ic (context); + priv->contexts = g_list_remove (priv->contexts, context); + if (ic) { + g_hash_table_remove (priv->ic_table, ic); + _ibus_call_with_reply_and_block (priv->ibus, "ReleaseInputContext", + DBUS_TYPE_STRING, &ic, + DBUS_TYPE_INVALID, + DBUS_TYPE_INVALID); - for (i = 0; i < g_strv_length (hotkeys); i++) { - g_debug ("hotkeys[%d] = %s", i, hotkeys[i]); } - g_strfreev (hotkeys); -#endif } - /* Callback functions for slave context */ #if 0 static void diff --git a/gtk2/ibusimclient.h b/gtk2/ibusimclient.h index 48489d2..9ae8a3e 100644 --- a/gtk2/ibusimclient.h +++ b/gtk2/ibusimclient.h @@ -21,7 +21,7 @@ #define __IBUS_IM_CLIENT_H_ #include - +#include "ibusimcontext.h" /* * Type macros. */ @@ -42,7 +42,7 @@ #if 0 #define DEBUG_FUNCTION_IN g_debug("%s IN", __FUNCTION__); -#define DEBUG_FUNCTION_OUT g_debug("%s OUT", __FUNCTION__); +#define DEBUG_FUNCTION_OUT g_debug("%s OUT", __FUNCTION__); #else #define DEBUG_FUNCTION_IN #define DEBUG_FUNCTION_OUT @@ -70,27 +70,29 @@ struct _IBusIMClientClass { /* class members */ }; +extern IBusIMClient *_client; + GType ibus_im_client_get_type (void); -IBusIMClient *ibus_im_client_get_client (void); -void ibus_im_client_register_type (GTypeModule *type_module); +void ibus_im_client_register_type (GTypeModule *type_module); +IBusIMClient *ibus_im_client_new (void); +IBusIMContext *ibus_im_client_create_im_context (IBusIMClient *client); void ibus_im_client_shutdown (void); -void ibus_im_client_focus_in (IBusIMClient *client); -void ibus_im_client_focus_out (IBusIMClient *client); -void ibus_im_client_set_im_context (IBusIMClient *client, - GtkIMContext *context); -GtkIMContext *ibus_im_client_get_im_context (IBusIMClient *client); -void ibus_im_client_reset (IBusIMClient *client); +void ibus_im_client_focus_in (IBusIMClient *client, + IBusIMContext *context); +void ibus_im_client_focus_out (IBusIMClient *client, + IBusIMContext *context); +void ibus_im_client_reset (IBusIMClient *client, + IBusIMContext *context); gboolean ibus_im_client_filter_keypress (IBusIMClient *client, - GdkEventKey *key); -gboolean ibus_im_client_get_preedit_string - (IBusIMClient *client, - gchar **str, - PangoAttrList **attrs, - gint *cursor_pos); + IBusIMContext *context, + GdkEventKey *key); void ibus_im_client_set_cursor_location - (IBusIMClient *client, - GdkRectangle *area); + (IBusIMClient *client, + IBusIMContext *context, + GdkRectangle *area); gboolean ibus_im_client_is_enabled (IBusIMClient *client); +void ibus_im_client_release_im_context(IBusIMClient *client, + IBusIMContext *context); G_END_DECLS diff --git a/gtk2/ibusimcontext.c b/gtk2/ibusimcontext.c index 5b9c089..abf236b 100644 --- a/gtk2/ibusimcontext.c +++ b/gtk2/ibusimcontext.c @@ -26,27 +26,20 @@ #include "ibusimcontext.h" #include "ibusimclient.h" -/* define GOBJECT macros */ -#define IBUS_TYPE_IM_CONTEXT \ - (_ibus_type_im_context) -#define IBUS_IM_CONTEXT(obj) \ - (GTK_CHECK_CAST ((obj), IBUS_TYPE_IM_CONTEXT, IBusIMContext)) -#define IBUS_IM_CONTEXT_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), IBUS_TYPE_IM_CONTEXT, IBusIMContextClass)) -#define IBUS_IS_IM_CONTEXT(obj) \ - (GTK_CHECK_TYPE ((obj), IBUS_TYPE_IM_CONTEXT)) -#define IBUS_IS_IM_CONTEXT_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_IM_CONTEXT)) -#define IBUS_IM_CONTEXT_GET_CLASS(obj) \ - (GTK_CHECK_GET_CLASS ((obj), IBUS_TYPE_IM_CONTEXT, IBusIMContextClass)) - -#define CURRENT_CONTEXT (ibus_im_client_get_im_context (priv->client)) - /* IBusIMContextPriv */ struct _IBusIMContextPrivate { GtkIMContext *slave; - IBusIMClient *client; GdkWindow *client_window; + + /* enabled */ + gboolean enable; + gchar *ic; + + /* preedit status */ + gchar *preedit_string; + PangoAttrList *preedit_attrs; + gint preedit_cursor_pos; + gboolean preedit_visible; }; @@ -93,7 +86,7 @@ static void _slave_delete_surrounding_cb -static GType _ibus_type_im_context = 0; +GType _ibus_type_im_context = 0; static GtkIMContextClass *parent_class = NULL; void @@ -158,10 +151,20 @@ ibus_im_context_init (IBusIMContext *obj) GError *error; IBusIMContext *ibus = IBUS_IM_CONTEXT (obj); - ibus->priv = G_TYPE_INSTANCE_GET_PRIVATE (ibus, IBUS_TYPE_IM_CONTEXT, IBusIMContextPrivate); + IBusIMContextPrivate *priv = ibus->priv = + G_TYPE_INSTANCE_GET_PRIVATE (ibus, IBUS_TYPE_IM_CONTEXT, IBusIMContextPrivate); + + priv->client_window = NULL; + + // Init ibus status + priv->enable = FALSE; + + // Init preedit status + priv->preedit_string = NULL; + priv->preedit_attrs = NULL; + priv->preedit_cursor_pos = 0; + priv->preedit_visible = FALSE; - ibus->priv->client = ibus_im_client_get_client (); - ibus->priv->client_window = NULL; // Create slave im context ibus->priv->slave = gtk_im_context_simple_new (); @@ -187,13 +190,13 @@ ibus_im_context_finalize (GObject *obj) IBusIMContext *ibus = IBUS_IM_CONTEXT (obj); IBusIMContextPrivate *priv = ibus->priv; - if (GTK_IM_CONTEXT (ibus) == CURRENT_CONTEXT) { - ibus_im_client_focus_out (priv->client); - ibus_im_client_set_im_context (priv->client, NULL); - } + ibus_im_client_release_im_context (_client, ibus); g_object_unref (priv->slave); - g_object_unref (priv->client); + + // release preedit + if (priv->preedit_string) g_free (priv->preedit_string); + if (priv->preedit_attrs) pango_attr_list_unref (priv->preedit_attrs); G_OBJECT_CLASS(parent_class)->finalize (obj); } @@ -207,12 +210,10 @@ ibus_im_context_filter_keypress (GtkIMContext *context, IBusIMContext *ibus = IBUS_IM_CONTEXT (context); IBusIMContextPrivate *priv = ibus->priv; - if (context != CURRENT_CONTEXT) - return FALSE; - - if (ibus_im_client_filter_keypress (priv->client, event)) + if (ibus_im_client_filter_keypress (_client, ibus, event)) return TRUE; - return gtk_im_context_filter_keypress (priv->slave, event); + else + return gtk_im_context_filter_keypress (priv->slave, event); } static void @@ -223,12 +224,7 @@ ibus_im_context_focus_in (GtkIMContext *context) IBusIMContext *ibus = IBUS_IM_CONTEXT (context); IBusIMContextPrivate *priv = ibus->priv; - if (context != CURRENT_CONTEXT) { - ibus_im_client_focus_out (priv->client); - ibus_im_client_set_im_context (priv->client, context); - } - - ibus_im_client_focus_in (priv->client); + ibus_im_client_focus_in (_client, ibus); gtk_im_context_focus_in (priv->slave); } @@ -240,7 +236,7 @@ ibus_im_context_focus_out (GtkIMContext *context) IBusIMContext *ibus = IBUS_IM_CONTEXT (context); IBusIMContextPrivate *priv = ibus->priv; - ibus_im_client_focus_out (priv->client); + ibus_im_client_focus_out (_client, ibus); gtk_im_context_focus_out (priv->slave); } @@ -252,9 +248,7 @@ ibus_im_context_reset (GtkIMContext *context) IBusIMContext *ibus = IBUS_IM_CONTEXT (context); IBusIMContextPrivate *priv = ibus->priv; - if (context == CURRENT_CONTEXT) { - ibus_im_client_reset (priv->client); - } + ibus_im_client_reset (_client, ibus); gtk_im_context_reset (priv->slave); } @@ -270,12 +264,31 @@ ibus_im_context_get_preedit_string (GtkIMContext *context, IBusIMContext *ibus = IBUS_IM_CONTEXT (context); IBusIMContextPrivate *priv = ibus->priv; - if (context == CURRENT_CONTEXT && - ibus_im_client_is_enabled (priv->client)) { - ibus_im_client_get_preedit_string (priv->client, str, attrs, cursor_pos); - return; + if (priv->enable) { + if (priv->preedit_visible) { + if (str) { + *str = g_strdup (priv->preedit_string ? priv->preedit_string: ""); + } + + if (attrs) { + *attrs = priv->preedit_attrs ? + pango_attr_list_ref (priv->preedit_attrs): + pango_attr_list_new (); + } + + if (cursor_pos) { + *cursor_pos = priv->preedit_cursor_pos; + } + } + else { + if (str) *str = g_strdup (""); + if (attrs) *attrs = pango_attr_list_new (); + if (cursor_pos) *cursor_pos = 0; + } + } + else { + gtk_im_context_get_preedit_string (priv->slave, str, attrs, cursor_pos); } - gtk_im_context_get_preedit_string (ibus->priv->slave, str, attrs, cursor_pos); } @@ -286,8 +299,9 @@ ibus_im_context_set_client_window (GtkIMContext *context, GdkWindow *client) IBusIMContext *ibus = IBUS_IM_CONTEXT (context); IBusIMContextPrivate *priv = ibus->priv; + priv->client_window = client; - gtk_im_context_set_client_window (ibus->priv->slave, client); + gtk_im_context_set_client_window (priv->slave, client); } static void @@ -297,7 +311,8 @@ ibus_im_context_set_cursor_location (GtkIMContext *context, GdkRectangle *area) IBusIMContext *ibus = IBUS_IM_CONTEXT (context); IBusIMContextPrivate *priv = ibus->priv; - if (context == CURRENT_CONTEXT && ibus_im_client_is_enabled (priv->client)) { + + if (priv->enable) { /* It is the focused context */ gint x, y; if(priv->client_window) { @@ -305,7 +320,7 @@ ibus_im_context_set_cursor_location (GtkIMContext *context, GdkRectangle *area) area->x += x; area->y += y; } - ibus_im_client_set_cursor_location (priv->client, area); + ibus_im_client_set_cursor_location (_client, ibus, area); } gtk_im_context_set_cursor_location (priv->slave, area); } @@ -318,7 +333,7 @@ _slave_commit_cb (GtkIMContext *slave, gchar *string, IBusIMContext *context) IBusIMContextPrivate *priv = context->priv; #if 0 - if ((GtkIMContext *)context == CURRENT_CONTEXT && ibus_im_client_is_enabled (priv->client)) + if ((GtkIMContext *)context == CURRENT_CONTEXT && ibus_im_client_is_enabled (_client)) return; #endif g_signal_emit_by_name (context, "commit", string); @@ -329,8 +344,10 @@ _slave_preedit_changed_cb (GtkIMContext *slave, IBusIMContext *context) { DEBUG_FUNCTION_IN; IBusIMContextPrivate *priv = context->priv; - if ((GtkIMContext *)context == CURRENT_CONTEXT && ibus_im_client_is_enabled (priv->client)) + + if (priv->enable && priv->ic) return; + g_signal_emit_by_name (context, "preedit-changed"); } @@ -339,7 +356,8 @@ _slave_preedit_start_cb (GtkIMContext *slave, IBusIMContext *context) { DEBUG_FUNCTION_IN; IBusIMContextPrivate *priv = context->priv; - if ((GtkIMContext *)context == CURRENT_CONTEXT && ibus_im_client_is_enabled (priv->client)) + + if (priv->enable && priv->ic) return; g_signal_emit_by_name (context, "preedit-start"); } @@ -349,7 +367,8 @@ _slave_preedit_end_cb (GtkIMContext *slave, IBusIMContext *context) { DEBUG_FUNCTION_IN; IBusIMContextPrivate *priv = context->priv; - if ((GtkIMContext *)context == CURRENT_CONTEXT && ibus_im_client_is_enabled (priv->client)) + + if (priv->enable && priv->ic) return; g_signal_emit_by_name (context, "preedit-end"); } @@ -359,7 +378,8 @@ _slave_retrieve_surrounding_cb (GtkIMContext *slave, IBusIMContext *context) { DEBUG_FUNCTION_IN; IBusIMContextPrivate *priv = context->priv; - if ((GtkIMContext *)context == CURRENT_CONTEXT && ibus_im_client_is_enabled (priv->client)) + + if (priv->enable && priv->ic) return; g_signal_emit_by_name (context, "retrieve-surrounding"); } @@ -369,8 +389,58 @@ _slave_delete_surrounding_cb (GtkIMContext *slave, gint a1, gint a2, IBusIMConte { DEBUG_FUNCTION_IN; IBusIMContextPrivate *priv = context->priv; - if ((GtkIMContext *)context == CURRENT_CONTEXT && ibus_im_client_is_enabled (priv->client)) + + if (priv->enable && priv->ic) return; g_signal_emit_by_name (context, "delete-surrounding", a1, a2); } +gchar * +ibus_im_context_get_ic (IBusIMContext *context) +{ + IBusIMContextPrivate *priv = context->priv; + return priv->ic; +} + +void +ibus_im_context_set_ic (IBusIMContext *context, const gchar *ic) +{ + IBusIMContextPrivate *priv = context->priv; + if (priv->ic) g_free (priv->ic); + priv->ic = g_strdup (ic); +} + +void +ibus_im_context_enable (IBusIMContext *context) +{ + IBusIMContextPrivate *priv = context->priv; + priv->enable = TRUE; +} + +void +ibus_im_context_disable (IBusIMContext *context) +{ + IBusIMContextPrivate *priv = context->priv; + priv->enable = FALSE; +} + + +void +ibus_im_context_commit_string (IBusIMContext *context, const gchar *string) +{ + g_signal_emit_by_name (context, "commit", string); +} + +void +ibus_im_context_update_preedit (IBusIMContext *context, const gchar *string, + PangoAttrList *attrs, gint cursor_pos, gboolean show) +{ + IBusIMContextPrivate *priv = context->priv; + + priv->preedit_string = g_strdup (string); + priv->preedit_attrs = pango_attr_list_ref (attrs); + priv->preedit_cursor_pos = cursor_pos; + priv->preedit_visible = show; + + g_signal_emit_by_name (context, "preedit-changed"); +} diff --git a/gtk2/ibusimcontext.h b/gtk2/ibusimcontext.h index 074d1e6..9c6b5f2 100644 --- a/gtk2/ibusimcontext.h +++ b/gtk2/ibusimcontext.h @@ -25,6 +25,18 @@ /* * Type macros. */ +#define IBUS_TYPE_IM_CONTEXT \ + (_ibus_type_im_context) +#define IBUS_IM_CONTEXT(obj) \ + (GTK_CHECK_CAST ((obj), IBUS_TYPE_IM_CONTEXT, IBusIMContext)) +#define IBUS_IM_CONTEXT_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), IBUS_TYPE_IM_CONTEXT, IBusIMContextClass)) +#define IBUS_IS_IM_CONTEXT(obj) \ + (GTK_CHECK_TYPE ((obj), IBUS_TYPE_IM_CONTEXT)) +#define IBUS_IS_IM_CONTEXT_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_IM_CONTEXT)) +#define IBUS_IM_CONTEXT_GET_CLASS(obj) \ + (GTK_CHECK_GET_CLASS ((obj), IBUS_TYPE_IM_CONTEXT, IBusIMContextClass)) G_BEGIN_DECLS typedef struct _IBusIMContext IBusIMContext; @@ -42,10 +54,28 @@ struct _IBusIMContextClass { /* class members */ }; -GtkIMContext *ibus_im_context_new (void); -void ibus_im_context_register_type (GTypeModule *type_module); -void ibus_im_context_shutdown (void); +extern GType _ibus_type_im_context; +GtkIMContext + *ibus_im_context_new (void); +void ibus_im_context_register_type + (GTypeModule *type_module); +void ibus_im_context_shutdown + (void); +gchar *ibus_im_context_get_ic (IBusIMContext *context); +void ibus_im_context_set_ic (IBusIMContext *context, + const gchar *ic); +void ibus_im_context_enable (IBusIMContext *context); +void ibus_im_context_disable (IBusIMContext *context); +void ibus_im_context_commit_string + (IBusIMContext *context, + const gchar *string); +void ibus_im_context_update_preedit + (IBusIMContext *context, + const gchar *string, + PangoAttrList *attrs, + gint cursor_pos, + gboolean show); G_END_DECLS #endif -- 2.7.4