From 9265deb7c084c5e37b8402de8d38c0e7b0671e2b Mon Sep 17 00:00:00 2001 From: Huang Peng Date: Tue, 24 Feb 2009 08:13:18 +0800 Subject: [PATCH] implement next_engine & prev_engine hotkeys. --- bus/ibusimpl.c | 178 +++++++++++++++++++++++++++++++++++++++-------------- bus/inputcontext.c | 41 ++++++++++-- bus/inputcontext.h | 5 +- 3 files changed, 172 insertions(+), 52 deletions(-) diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c index 053080f..c52907e 100644 --- a/bus/ibusimpl.c +++ b/bus/ibusimpl.c @@ -130,22 +130,18 @@ _panel_destroy_cb (BusPanelProxy *panel, } static void -bus_ibus_impl_set_trigger (BusIBusImpl *ibus, - GValue *value) +bus_ibus_impl_set_hotkey (BusIBusImpl *ibus, + GQuark hotkey, + GValue *value) { g_assert (BUS_IS_IBUS_IMPL (ibus)); GValueArray *array; gint i; - ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, - g_quark_from_static_string ("trigger")); + ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey); if (value == NULL) { - ibus_hotkey_profile_add_hotkey (ibus->hotkey_profile, - IBUS_space, - IBUS_CONTROL_MASK, - g_quark_from_static_string ("trigger")); return; } @@ -160,8 +156,39 @@ bus_ibus_impl_set_trigger (BusIBusImpl *ibus, ibus_hotkey_profile_add_hotkey_from_string (ibus->hotkey_profile, g_value_get_string (str), - g_quark_from_static_string ("trigger")); + hotkey); } + +} + +static void +bus_ibus_impl_set_trigger (BusIBusImpl *ibus, + GValue *value) +{ + GQuark hotkey = g_quark_from_static_string ("trigger"); + bus_ibus_impl_set_hotkey (ibus, hotkey, value); + if (value == NULL) { + ibus_hotkey_profile_add_hotkey (ibus->hotkey_profile, + IBUS_space, + IBUS_CONTROL_MASK, + hotkey); + } +} + +static void +bus_ibus_impl_set_next_engine (BusIBusImpl *ibus, + GValue *value) +{ + GQuark hotkey = g_quark_from_static_string ("next-engine"); + bus_ibus_impl_set_hotkey (ibus, hotkey, value); +} + +static void +bus_ibus_impl_set_prev_engine (BusIBusImpl *ibus, + GValue *value) +{ + GQuark hotkey = g_quark_from_static_string ("prev-engine"); + bus_ibus_impl_set_hotkey (ibus, hotkey, value); } static void @@ -214,6 +241,8 @@ bus_ibus_impl_reload_config (BusIBusImpl *ibus) void ( *func) (BusIBusImpl *, GValue *); } entries [] = { { "general/hotkey", "trigger", bus_ibus_impl_set_trigger }, + { "general/hotkey", "next_engine", bus_ibus_impl_set_next_engine }, + { "general/hotkey", "prev_engine", bus_ibus_impl_set_prev_engine }, { "general", "preload_engines", bus_ibus_impl_set_preload_engines }, { NULL, NULL, NULL }, }; @@ -253,8 +282,10 @@ _config_value_changed_cb (IBusConfig *config, gchar *key; void ( *func) (BusIBusImpl *, GValue *); } entries [] = { - { "general/hotkey", "trigger", bus_ibus_impl_set_trigger }, - { "general", "preload_engines", bus_ibus_impl_set_preload_engines }, + { "general/hotkey", "trigger", bus_ibus_impl_set_trigger }, + { "general/hotkey", "next_engine", bus_ibus_impl_set_next_engine }, + { "general/hotkey", "prev_engine", bus_ibus_impl_set_prev_engine }, + { "general", "preload_engines", bus_ibus_impl_set_preload_engines }, { NULL, NULL, NULL }, }; @@ -504,14 +535,58 @@ _ibus_get_address (BusIBusImpl *ibus, return reply; } +static BusEngineProxy * +bus_ibus_impl_create_engine (IBusEngineDesc *engine_desc) +{ + IBusComponent *comp; + BusFactoryProxy *factory; + BusEngineProxy *engine; + + factory = bus_factory_proxy_get_from_engine (engine_desc); + + if (factory == NULL) { + /* try to execute the engine */ + comp = ibus_component_get_from_engine (engine_desc); + g_assert (comp); + + if (!ibus_component_is_running (comp)) { + ibus_component_start (comp); + + gint time = 0; + while (time < G_USEC_PER_SEC * 3) { + if (g_main_context_pending (NULL)) { + g_main_context_iteration (NULL, FALSE); + } + else { + g_usleep (50 * 1000); + time += 50 * 1000; + } + factory = bus_factory_proxy_get_from_engine (engine_desc); + if (factory != NULL) { + break; + } + } + } + factory = bus_factory_proxy_get_from_engine (engine_desc); + } + + if (factory == NULL) { + return NULL; + } + + g_object_ref (factory); + engine = bus_factory_proxy_create_engine (factory, engine_desc); + g_object_unref (factory); + + return engine; +} + static void _context_request_engine_cb (BusInputContext *context, gchar *engine_name, BusIBusImpl *ibus) { IBusEngineDesc *engine_desc = NULL; - IBusComponent *comp; - BusFactoryProxy *factory; BusEngineProxy *engine; if (engine_name == NULL || engine_name[0] == '\0') { @@ -553,44 +628,15 @@ _context_request_engine_cb (BusInputContext *context, } } - if (engine_desc == NULL) + if (engine_desc == NULL) { return; - - factory = bus_factory_proxy_get_from_engine (engine_desc); - - if (factory == NULL) { - /* try to execute the engine */ - comp = ibus_component_get_from_engine (engine_desc); - g_assert (comp); - - if (!ibus_component_is_running (comp)) { - ibus_component_start (comp); - - gint time = 0; - while (time < G_USEC_PER_SEC * 3) { - if (g_main_context_pending (NULL)) { - g_main_context_iteration (NULL, FALSE); - } - else { - g_usleep (50 * 1000); - time += 50 * 1000; - } - factory = bus_factory_proxy_get_from_engine (engine_desc); - if (factory != NULL) { - break; - } - } - } - factory = bus_factory_proxy_get_from_engine (engine_desc); } - if (factory == NULL) - return; + engine = bus_ibus_impl_create_engine (engine_desc); - engine = bus_factory_proxy_create_engine (factory, engine_desc); - - if (engine == NULL) + if (engine == NULL) { return; + } bus_input_context_set_engine (context, engine); g_object_unref (engine); @@ -600,7 +646,47 @@ static void _context_request_next_engine_cb (BusInputContext *context, BusIBusImpl *ibus) { + BusEngineProxy *engine; + IBusEngineDesc *desc; + IBusEngineDesc *next_desc = NULL; + GList *p; + + engine = bus_input_context_get_engine (context); + if (engine == NULL) { + _context_request_engine_cb (context, NULL, ibus); + return; + } + + desc = bus_engine_proxy_get_desc (engine); + + p = g_list_find (ibus->register_engine_list, desc); + if (p != NULL) { + p = p->next; + } + if (p == NULL) { + p = g_list_find (ibus->engine_list, desc); + if (p != NULL) { + p = p->next; + } + } + if (p != NULL) { + next_desc = (IBusEngineDesc*) p->data; + } + else { + if (ibus->register_engine_list) { + next_desc = (IBusEngineDesc *)ibus->register_engine_list->data; + } + else if (ibus->engine_list) { + next_desc = (IBusEngineDesc *)ibus->engine_list->data; + } + } + + if (next_desc != NULL) { + engine = bus_ibus_impl_create_engine (next_desc); + bus_input_context_set_engine (context, engine); + g_object_unref (engine); + } } static void diff --git a/bus/inputcontext.c b/bus/inputcontext.c index 6ba7322..d857479 100644 --- a/bus/inputcontext.c +++ b/bus/inputcontext.c @@ -1022,7 +1022,7 @@ bus_input_context_ibus_message (BusInputContext *context, gboolean -bus_input_context_is_focus (BusInputContext *context) +bus_input_context_has_focus (BusInputContext *context) { g_assert (BUS_IS_INPUT_CONTEXT (context)); @@ -1425,7 +1425,6 @@ bus_input_context_disable (BusInputContext *context) BusInputContextPrivate *priv; priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); - if (priv->engine) { if (priv->has_focus) { bus_engine_proxy_focus_out (priv->engine); @@ -1443,6 +1442,17 @@ bus_input_context_disable (BusInputContext *context) priv->enabled = FALSE; } +gboolean +bus_input_context_is_enabled (BusInputContext *context) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + return priv->enabled; +} + const static struct { const gchar *name; GCallback callback; @@ -1492,7 +1502,6 @@ void bus_input_context_set_engine (BusInputContext *context, BusEngineProxy *engine) { - g_assert (BUS_IS_INPUT_CONTEXT (context)); BusInputContextPrivate *priv; @@ -1517,12 +1526,29 @@ bus_input_context_set_engine (BusInputContext *context, context); } bus_engine_proxy_set_cursor_location (priv->engine, priv->x, priv->y, priv->w, priv->h); + if (priv->enabled) { + bus_engine_proxy_enable (priv->engine); + if (priv->has_focus) { + bus_engine_proxy_focus_in (priv->engine); + } + } } g_signal_emit (context, context_signals[ENGINE_CHANGED], 0); } +BusEngineProxy * +bus_input_context_get_engine (BusInputContext *context) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + return priv->engine; +} + static gboolean bus_input_context_filter_keyboard_shortcuts (BusInputContext *context, guint keyval, @@ -1549,7 +1575,6 @@ bus_input_context_filter_keyboard_shortcuts (BusInputContext *context, keyval, modifiers, 0); - if (event == trigger) { if (priv->engine == NULL) { g_signal_emit (context, context_signals[REQUEST_ENGINE], 0, NULL); @@ -1569,9 +1594,17 @@ bus_input_context_filter_keyboard_shortcuts (BusInputContext *context, return TRUE; } else if (event == next_factory) { + g_signal_emit (context, context_signals[REQUEST_NEXT_ENGINE], 0); + if (priv->engine && !priv->enabled) { + bus_input_context_enable (context); + } return TRUE; } else if (event == prev_factory) { + g_signal_emit (context, context_signals[REQUEST_PREV_ENGINE], 0); + if (priv->engine && !priv->enabled) { + bus_input_context_enable (context); + } return TRUE; } else diff --git a/bus/inputcontext.h b/bus/inputcontext.h index edebdc0..537cbef 100644 --- a/bus/inputcontext.h +++ b/bus/inputcontext.h @@ -61,18 +61,19 @@ struct _BusInputContextClass { GType bus_input_context_get_type (void); BusInputContext *bus_input_context_new (BusConnection *connection, const gchar *client); -gboolean bus_input_context_is_focus (BusInputContext *context); void bus_input_context_focus_in (BusInputContext *context); void bus_input_context_focus_out (BusInputContext *context); -void bus_input_context_enable_or_disable(BusInputContext *context); +gboolean bus_input_context_has_focus (BusInputContext *context); void bus_input_context_enable (BusInputContext *context); void bus_input_context_disable (BusInputContext *context); +gboolean bus_input_context_is_enabled (BusInputContext *context); void bus_input_context_page_up (BusInputContext *context); void bus_input_context_page_down (BusInputContext *context); void bus_input_context_cursor_up (BusInputContext *context); void bus_input_context_cursor_down (BusInputContext *context); void bus_input_context_set_engine (BusInputContext *context, BusEngineProxy *factory); +BusEngineProxy *bus_input_context_get_engine (BusInputContext *context); void bus_input_context_property_activate(BusInputContext *context, const gchar *prop_name, gint prop_state); -- 2.7.4