1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 /* vim:set et sts=4: */
3 /* ibus - The Input Bus
4 * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
5 * Copyright (C) 2008-2010 Red Hat, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
24 #include <sys/types.h>
35 #include "connection.h"
37 #include "factoryproxy.h"
38 #include "panelproxy.h"
39 #include "inputcontext.h"
44 /* instance members */
45 GHashTable *factory_dict;
50 GList *register_engine_list;
51 GList *component_list;
53 gboolean use_sys_layout;
54 gboolean embed_preedit_text;
55 gboolean enable_by_default;
57 BusRegistry *registry;
59 BusInputContext *focused_context;
62 IBusHotkeyProfile *hotkey_profile;
65 gboolean use_global_engine;
66 BusEngineProxy *global_engine;
67 gchar *global_previous_engine_name;
69 IBusHotkeyProfile *engines_hotkey_profile;
70 GHashTable *hotkey_to_engines_map;
73 struct _BusIBusImplClass {
74 IBusServiceClass parent;
88 static guint _signals[LAST_SIGNAL] = { 0 };
91 /* functions prototype */
92 static void bus_ibus_impl_destroy (BusIBusImpl *ibus);
93 static void bus_ibus_impl_service_method_call
94 (IBusService *service,
95 GDBusConnection *connection,
97 const gchar *object_path,
98 const gchar *interface_name,
99 const gchar *method_name,
100 GVariant *parameters,
101 GDBusMethodInvocation
105 static GVariant *ibus_ibus_impl_service_get_property
106 (IBusService *service,
107 GDBusConnection *connection,
109 const gchar *object_path,
110 const gchar *interface_name,
111 const gchar *property_name,
113 static gboolean ibus_ibus_impl_service_set_property
114 (IBusService *service,
115 GDBusConnection *connection,
117 const gchar *object_path,
118 const gchar *interface_name,
119 const gchar *property_name,
123 static void bus_ibus_impl_add_factory (BusIBusImpl *ibus,
124 BusFactoryProxy *factory);
125 static void bus_ibus_impl_set_trigger (BusIBusImpl *ibus,
127 static void bus_ibus_impl_set_next_engine_in_menu
130 static void bus_ibus_impl_set_previous_engine
133 static void bus_ibus_impl_set_preload_engines
136 static void bus_ibus_impl_set_use_sys_layout
139 static void bus_ibus_impl_set_embed_preedit_text
142 static void bus_ibus_impl_set_enable_by_default
145 static void bus_ibus_impl_set_use_global_engine
148 static void bus_ibus_impl_set_global_engine (BusIBusImpl *ibus,
149 BusEngineProxy *engine);
151 static void bus_ibus_impl_registry_changed (BusIBusImpl *ibus);
152 static void bus_ibus_impl_global_engine_changed
155 static void _factory_destroy_cb (BusFactoryProxy *factory,
158 static void bus_ibus_impl_set_context_engine_from_desc
160 BusInputContext *context,
161 IBusEngineDesc *engine_desc);
162 static void bus_ibus_impl_set_context_engine(BusIBusImpl *ibus,
163 BusInputContext *context,
164 BusEngineProxy *engine);
166 static gchar *bus_ibus_impl_load_global_engine_name_from_config
168 static void bus_ibus_impl_save_global_engine_name_to_config
171 static gchar *bus_ibus_impl_load_global_previous_engine_name_from_config
173 static void bus_ibus_impl_save_global_previous_engine_name_to_config
175 static void bus_ibus_impl_update_engines_hotkey_profile
178 static const gchar introspection_xml[] =
180 " <interface name='org.freedesktop.IBus'>"
181 " <method name='GetAddress'>"
182 " <arg direction='out' type='s' name='address' />"
184 " <method name='CreateInputContext'>"
185 " <arg direction='in' type='s' name='client_name' />"
186 " <arg direction='out' type='o' name='object_path' />"
188 " <method name='CurrentInputContext'>"
189 " <arg direction='out' type='o' name='object_path' />"
191 " <method name='RegisterComponent'>"
192 " <arg direction='in' type='v' name='component' />"
194 " <method name='ListEngines'>"
195 " <arg direction='out' type='av' name='engines' />"
197 " <method name='ListActiveEngines'>"
198 " <arg direction='out' type='av' name='engines' />"
200 " <method name='Exit'>"
201 " <arg direction='in' type='b' name='restart' />"
203 " <method name='Ping'>"
204 " <arg direction='in' type='v' name='data' />"
205 " <arg direction='out' type='v' name='data' />"
207 " <method name='GetUseSysLayout'>"
208 " <arg direction='out' type='b' name='enabled' />"
210 " <method name='GetUseGlobalEngine'>"
211 " <arg direction='out' type='b' name='enabled' />"
213 " <method name='GetGlobalEngine'>"
214 " <arg direction='out' type='v' name='desc' />"
216 " <method name='SetGlobalEngine'>"
217 " <arg direction='in' type='s' name='engine_name' />"
219 " <method name='IsGlobalEngineEnabled'>"
220 " <arg direction='out' type='b' name='enabled' />"
222 " <signal name='RegistryChanged'>"
224 " <signal name='GlobalEngineChanged'>"
230 G_DEFINE_TYPE(BusIBusImpl, bus_ibus_impl, IBUS_TYPE_SERVICE)
233 bus_ibus_impl_class_init (BusIBusImplClass *class)
235 IBUS_OBJECT_CLASS(class)->destroy = (IBusObjectDestroyFunc) bus_ibus_impl_destroy;
237 IBUS_SERVICE_CLASS (class)->service_method_call = bus_ibus_impl_service_method_call;
238 ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml);
242 _panel_destroy_cb (BusPanelProxy *panel,
245 g_assert (BUS_IS_PANEL_PROXY (panel));
246 g_assert (BUS_IS_IBUS_IMPL (ibus));
248 g_return_if_fail (ibus->panel == panel);
251 g_object_unref (panel);
255 bus_ibus_impl_set_hotkey (BusIBusImpl *ibus,
259 g_assert (BUS_IS_IBUS_IMPL (ibus));
261 ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
268 g_variant_iter_init (&iter, value);
269 const gchar *str = NULL;
270 while (g_variant_iter_loop (&iter,"&s", &str)) {
271 ibus_hotkey_profile_add_hotkey_from_string (ibus->hotkey_profile,
279 bus_ibus_impl_set_trigger (BusIBusImpl *ibus,
282 GQuark hotkey = g_quark_from_static_string ("trigger");
284 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
287 /* set default trigger */
288 ibus_hotkey_profile_add_hotkey (ibus->hotkey_profile,
296 bus_ibus_impl_set_next_engine_in_menu (BusIBusImpl *ibus,
299 GQuark hotkey = g_quark_from_static_string ("next-engine-in-menu");
300 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
304 bus_ibus_impl_set_previous_engine (BusIBusImpl *ibus,
307 GQuark hotkey = g_quark_from_static_string ("previous-engine");
308 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
312 bus_ibus_impl_set_preload_engines (BusIBusImpl *ibus,
315 GList *engine_list = NULL;
317 g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
318 g_list_free (ibus->engine_list);
320 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_ARRAY) {
322 g_variant_iter_init (&iter, value);
323 const gchar *engine_name = NULL;
324 while (g_variant_iter_loop (&iter, "&s", &engine_name)) {
325 IBusEngineDesc *engine = bus_registry_find_engine_by_name (ibus->registry, engine_name);
326 if (engine == NULL || g_list_find (engine_list, engine) != NULL)
328 engine_list = g_list_append (engine_list, engine);
332 g_list_foreach (engine_list, (GFunc) g_object_ref, NULL);
333 ibus->engine_list = engine_list;
335 if (ibus->engine_list) {
336 IBusComponent *component = ibus_component_get_from_engine ((IBusEngineDesc *) ibus->engine_list->data);
337 if (component && !ibus_component_is_running (component)) {
338 ibus_component_start (component, g_verbose);
342 bus_ibus_impl_update_engines_hotkey_profile (ibus);
346 bus_ibus_impl_set_use_sys_layout (BusIBusImpl *ibus,
349 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
350 ibus->use_sys_layout = g_variant_get_boolean (value);
355 bus_ibus_impl_set_embed_preedit_text (BusIBusImpl *ibus,
358 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
359 ibus->embed_preedit_text = g_variant_get_boolean (value);
364 bus_ibus_impl_set_enable_by_default (BusIBusImpl *ibus,
367 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
368 ibus->enable_by_default = g_variant_get_boolean (value);
373 bus_ibus_impl_set_use_global_engine (BusIBusImpl *ibus,
376 if (value == NULL || g_variant_classify (value) != G_VARIANT_CLASS_BOOLEAN)
379 gboolean new_value = g_variant_get_boolean (value);
380 if (ibus->use_global_engine == new_value)
384 /* turn on use_global_engine option */
385 ibus->use_global_engine = TRUE;
386 BusEngineProxy *engine = ibus->focused_context != NULL ?
387 bus_input_context_get_engine (ibus->focused_context) : NULL;
388 if (engine != NULL) {
389 bus_ibus_impl_set_global_engine (ibus, engine);
393 /* turn off use_global_engine option */
394 bus_ibus_impl_set_global_engine (ibus, NULL);
395 ibus->use_global_engine = FALSE;
396 g_free (ibus->global_previous_engine_name);
401 _engine_desc_cmp (IBusEngineDesc *desc1,
402 IBusEngineDesc *desc2)
404 return - ((gint) ibus_engine_desc_get_rank (desc1)) +
405 ((gint) ibus_engine_desc_get_rank (desc2));
409 bus_ibus_impl_set_default_preload_engines (BusIBusImpl *ibus)
411 g_assert (BUS_IS_IBUS_IMPL (ibus));
413 static gboolean done = FALSE;
415 if (done || ibus->config == NULL) {
419 GVariant *variant = ibus_config_get_value (ibus->config, "general", "preload_engines");
420 if (variant != NULL) {
422 g_variant_unref (variant);
427 gchar *lang = g_strdup (setlocale (LC_ALL, NULL));
428 gchar *p = index (lang, '.');
433 GList *engines = bus_registry_get_engines_by_language (ibus->registry, lang);
434 if (engines == NULL) {
435 p = index (lang, '_');
438 engines = bus_registry_get_engines_by_language (ibus->registry, lang);
443 /* sort engines by rank */
444 engines = g_list_sort (engines, (GCompareFunc) _engine_desc_cmp);
446 GVariantBuilder builder;
447 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
449 for (list = engines; list != NULL; list = list->next) {
450 IBusEngineDesc *desc = (IBusEngineDesc *)list->data;
451 /* ignore engines with rank <== 0 */
452 if (ibus_engine_desc_get_rank (desc) > 0)
453 g_variant_builder_add (&builder, "s", ibus_engine_desc_get_name (desc));
455 ibus_config_set_value (ibus->config,
456 "general", "preload_engines", g_variant_builder_end (&builder));
457 g_list_free (engines);
460 const static struct {
463 void ( *func) (BusIBusImpl *, GVariant *);
464 } bus_ibus_impl_config_items [] = {
465 { "general/hotkey", "trigger", bus_ibus_impl_set_trigger },
466 { "general/hotkey", "next_engine_in_menu", bus_ibus_impl_set_next_engine_in_menu },
467 { "general/hotkey", "previous_engine", bus_ibus_impl_set_previous_engine },
468 { "general", "preload_engines", bus_ibus_impl_set_preload_engines },
469 { "general", "use_system_keyboard_layout", bus_ibus_impl_set_use_sys_layout },
470 { "general", "use_global_engine", bus_ibus_impl_set_use_global_engine },
471 { "general", "embed_preedit_text", bus_ibus_impl_set_embed_preedit_text },
472 { "general", "enable_by_default", bus_ibus_impl_set_enable_by_default },
476 bus_ibus_impl_reload_config (BusIBusImpl *ibus)
478 g_assert (BUS_IS_IBUS_IMPL (ibus));
481 for (i = 0; i < G_N_ELEMENTS (bus_ibus_impl_config_items); i++) {
482 GVariant *variant = NULL;
483 if (ibus->config != NULL)
484 variant = ibus_config_get_value (ibus->config,
485 bus_ibus_impl_config_items[i].section,
486 bus_ibus_impl_config_items[i].key);
487 bus_ibus_impl_config_items[i].func (ibus, variant);
488 if (variant) g_variant_unref (variant);
493 _config_value_changed_cb (IBusConfig *config,
499 g_assert (IBUS_IS_CONFIG (config));
503 g_assert (BUS_IS_IBUS_IMPL (ibus));
506 for (i = 0; i < G_N_ELEMENTS (bus_ibus_impl_config_items); i++) {
507 if (g_strcmp0 (bus_ibus_impl_config_items[i].section, section) == 0 &&
508 g_strcmp0 (bus_ibus_impl_config_items[i].key, key) == 0) {
509 bus_ibus_impl_config_items[i].func (ibus, value);
516 _config_destroy_cb (IBusConfig *config,
519 g_assert (IBUS_IS_CONFIG (config));
520 g_assert (BUS_IS_IBUS_IMPL (ibus));
522 g_assert (ibus->config == config);
524 g_object_unref (ibus->config);
529 _registry_changed_cb (BusRegistry *registry,
532 bus_ibus_impl_registry_changed (ibus);
536 _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
538 const gchar *old_name,
539 const gchar *new_name,
542 g_assert (BUS_IS_DBUS_IMPL (dbus));
543 g_assert (name != NULL);
544 g_assert (old_name != NULL);
545 g_assert (new_name != NULL);
546 g_assert (BUS_IS_IBUS_IMPL (ibus));
548 if (g_strcmp0 (name, IBUS_SERVICE_PANEL) == 0) {
549 if (g_strcmp0 (new_name, "") != 0) {
550 BusConnection *connection;
552 if (ibus->panel != NULL) {
553 ibus_proxy_destroy ((IBusProxy *)ibus->panel);
554 /* panel should be NULL after destroy */
555 g_assert (ibus->panel == NULL);
558 connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
559 g_return_if_fail (connection != NULL);
561 ibus->panel = bus_panel_proxy_new (connection);
562 g_object_ref_sink (ibus->panel);
564 g_signal_connect (ibus->panel,
566 G_CALLBACK (_panel_destroy_cb),
569 if (ibus->focused_context != NULL) {
570 bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context);
574 else if (g_strcmp0 (name, IBUS_SERVICE_CONFIG) == 0) {
575 if (g_strcmp0 (new_name, "") != 0) {
576 BusConnection *connection;
578 if (ibus->config != NULL) {
579 ibus_proxy_destroy ((IBusProxy *)ibus->config);
580 /* config should be NULL */
581 g_assert (ibus->config == NULL);
584 connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
585 g_return_if_fail (connection != NULL);
587 ibus->config = g_initable_new (IBUS_TYPE_CONFIG,
590 "g-object-path", IBUS_PATH_CONFIG,
591 "g-interface-name", IBUS_INTERFACE_CONFIG,
592 "g-connection", bus_connection_get_dbus_connection (connection),
594 g_object_ref_sink (ibus->config);
596 g_signal_connect (ibus->config,
598 G_CALLBACK (_config_value_changed_cb),
601 g_signal_connect (ibus->config,
603 G_CALLBACK (_config_destroy_cb),
606 bus_ibus_impl_set_default_preload_engines (ibus);
607 bus_ibus_impl_reload_config (ibus);
611 BusFactoryProxy *factory = bus_registry_name_owner_changed (ibus->registry,
612 name, old_name, new_name);
614 if (factory != NULL) {
615 bus_ibus_impl_add_factory (ibus, factory);
620 bus_ibus_impl_init (BusIBusImpl *ibus)
622 ibus->factory_dict = g_hash_table_new_full (
626 (GDestroyNotify) g_object_unref);
628 ibus->engine_list = NULL;
629 ibus->register_engine_list = NULL;
630 ibus->contexts = NULL;
631 ibus->focused_context = NULL;
635 ibus->registry = bus_registry_new ();
637 g_signal_connect (ibus->registry,
639 G_CALLBACK (_registry_changed_cb),
641 #ifdef G_THREADS_ENABLED
642 extern gint g_monitor_timeout;
643 if (g_monitor_timeout != 0) {
644 /* Start the monitor of registry changes. */
645 bus_registry_start_monitor_changes (ibus->registry);
649 ibus->hotkey_profile = ibus_hotkey_profile_new ();
650 ibus->keymap = ibus_keymap_get ("us");
652 ibus->use_sys_layout = FALSE;
653 ibus->embed_preedit_text = TRUE;
654 ibus->enable_by_default = FALSE;
655 ibus->use_global_engine = FALSE;
656 ibus->global_engine = NULL;
657 ibus->global_previous_engine_name = NULL;
659 ibus->engines_hotkey_profile = NULL;
660 ibus->hotkey_to_engines_map = NULL;
662 bus_ibus_impl_reload_config (ibus);
664 g_signal_connect (BUS_DEFAULT_DBUS,
665 "name-owner-changed",
666 G_CALLBACK (_dbus_name_owner_changed_cb),
671 bus_ibus_impl_destroy (BusIBusImpl *ibus)
678 bus_registry_stop_all_components (ibus->registry);
684 while ((pid = waitpid (0, &status, WNOHANG)) > 0);
686 if (pid == -1) { /* all children finished */
689 if (pid == 0) { /* no child status changed */
692 if (timeout >= G_USEC_PER_SEC) {
695 old = signal (SIGTERM, SIG_IGN);
696 kill (-getpid (), SIGTERM);
697 signal (SIGTERM, old);
701 g_warning ("Not every child processes exited!");
708 g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
709 g_list_free (ibus->engine_list);
710 ibus->engine_list = NULL;
712 g_list_foreach (ibus->register_engine_list, (GFunc) g_object_unref, NULL);
713 g_list_free (ibus->register_engine_list);
714 ibus->register_engine_list = NULL;
716 if (ibus->factory_dict != NULL) {
717 g_hash_table_destroy (ibus->factory_dict);
718 ibus->factory_dict = NULL;
721 if (ibus->hotkey_profile != NULL) {
722 g_object_unref (ibus->hotkey_profile);
723 ibus->hotkey_profile = NULL;
726 if (ibus->keymap != NULL) {
727 g_object_unref (ibus->keymap);
731 if (ibus->global_engine) {
732 g_object_unref (ibus->global_engine);
733 ibus->global_engine = NULL;
736 g_free (ibus->global_previous_engine_name);
738 if (ibus->engines_hotkey_profile != NULL) {
739 g_object_unref (ibus->engines_hotkey_profile);
740 ibus->engines_hotkey_profile = NULL;
743 if (ibus->hotkey_to_engines_map) {
744 g_hash_table_unref (ibus->hotkey_to_engines_map);
745 ibus->hotkey_to_engines_map = NULL;
749 IBUS_OBJECT_CLASS(bus_ibus_impl_parent_class)->destroy (IBUS_OBJECT (ibus));
753 _ibus_get_address (BusIBusImpl *ibus,
754 GVariant *parameters,
755 GDBusMethodInvocation *invocation)
757 g_dbus_method_invocation_return_value (invocation,
758 g_variant_new ("(s)", bus_server_get_address ()));
763 _timeout_cb (gpointer data)
768 static BusFactoryProxy *
769 _get_factory_proxy(IBusEngineDesc *engine_desc)
771 BusFactoryProxy *factory = NULL;
773 /* Add a timeout to wake up g_main_context_iteration in every 0.5 second,
774 * and then to check the factory assocated with the engine_desc */
775 guint timeout_id = g_timeout_add (500, _timeout_cb, NULL);
777 GTimer *timer = g_timer_new ();
779 /* Leave the loop, if it spends more than 5 seconds */
780 while (g_timer_elapsed (timer, NULL) <= 5.0) {
781 if (g_main_context_iteration (NULL, TRUE)) {
782 factory = bus_factory_proxy_get_from_engine (engine_desc);
783 if (factory != NULL) {
789 g_source_remove (timeout_id);
790 g_timer_destroy (timer);
795 static BusEngineProxy *
796 bus_ibus_impl_create_engine (IBusEngineDesc *engine_desc)
799 BusFactoryProxy *factory;
800 BusEngineProxy *engine;
802 factory = bus_factory_proxy_get_from_engine (engine_desc);
804 if (factory == NULL) {
805 /* try to execute the engine */
806 comp = ibus_component_get_from_engine (engine_desc);
809 if (!ibus_component_is_running (comp)) {
810 ibus_component_start (comp, g_verbose);
812 factory = _get_factory_proxy (engine_desc);
815 if (factory == NULL) {
819 g_object_ref (factory);
820 engine = bus_factory_proxy_create_engine (factory, engine_desc);
821 g_object_unref (factory);
826 static IBusEngineDesc *
827 _find_engine_desc_by_name(BusIBusImpl *ibus,
828 const gchar *engine_name)
830 IBusEngineDesc *engine_desc = NULL;
833 /* find engine in registered engine list */
834 for (p = ibus->register_engine_list; p != NULL; p = p->next) {
835 engine_desc = (IBusEngineDesc *)p->data;
836 if (g_strcmp0 (ibus_engine_desc_get_name (engine_desc), engine_name) == 0)
840 /* find engine in preload engine list */
841 for (p = ibus->engine_list; p != NULL; p = p->next) {
842 engine_desc = (IBusEngineDesc *)p->data;
843 if (g_strcmp0 (ibus_engine_desc_get_name (engine_desc), engine_name) == 0)
851 _context_request_engine_cb (BusInputContext *context,
852 const gchar *engine_name,
855 IBusEngineDesc *engine_desc = NULL;
857 /* context should has focus before request an engine */
858 g_return_if_fail (bus_input_context_has_focus (context));
860 if (engine_name == NULL || engine_name[0] == '\0') {
861 /* Use global engine if possible. */
862 if (ibus->use_global_engine) {
863 if (ibus->global_engine) {
864 bus_ibus_impl_set_context_engine (ibus, context, ibus->global_engine);
868 gchar *name = bus_ibus_impl_load_global_engine_name_from_config (ibus);
870 engine_desc = _find_engine_desc_by_name (ibus, name);
875 /* request default engine */
877 if (ibus->register_engine_list) {
878 engine_desc = (IBusEngineDesc *)ibus->register_engine_list->data;
880 else if (ibus->engine_list) {
881 engine_desc = (IBusEngineDesc *)ibus->engine_list->data;
886 /* request engine by name */
887 engine_desc = _find_engine_desc_by_name (ibus, engine_name);
890 bus_ibus_impl_set_context_engine_from_desc (ibus, context, engine_desc);
894 bus_ibus_impl_context_request_next_engine_in_menu (BusIBusImpl *ibus,
895 BusInputContext *context)
897 BusEngineProxy *engine;
898 IBusEngineDesc *desc;
899 IBusEngineDesc *next_desc = NULL;
902 engine = bus_input_context_get_engine (context);
903 if (engine == NULL) {
904 _context_request_engine_cb (context, NULL, ibus);
908 desc = bus_engine_proxy_get_desc (engine);
910 p = g_list_find (ibus->register_engine_list, desc);
915 p = g_list_find (ibus->engine_list, desc);
922 next_desc = (IBusEngineDesc*) p->data;
925 if (ibus->register_engine_list) {
926 next_desc = (IBusEngineDesc *)ibus->register_engine_list->data;
928 else if (ibus->engine_list) {
929 next_desc = (IBusEngineDesc *)ibus->engine_list->data;
933 bus_ibus_impl_set_context_engine_from_desc (ibus, context, next_desc);
937 bus_ibus_impl_context_request_previous_engine (BusIBusImpl *ibus,
938 BusInputContext *context)
940 gchar *engine_name = NULL;
941 if (!ibus->use_global_engine) {
942 engine_name = (gchar *) g_object_get_data (G_OBJECT (context), "previous-engine-name");
945 if (!ibus->global_previous_engine_name) {
946 ibus->global_previous_engine_name = bus_ibus_impl_load_global_previous_engine_name_from_config (ibus);
948 engine_name = ibus->global_previous_engine_name;
952 * If the previous engine name is not found, switch to the next engine
953 * in the menu. This behavior is better than doing nothing.
956 bus_ibus_impl_context_request_next_engine_in_menu(ibus, context);
959 _context_request_engine_cb (context, engine_name, ibus);
963 _global_engine_destroy_cb (BusEngineProxy *engine,
966 if (ibus->global_engine != engine) {
970 g_signal_handlers_disconnect_by_func (ibus->global_engine,
971 G_CALLBACK (_global_engine_destroy_cb), ibus);
972 g_object_unref (ibus->global_engine);
973 ibus->global_engine = NULL;
977 bus_ibus_impl_set_global_engine (BusIBusImpl *ibus,
978 BusEngineProxy *engine)
980 g_assert (ibus->use_global_engine == TRUE);
982 if (ibus->global_engine == engine) {
986 g_free (ibus->global_previous_engine_name);
987 ibus->global_previous_engine_name = NULL;
988 if (ibus->global_engine) {
989 /* Save the current global engine's name as previous engine. */
990 const gchar *name = ibus_engine_desc_get_name (bus_engine_proxy_get_desc (ibus->global_engine));
991 ibus->global_previous_engine_name = g_strdup (name);
993 ibus_proxy_destroy ((IBusProxy *)ibus->global_engine);
994 /* global_engine should be NULL */
995 g_assert (ibus->global_engine == NULL);
998 if (engine != NULL && !IBUS_PROXY_DESTROYED (engine)) {
999 g_object_ref (engine);
1000 ibus->global_engine = engine;
1001 g_signal_connect (ibus->global_engine, "destroy",
1002 G_CALLBACK (_global_engine_destroy_cb), ibus);
1005 bus_ibus_impl_save_global_engine_name_to_config (ibus);
1006 bus_ibus_impl_save_global_previous_engine_name_to_config (ibus);
1007 bus_ibus_impl_global_engine_changed (ibus);
1011 bus_ibus_impl_set_context_engine_from_desc (BusIBusImpl *ibus,
1012 BusInputContext *context,
1013 IBusEngineDesc *engine_desc)
1015 if (engine_desc != NULL) {
1016 BusEngineProxy *engine = bus_ibus_impl_create_engine (engine_desc);
1017 if (engine != NULL) {
1018 bus_ibus_impl_set_context_engine (ibus, context, engine);
1024 bus_ibus_impl_set_context_engine (BusIBusImpl *ibus,
1025 BusInputContext *context,
1026 BusEngineProxy *engine) {
1027 g_object_set_data (G_OBJECT (context), "previous-engine-name", NULL);
1029 /* If use_global_engine is disabled, then we need to save the previous engine
1030 * of each input context. */
1031 if (!ibus->use_global_engine) {
1032 BusEngineProxy *previous_engine = bus_input_context_get_engine (context);
1033 if (previous_engine) {
1034 const gchar *name = ibus_engine_desc_get_name (bus_engine_proxy_get_desc (previous_engine));
1035 g_object_set_data_full (G_OBJECT (context), "previous-engine-name",
1041 bus_input_context_set_engine (context, engine);
1045 _context_engine_changed_cb (BusInputContext *context,
1048 BusEngineProxy *engine;
1050 if (context != ibus->focused_context || !ibus->use_global_engine) {
1054 engine = bus_input_context_get_engine (context);
1055 if (engine != NULL) {
1056 /* only set global engine if engine is not NULL */
1057 bus_ibus_impl_set_global_engine (ibus, engine);
1062 _context_focus_out_cb (BusInputContext *context,
1065 g_assert (BUS_IS_IBUS_IMPL (ibus));
1066 g_assert (BUS_IS_INPUT_CONTEXT (context));
1068 /* Do noting if context does not support focus.
1069 * Actually, the context should emit focus signals, if it does not support focus */
1070 if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
1074 /* Do noting if it is not focused context. */
1075 if (ibus->focused_context != context) {
1079 ibus->focused_context = NULL;
1081 if (ibus->panel != NULL) {
1082 bus_panel_proxy_focus_out (ibus->panel, context);
1085 /* If the use_global_engine option is enabled,
1086 * the global engine shoule be detached from the focused context. */
1087 if (ibus->use_global_engine) {
1088 bus_ibus_impl_set_context_engine (ibus, context, NULL);
1091 g_object_unref (context);
1095 _context_focus_in_cb (BusInputContext *context,
1098 g_assert (BUS_IS_IBUS_IMPL (ibus));
1099 g_assert (BUS_IS_INPUT_CONTEXT (context));
1101 /* Do nothing if context does not support focus.
1102 * The global engine shoule be detached from the focused context. */
1103 if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
1107 /* Do nothing if it is focused context already. */
1108 if (ibus->focused_context == context) {
1112 if (ibus->focused_context) {
1113 /* focus out context */
1114 bus_input_context_focus_out (ibus->focused_context);
1115 g_assert (ibus->focused_context == NULL);
1118 /* If the use_global_engine option is enabled, then we need:
1119 * - Switch the context to use the global engine or save the context's
1120 * existing engine as global engine.
1121 * - Set the context's enabled state according to the saved state.
1122 * Note: we get this signal only if the context supports IBUS_CAP_FOCUS. */
1123 if (ibus->use_global_engine) {
1124 if (!ibus->global_engine) {
1125 bus_ibus_impl_set_global_engine (ibus, bus_input_context_get_engine (context));
1128 bus_ibus_impl_set_context_engine (ibus, context, ibus->global_engine);
1129 if (ibus->global_engine && bus_engine_proxy_is_enabled (ibus->global_engine)) {
1130 bus_input_context_enable (context);
1135 if (ibus->panel != NULL) {
1136 bus_panel_proxy_focus_in (ibus->panel, context);
1139 g_object_ref (context);
1140 ibus->focused_context = context;
1144 _context_destroy_cb (BusInputContext *context,
1147 g_assert (BUS_IS_IBUS_IMPL (ibus));
1148 g_assert (BUS_IS_INPUT_CONTEXT (context));
1150 if (context == ibus->focused_context) {
1151 /* focus out context */
1152 bus_input_context_focus_out (ibus->focused_context);
1153 g_assert (ibus->focused_context == NULL);
1156 ibus->contexts = g_list_remove (ibus->contexts, context);
1157 g_object_unref (context);
1162 _context_enabled_cb (BusInputContext *context,
1168 _context_disabled_cb (BusInputContext *context,
1175 _ibus_create_input_context (BusIBusImpl *ibus,
1176 GVariant *parameters,
1177 GDBusMethodInvocation *invocation)
1179 const gchar *client_name = NULL;
1180 g_variant_get (parameters, "(&s)", &client_name);
1182 BusConnection *connection = bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
1183 BusInputContext *context = bus_input_context_new (connection, client_name);
1184 g_object_ref_sink (context);
1185 ibus->contexts = g_list_append (ibus->contexts, context);
1187 static const struct {
1191 { "request-engine", G_CALLBACK (_context_request_engine_cb) },
1192 { "engine-changed", G_CALLBACK (_context_engine_changed_cb) },
1193 { "focus-in", G_CALLBACK (_context_focus_in_cb) },
1194 { "focus-out", G_CALLBACK (_context_focus_out_cb) },
1195 { "destroy", G_CALLBACK (_context_destroy_cb) },
1197 { "enabled", G_CALLBACK (_context_enabled_cb) },
1198 { "disabled", G_CALLBACK (_context_disabled_cb) },
1203 for (i = 0; i < G_N_ELEMENTS (signals); i++) {
1204 g_signal_connect (context,
1206 signals[i].callback,
1210 if (ibus->enable_by_default) {
1211 bus_input_context_enable (context);
1214 const gchar *path = ibus_service_get_object_path ((IBusService *) context);
1215 bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
1216 (IBusService *)context);
1217 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
1221 _ibus_current_input_context (BusIBusImpl *ibus,
1222 GVariant *parameters,
1223 GDBusMethodInvocation *invocation)
1225 if (!ibus->focused_context)
1227 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1228 "No focused input context");
1231 const gchar *path = ibus_service_get_object_path ((IBusService *)ibus->focused_context);
1232 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
1237 _factory_destroy_cb (BusFactoryProxy *factory,
1240 g_assert (BUS_IS_IBUS_IMPL (ibus));
1241 g_assert (BUS_IS_FACTORY_PROXY (factory));
1243 IBusComponent *component;
1246 ibus->factory_list = g_list_remove (ibus->factory_list, factory);
1248 component = bus_factory_proxy_get_component (factory);
1250 if (component != NULL) {
1251 p = engines = ibus_component_get_engines (component);
1252 for (; p != NULL; p = p->next) {
1253 if (g_list_find (ibus->register_engine_list, p->data)) {
1254 ibus->register_engine_list = g_list_remove (ibus->register_engine_list, p->data);
1255 g_object_unref (p->data);
1258 g_list_free (engines);
1261 g_object_unref (factory);
1263 bus_ibus_impl_update_engines_hotkey_profile (ibus);
1267 bus_ibus_impl_add_factory (BusIBusImpl *ibus,
1268 BusFactoryProxy *factory)
1270 g_assert (BUS_IS_IBUS_IMPL (ibus));
1271 g_assert (BUS_IS_FACTORY_PROXY (factory));
1273 g_object_ref_sink (factory);
1274 ibus->factory_list = g_list_append (ibus->factory_list, factory);
1276 g_signal_connect (factory, "destroy", G_CALLBACK (_factory_destroy_cb), ibus);
1281 _ibus_register_component (BusIBusImpl *ibus,
1282 GVariant *parameters,
1283 GDBusMethodInvocation *invocation)
1285 GVariant *variant = g_variant_get_child_value (parameters, 0);
1286 IBusComponent *component = (IBusComponent *)ibus_serializable_deserialize (variant);
1288 if (!IBUS_IS_COMPONENT (component)) {
1290 g_object_unref (component);
1291 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1292 "The first argument should be an IBusComponent.");
1296 g_object_ref_sink (component);
1297 BusConnection *connection = bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
1298 BusFactoryProxy *factory = bus_factory_proxy_new (component, connection);
1300 if (factory == NULL) {
1301 g_object_unref (component);
1302 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1303 "Create factory failed.");
1307 bus_ibus_impl_add_factory (ibus, factory);
1309 GList *engines = ibus_component_get_engines (component);
1310 g_list_foreach (engines, (GFunc) g_object_ref, NULL);
1311 ibus->register_engine_list = g_list_concat (ibus->register_engine_list, engines);
1312 g_object_unref (component);
1314 bus_ibus_impl_update_engines_hotkey_profile (ibus);
1316 g_dbus_method_invocation_return_value (invocation, NULL);
1320 _ibus_list_engines (BusIBusImpl *ibus,
1321 GVariant *parameters,
1322 GDBusMethodInvocation *invocation)
1324 GVariantBuilder builder;
1325 g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1327 GList *engines = bus_registry_get_engines (ibus->registry);
1329 for (p = engines; p != NULL; p = p->next) {
1330 g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *)p->data));
1332 g_list_free (engines);
1333 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1337 _ibus_list_active_engines (BusIBusImpl *ibus,
1338 GVariant *parameters,
1339 GDBusMethodInvocation *invocation)
1341 GVariantBuilder builder;
1342 g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1345 for (p = ibus->engine_list; p != NULL; p = p->next) {
1346 g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *)p->data));
1348 for (p = ibus->register_engine_list; p != NULL; p = p->next) {
1349 g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *)p->data));
1351 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1356 _ibus_exit (BusIBusImpl *ibus,
1357 GVariant *parameters,
1358 GDBusMethodInvocation *invocation)
1360 gboolean restart = FALSE;
1361 g_variant_get (parameters, "(b)", &restart);
1363 g_dbus_method_invocation_return_value (invocation, NULL);
1371 extern gchar **g_argv;
1375 exe = g_strdup_printf ("/proc/%d/exe", getpid ());
1376 exe = g_file_read_link (exe, NULL);
1379 exe = BINDIR"/ibus-daemon";
1381 /* close all fds except stdin, stdout, stderr */
1382 for (fd = 3; fd <= sysconf (_SC_OPEN_MAX); fd ++) {
1386 execv (exe, g_argv);
1388 /* If the server binary is replaced while the server is running,
1389 * "readlink /proc/[pid]/exe" might return a path with " (deleted)"
1391 const gchar suffix[] = " (deleted)";
1392 if (g_str_has_suffix (exe, suffix)) {
1393 exe [strlen (exe) - sizeof (suffix) + 1] = '\0';
1394 execv (exe, g_argv);
1396 g_warning ("execv %s failed!", g_argv[0]);
1400 /* should not reach here */
1401 g_assert_not_reached ();
1405 _ibus_ping (BusIBusImpl *ibus,
1406 GVariant *parameters,
1407 GDBusMethodInvocation *invocation)
1409 g_dbus_method_invocation_return_value (invocation, parameters);
1413 _ibus_get_use_sys_layout (BusIBusImpl *ibus,
1414 GVariant *parameters,
1415 GDBusMethodInvocation *invocation)
1417 g_dbus_method_invocation_return_value (invocation,
1418 g_variant_new ("(b)", ibus->use_sys_layout));
1422 _ibus_get_use_global_engine (BusIBusImpl *ibus,
1423 GVariant *parameters,
1424 GDBusMethodInvocation *invocation)
1426 g_dbus_method_invocation_return_value (invocation,
1427 g_variant_new ("(b)", ibus->use_global_engine));
1431 _ibus_get_global_engine (BusIBusImpl *ibus,
1432 GVariant *parameters,
1433 GDBusMethodInvocation *invocation)
1435 if (ibus->use_global_engine && ibus->global_engine) {
1436 IBusEngineDesc *desc = bus_engine_proxy_get_desc (ibus->global_engine);
1438 GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)desc);
1439 g_dbus_method_invocation_return_value (invocation,
1440 g_variant_new ("(v)", variant));
1444 g_dbus_method_invocation_return_error (invocation,
1445 G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1446 "No global engine.");
1450 _ibus_set_global_engine (BusIBusImpl *ibus,
1451 GVariant *parameters,
1452 GDBusMethodInvocation *invocation)
1454 if (!ibus->use_global_engine) {
1455 g_dbus_method_invocation_return_error (invocation,
1456 G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1457 "Global engine feature is disabled.");
1461 const gchar *new_engine_name = NULL;
1462 g_variant_get (parameters, "(&s)", &new_engine_name);
1463 const gchar *old_engine_name = NULL;
1465 if (ibus->global_engine) {
1466 old_engine_name = ibus_engine_desc_get_name (bus_engine_proxy_get_desc (ibus->global_engine));
1469 if (g_strcmp0 (new_engine_name, old_engine_name) == 0) {
1470 /* If the user requested the same global engine, then we just enable the
1472 if (ibus->focused_context) {
1473 bus_input_context_enable (ibus->focused_context);
1475 else if (ibus->global_engine) {
1476 bus_engine_proxy_enable (ibus->global_engine);
1478 g_dbus_method_invocation_return_value (invocation, NULL);
1482 /* If there is a focused input context, then we just change the engine of
1483 * the focused context, which will then change the global engine
1484 * automatically. Otherwise, we need to change the global engine directly.
1486 if (ibus->focused_context) {
1487 _context_request_engine_cb (ibus->focused_context, new_engine_name, ibus);
1490 IBusEngineDesc *engine_desc = _find_engine_desc_by_name (ibus, new_engine_name);
1491 if (engine_desc != NULL) {
1492 BusEngineProxy *new_engine = bus_ibus_impl_create_engine (engine_desc);
1493 if (new_engine != NULL) {
1494 /* Enable the global engine by default, because the user
1495 * selected it explicitly. */
1496 bus_engine_proxy_enable (new_engine);
1498 /* Assume the ownership of the new global engine. Normally it's
1499 * done by the input context. But as we need to change the global
1500 * engine directly, so we need to do it here. */
1501 g_object_ref_sink (new_engine);
1502 bus_ibus_impl_set_global_engine (ibus, new_engine);
1504 /* The global engine should already be referenced. */
1505 g_object_unref (new_engine);
1509 g_dbus_method_invocation_return_value (invocation, NULL);
1513 _ibus_is_global_engine_enabled (BusIBusImpl *ibus,
1514 GVariant *parameters,
1515 GDBusMethodInvocation *invocation)
1517 gboolean enabled = (ibus->use_global_engine && ibus->global_engine &&
1518 bus_engine_proxy_is_enabled (ibus->global_engine));
1519 g_dbus_method_invocation_return_value (invocation,
1520 g_variant_new ("(b)", enabled));
1524 bus_ibus_impl_service_method_call (IBusService *service,
1525 GDBusConnection *connection,
1526 const gchar *sender,
1527 const gchar *object_path,
1528 const gchar *interface_name,
1529 const gchar *method_name,
1530 GVariant *parameters,
1531 GDBusMethodInvocation *invocation)
1533 if (g_strcmp0 (interface_name, "org.freedesktop.IBus") != 0) {
1534 IBUS_SERVICE_CLASS(bus_ibus_impl_parent_class)->service_method_call (
1535 service, connection, sender, object_path, interface_name, method_name,
1536 parameters, invocation);
1540 static const struct {
1541 const gchar *method_name;
1542 void (* method_callback) (BusIBusImpl *, GVariant *, GDBusMethodInvocation *);
1544 /* IBus interface */
1545 { "GetAddress", _ibus_get_address },
1546 { "CreateInputContext", _ibus_create_input_context },
1547 { "CurrentInputContext", _ibus_current_input_context },
1548 { "RegisterComponent", _ibus_register_component },
1549 { "ListEngines", _ibus_list_engines },
1550 { "ListActiveEngines", _ibus_list_active_engines },
1551 { "Exit", _ibus_exit },
1552 { "Ping", _ibus_ping },
1553 { "GetUseSysLayout", _ibus_get_use_sys_layout },
1554 { "GetUseGlobalEngine", _ibus_get_use_global_engine },
1555 { "GetGlobalEngine", _ibus_get_global_engine },
1556 { "SetGlobalEngine", _ibus_set_global_engine },
1557 { "IsGlobalEngineEnabled", _ibus_is_global_engine_enabled },
1561 for (i = 0; i < G_N_ELEMENTS (methods); i++) {
1562 if (g_strcmp0 (methods[i].method_name, method_name) == 0) {
1563 methods[i].method_callback ((BusIBusImpl *)service, parameters, invocation);
1567 g_return_if_reached ();
1571 bus_ibus_impl_get_default (void)
1573 static BusIBusImpl *ibus = NULL;
1576 ibus = (BusIBusImpl *) g_object_new (BUS_TYPE_IBUS_IMPL,
1577 "object-path", IBUS_PATH_IBUS,
1584 bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
1587 g_assert (BUS_IS_IBUS_IMPL (ibus));
1589 BusFactoryProxy *factory;
1591 factory = (BusFactoryProxy *) g_hash_table_lookup (ibus->factory_dict, path);
1597 bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus)
1599 g_assert (BUS_IS_IBUS_IMPL (ibus));
1601 return ibus->hotkey_profile;
1605 bus_ibus_impl_get_keymap (BusIBusImpl *ibus)
1608 g_assert (BUS_IS_IBUS_IMPL (ibus));
1610 return ibus->keymap;
1614 bus_ibus_impl_get_registry (BusIBusImpl *ibus)
1617 g_assert (BUS_IS_IBUS_IMPL (ibus));
1619 return ibus->registry;
1623 bus_ibus_impl_emit_signal (BusIBusImpl *ibus,
1624 const gchar *signal_name,
1625 GVariant *parameters)
1628 GDBusMessage *message = g_dbus_message_new_signal ("/org/freedesktop/IBus",
1629 "org.freedesktop.DBus",
1631 g_dbus_message_set_sender (message, "org.freedesktop.DBus");
1633 g_dbus_message_set_body (message, parameters);
1634 bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
1635 g_object_unref (message);
1639 bus_ibus_impl_registry_changed (BusIBusImpl *ibus)
1641 bus_ibus_impl_emit_signal (ibus, "RegistryChanged", NULL);
1645 bus_ibus_impl_global_engine_changed (BusIBusImpl *ibus)
1647 bus_ibus_impl_emit_signal (ibus, "GlobalEngineChanged", NULL);
1651 bus_ibus_impl_filter_keyboard_shortcuts (BusIBusImpl *ibus,
1652 BusInputContext *context,
1656 guint prev_modifiers)
1658 static GQuark trigger = 0;
1659 static GQuark next = 0;
1660 static GQuark previous = 0;
1666 trigger = g_quark_from_static_string ("trigger");
1667 next = g_quark_from_static_string ("next-engine-in-menu");
1668 previous = g_quark_from_static_string ("previous-engine");
1671 /* Try global hotkeys first. */
1672 event = ibus_hotkey_profile_filter_key_event (ibus->hotkey_profile,
1679 if (event == trigger) {
1680 gboolean enabled = bus_input_context_is_enabled (context);
1682 bus_input_context_disable (context);
1685 bus_input_context_enable (context);
1687 return (enabled != bus_input_context_is_enabled (context));
1689 if (event == next) {
1690 if (bus_input_context_is_enabled(context)) {
1691 bus_ibus_impl_context_request_next_engine_in_menu (ibus, context);
1694 bus_input_context_enable (context);
1698 if (event == previous) {
1699 if (bus_input_context_is_enabled(context)) {
1700 bus_ibus_impl_context_request_previous_engine (ibus, context);
1703 bus_input_context_enable (context);
1708 if (!ibus->engines_hotkey_profile || !ibus->hotkey_to_engines_map) {
1712 /* Then try engines hotkeys. */
1713 event = ibus_hotkey_profile_filter_key_event (ibus->engines_hotkey_profile,
1723 engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
1724 GUINT_TO_POINTER (event));
1726 BusEngineProxy *current_engine = bus_input_context_get_engine (context);
1727 IBusEngineDesc *current_engine_desc =
1728 (current_engine ? bus_engine_proxy_get_desc (current_engine) : NULL);
1729 IBusEngineDesc *new_engine_desc = (IBusEngineDesc *) engine_list->data;
1731 g_assert (new_engine_desc);
1733 /* Find out what engine we should switch to. If the current engine has
1734 * the same hotkey, then we should switch to the next engine with the
1735 * same hotkey in the list. Otherwise, we just switch to the first
1736 * engine in the list. */
1737 GList *p = engine_list;
1738 for (; p->next != NULL; p = p->next) {
1739 if (current_engine_desc == (IBusEngineDesc *) p->data) {
1740 new_engine_desc = (IBusEngineDesc *) p->next->data;
1745 if (current_engine_desc != new_engine_desc) {
1746 bus_ibus_impl_set_context_engine_from_desc (ibus, context, new_engine_desc);
1756 bus_ibus_impl_load_global_engine_name_from_config (BusIBusImpl *ibus)
1758 g_assert (BUS_IS_IBUS_IMPL (ibus));
1759 g_return_val_if_fail (IBUS_IS_CONFIG (ibus->config), NULL);
1761 GVariant *variant = ibus_config_get_value (ibus->config, "general", "global_engine");
1762 gchar *engine_name = NULL;
1763 if (variant != NULL) {
1764 g_variant_get (variant, "s", &engine_name);
1765 g_variant_unref (variant);
1771 bus_ibus_impl_save_global_engine_name_to_config (BusIBusImpl *ibus)
1773 g_assert (BUS_IS_IBUS_IMPL (ibus));
1774 g_return_if_fail (IBUS_IS_CONFIG (ibus->config));
1776 if (ibus->use_global_engine && ibus->global_engine) {
1777 IBusEngineDesc *desc = bus_engine_proxy_get_desc (ibus->global_engine);
1778 ibus_config_set_value (ibus->config,
1779 "general", "global_engine",
1780 g_variant_new ("s", ibus_engine_desc_get_name (desc)));
1785 bus_ibus_impl_load_global_previous_engine_name_from_config (BusIBusImpl *ibus)
1787 g_assert (BUS_IS_IBUS_IMPL (ibus));
1788 g_return_val_if_fail (IBUS_IS_CONFIG (ibus->config), NULL);
1790 GVariant *value = ibus_config_get_value (ibus->config, "general", "global_previous_engine");
1793 gchar *engine_name = NULL;
1794 g_variant_get (value, "(s)", &engine_name);
1795 g_variant_unref (value);
1800 bus_ibus_impl_save_global_previous_engine_name_to_config (BusIBusImpl *ibus)
1802 g_assert (BUS_IS_IBUS_IMPL (ibus));
1803 g_return_if_fail (IBUS_IS_CONFIG (ibus->config));
1805 if (ibus->use_global_engine && ibus->global_previous_engine_name) {
1806 ibus_config_set_value (ibus->config,
1807 "general", "global_previous_engine",
1808 g_variant_new ("s", ibus->global_previous_engine_name));
1813 _add_engine_hotkey (IBusEngineDesc *engine, BusIBusImpl *ibus)
1815 const gchar *hotkeys;
1816 gchar **hotkey_list;
1829 hotkeys = ibus_engine_desc_get_hotkeys (engine);
1831 if (!hotkeys || !*hotkeys) {
1835 hotkey_list = g_strsplit_set (hotkeys, ";,", 0);
1837 for (p = hotkey_list; p && *p; ++p) {
1838 hotkey = g_strstrip (*p);
1839 if (!*hotkey || !ibus_key_event_from_string (hotkey, &keyval, &modifiers)) {
1843 /* If the hotkey already exists, we won't need to add it again. */
1844 event = ibus_hotkey_profile_lookup_hotkey (ibus->engines_hotkey_profile,
1847 event = g_quark_from_string (hotkey);
1848 ibus_hotkey_profile_add_hotkey (ibus->engines_hotkey_profile,
1849 keyval, modifiers, event);
1852 engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
1853 GUINT_TO_POINTER (event));
1855 /* As we will rebuild the engines hotkey map whenever an engine was
1856 * added or removed, we don't need to hold a reference of the engine
1858 engine_list = g_list_append (engine_list, engine);
1860 /* We need to steal the value before adding it back, otherwise it will
1862 g_hash_table_steal (ibus->hotkey_to_engines_map, GUINT_TO_POINTER (event));
1864 g_hash_table_insert (ibus->hotkey_to_engines_map,
1865 GUINT_TO_POINTER (event), engine_list);
1868 g_strfreev (hotkey_list);
1872 bus_ibus_impl_update_engines_hotkey_profile (BusIBusImpl *ibus)
1874 if (ibus->engines_hotkey_profile) {
1875 g_object_unref (ibus->engines_hotkey_profile);
1878 if (ibus->hotkey_to_engines_map) {
1879 g_hash_table_unref (ibus->hotkey_to_engines_map);
1882 ibus->engines_hotkey_profile = ibus_hotkey_profile_new();
1883 ibus->hotkey_to_engines_map =
1884 g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_list_free);
1886 g_list_foreach (ibus->register_engine_list, (GFunc) _add_engine_hotkey, ibus);
1887 g_list_foreach (ibus->engine_list, (GFunc) _add_engine_hotkey, ibus);
1891 bus_ibus_impl_is_use_sys_layout (BusIBusImpl *ibus)
1893 g_assert (BUS_IS_IBUS_IMPL(ibus));
1895 return ibus->use_sys_layout;
1899 bus_ibus_impl_get_focused_input_context (BusIBusImpl *ibus)
1901 g_assert (BUS_IS_IBUS_IMPL(ibus));
1903 return ibus->focused_context;