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;
47 /* registered components */
48 GList *registered_components;
51 /* a fake input context for global engine support */
52 BusInputContext *fake_context;
54 /* a list of engines that are preloaded. */
56 /* a list of engines that are started by a user (without the --ibus command line flag.) */
57 GList *register_engine_list;
59 /* if TRUE, ibus-daemon uses a keysym translated by the system (i.e. XKB) as-is.
60 * otherwise, ibus-daemon itself converts keycode into keysym. */
61 gboolean use_sys_layout;
63 gboolean embed_preedit_text;
64 gboolean enable_by_default;
66 BusRegistry *registry;
68 BusInputContext *focused_context;
72 /* global hotkeys such as "trigger" and "next_engine_in_menu" */
73 IBusHotkeyProfile *hotkey_profile;
74 /* a default keymap of ibus-daemon (usually "us") which is used only when use_sys_layout is FALSE. */
77 gboolean use_global_engine;
78 gchar *global_engine_name;
79 gchar *global_previous_engine_name;
81 /* engine-specific hotkeys */
82 IBusHotkeyProfile *engines_hotkey_profile;
83 GHashTable *hotkey_to_engines_map;
86 struct _BusIBusImplClass {
87 IBusServiceClass parent;
101 static guint _signals[LAST_SIGNAL] = { 0 };
104 /* functions prototype */
105 static void bus_ibus_impl_destroy (BusIBusImpl *ibus);
106 static void bus_ibus_impl_service_method_call
107 (IBusService *service,
108 GDBusConnection *connection,
110 const gchar *object_path,
111 const gchar *interface_name,
112 const gchar *method_name,
113 GVariant *parameters,
114 GDBusMethodInvocation
116 /* TODO use property to replace some getter and setter in future */
118 static GVariant *ibus_ibus_impl_service_get_property
119 (IBusService *service,
120 GDBusConnection *connection,
122 const gchar *object_path,
123 const gchar *interface_name,
124 const gchar *property_name,
126 static gboolean ibus_ibus_impl_service_set_property
127 (IBusService *service,
128 GDBusConnection *connection,
130 const gchar *object_path,
131 const gchar *interface_name,
132 const gchar *property_name,
136 static void bus_ibus_impl_set_trigger (BusIBusImpl *ibus,
138 static void bus_ibus_impl_set_next_engine_in_menu
141 static void bus_ibus_impl_set_previous_engine
144 static void bus_ibus_impl_set_preload_engines
147 static void bus_ibus_impl_set_use_sys_layout
150 static void bus_ibus_impl_set_embed_preedit_text
153 static void bus_ibus_impl_set_enable_by_default
156 static void bus_ibus_impl_set_use_global_engine
159 static void bus_ibus_impl_registry_changed (BusIBusImpl *ibus);
160 static void bus_ibus_impl_global_engine_changed
162 static void bus_ibus_impl_set_context_engine_from_desc
164 BusInputContext *context,
165 IBusEngineDesc *desc);
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
177 static BusInputContext
178 *bus_ibus_impl_create_input_context
180 BusConnection *connection,
181 const gchar *client);
182 /* some callback functions */
183 static void _context_engine_changed_cb (BusInputContext *context,
186 /* The interfaces available in this class, which consists of a list of methods this class implements and
187 * a list of signals this class may emit. Method calls to the interface that are not defined in this XML
188 * will be automatically rejected by the GDBus library (see src/ibusservice.c for details.) */
189 static const gchar introspection_xml[] =
191 " <interface name='org.freedesktop.IBus'>\n"
192 " <method name='GetAddress'>\n"
193 " <arg direction='out' type='s' name='address' />\n"
195 " <method name='CreateInputContext'>\n"
196 " <arg direction='in' type='s' name='client_name' />\n"
197 " <arg direction='out' type='o' name='object_path' />\n"
199 " <method name='CurrentInputContext'>\n"
200 " <arg direction='out' type='o' name='object_path' />\n"
202 " <method name='RegisterComponent'>\n"
203 " <arg direction='in' type='v' name='component' />\n"
205 " <method name='ListEngines'>\n"
206 " <arg direction='out' type='av' name='engines' />\n"
208 " <method name='ListActiveEngines'>\n"
209 " <arg direction='out' type='av' name='engines' />\n"
211 " <method name='Exit'>\n"
212 " <arg direction='in' type='b' name='restart' />\n"
214 " <method name='Ping'>\n"
215 " <arg direction='in' type='v' name='data' />\n"
216 " <arg direction='out' type='v' name='data' />\n"
218 " <method name='GetUseSysLayout'>\n"
219 " <arg direction='out' type='b' name='enabled' />\n"
221 " <method name='GetUseGlobalEngine'>\n"
222 " <arg direction='out' type='b' name='enabled' />\n"
224 " <method name='GetGlobalEngine'>\n"
225 " <arg direction='out' type='v' name='desc' />\n"
227 " <method name='SetGlobalEngine'>\n"
228 " <arg direction='in' type='s' name='engine_name' />\n"
230 " <method name='IsGlobalEngineEnabled'>\n"
231 " <arg direction='out' type='b' name='enabled' />\n"
233 " <signal name='RegistryChanged'>\n"
235 " <signal name='GlobalEngineChanged'>\n"
241 G_DEFINE_TYPE (BusIBusImpl, bus_ibus_impl, IBUS_TYPE_SERVICE)
244 bus_ibus_impl_class_init (BusIBusImplClass *class)
246 IBUS_OBJECT_CLASS (class)->destroy = (IBusObjectDestroyFunc) bus_ibus_impl_destroy;
248 /* override the parent class's implementation. */
249 IBUS_SERVICE_CLASS (class)->service_method_call = bus_ibus_impl_service_method_call;
250 /* register the xml so that bus_ibus_impl_service_method_call will be called on a method call defined in the xml (e.g. 'GetAddress'.) */
251 ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml);
255 _panel_destroy_cb (BusPanelProxy *panel,
258 g_assert (BUS_IS_PANEL_PROXY (panel));
259 g_assert (BUS_IS_IBUS_IMPL (ibus));
261 g_return_if_fail (ibus->panel == panel);
264 g_object_unref (panel);
268 bus_ibus_impl_set_hotkey (BusIBusImpl *ibus,
272 g_assert (BUS_IS_IBUS_IMPL (ibus));
274 ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
281 g_variant_iter_init (&iter, value);
282 const gchar *str = NULL;
283 while (g_variant_iter_loop (&iter,"&s", &str)) {
284 ibus_hotkey_profile_add_hotkey_from_string (ibus->hotkey_profile,
292 * bus_ibus_impl_set_trigger:
294 * A function to be called when "trigger" config is updated. If the value is NULL, the default trigger (Ctrl+space) is set.
297 bus_ibus_impl_set_trigger (BusIBusImpl *ibus,
300 GQuark hotkey = g_quark_from_static_string ("trigger");
302 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
306 /* set default trigger */
307 ibus_hotkey_profile_add_hotkey (ibus->hotkey_profile,
316 * bus_ibus_impl_set_next_engine_in_menu:
318 * A function to be called when "next_engine_in_menu" config is updated.
321 bus_ibus_impl_set_next_engine_in_menu (BusIBusImpl *ibus,
324 GQuark hotkey = g_quark_from_static_string ("next-engine-in-menu");
325 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
329 * bus_ibus_impl_set_previous_engine:
331 * A function to be called when "previous_engine" config is updated.
334 bus_ibus_impl_set_previous_engine (BusIBusImpl *ibus,
337 GQuark hotkey = g_quark_from_static_string ("previous-engine");
338 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
342 * bus_ibus_impl_set_preload_engines:
344 * A function to be called when "preload_engines" config is updated.
347 bus_ibus_impl_set_preload_engines (BusIBusImpl *ibus,
350 GList *engine_list = NULL;
352 g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
353 g_list_free (ibus->engine_list);
355 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_ARRAY) {
357 g_variant_iter_init (&iter, value);
358 const gchar *engine_name = NULL;
359 while (g_variant_iter_loop (&iter, "&s", &engine_name)) {
360 IBusEngineDesc *engine = bus_registry_find_engine_by_name (ibus->registry, engine_name);
361 if (engine == NULL || g_list_find (engine_list, engine) != NULL)
363 engine_list = g_list_append (engine_list, engine);
367 g_list_foreach (engine_list, (GFunc) g_object_ref, NULL);
368 ibus->engine_list = engine_list;
370 if (ibus->engine_list) {
371 BusComponent *component = bus_component_from_engine_desc ((IBusEngineDesc *) ibus->engine_list->data);
372 if (component && !bus_component_is_running (component)) {
373 bus_component_start (component, g_verbose);
377 bus_ibus_impl_update_engines_hotkey_profile (ibus);
381 * bus_ibus_impl_set_use_sys_layout:
383 * A function to be called when "use_system_keyboard_layout" config is updated.
386 bus_ibus_impl_set_use_sys_layout (BusIBusImpl *ibus,
389 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
390 ibus->use_sys_layout = g_variant_get_boolean (value);
395 * bus_ibus_impl_set_embed_preedit_text:
397 * A function to be called when "use_embed_preedit_text" config is updated.
400 bus_ibus_impl_set_embed_preedit_text (BusIBusImpl *ibus,
403 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
404 ibus->embed_preedit_text = g_variant_get_boolean (value);
409 * bus_ibus_impl_set_enable_by_default:
411 * A function to be called when "enable_by_default" config is updated.
414 bus_ibus_impl_set_enable_by_default (BusIBusImpl *ibus,
417 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
418 ibus->enable_by_default = g_variant_get_boolean (value);
423 * bus_ibus_impl_set_use_global_engine:
425 * A function to be called when "use_global_engine" config is updated.
428 bus_ibus_impl_set_use_global_engine (BusIBusImpl *ibus,
431 if (value == NULL || g_variant_classify (value) != G_VARIANT_CLASS_BOOLEAN)
434 gboolean new_value = g_variant_get_boolean (value);
435 if (ibus->use_global_engine == new_value)
439 /* turn on use_global_engine option */
440 ibus->use_global_engine = TRUE;
443 /* turn off use_global_engine option */
444 ibus->use_global_engine = FALSE;
446 /* if fake context has the focus, we should focus out it */
447 if (ibus->panel && ibus->focused_context == NULL) {
448 bus_panel_proxy_focus_out (ibus->panel, ibus->fake_context);
450 /* remove engine in fake context */
451 bus_input_context_set_engine (ibus->fake_context, NULL);
456 _engine_desc_cmp (IBusEngineDesc *desc1,
457 IBusEngineDesc *desc2)
459 return - ((gint) ibus_engine_desc_get_rank (desc1)) +
460 ((gint) ibus_engine_desc_get_rank (desc2));
464 * bus_ibus_impl_set_default_preload_engines:
466 * If the "preload_engines" config variable is not set yet, set the default value which is determined based on a current locale (LC_ALL).
469 bus_ibus_impl_set_default_preload_engines (BusIBusImpl *ibus)
471 g_assert (BUS_IS_IBUS_IMPL (ibus));
473 static gboolean done = FALSE;
475 if (done || ibus->config == NULL) {
479 GVariant *variant = ibus_config_get_value (ibus->config, "general", "preload_engines");
480 if (variant != NULL) {
482 g_variant_unref (variant);
487 gchar *lang = g_strdup (setlocale (LC_ALL, NULL));
488 gchar *p = index (lang, '.');
493 GList *engines = bus_registry_get_engines_by_language (ibus->registry, lang);
494 if (engines == NULL) {
495 p = index (lang, '_');
498 engines = bus_registry_get_engines_by_language (ibus->registry, lang);
503 /* sort engines by rank */
504 engines = g_list_sort (engines, (GCompareFunc) _engine_desc_cmp);
506 GVariantBuilder builder;
507 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
509 for (list = engines; list != NULL; list = list->next) {
510 IBusEngineDesc *desc = (IBusEngineDesc *) list->data;
511 /* ignore engines with rank <= 0 */
512 if (ibus_engine_desc_get_rank (desc) > 0)
513 g_variant_builder_add (&builder, "s", ibus_engine_desc_get_name (desc));
515 ibus_config_set_value (ibus->config,
516 "general", "preload_engines", g_variant_builder_end (&builder));
517 g_list_free (engines);
520 /* The list of config entries that are related to ibus-daemon. */
521 const static struct {
524 void (*func) (BusIBusImpl *, GVariant *);
525 } bus_ibus_impl_config_items [] = {
526 { "general/hotkey", "trigger", bus_ibus_impl_set_trigger },
527 { "general/hotkey", "next_engine_in_menu", bus_ibus_impl_set_next_engine_in_menu },
528 { "general/hotkey", "previous_engine", bus_ibus_impl_set_previous_engine },
529 { "general", "preload_engines", bus_ibus_impl_set_preload_engines },
530 { "general", "use_system_keyboard_layout", bus_ibus_impl_set_use_sys_layout },
531 { "general", "use_global_engine", bus_ibus_impl_set_use_global_engine },
532 { "general", "embed_preedit_text", bus_ibus_impl_set_embed_preedit_text },
533 { "general", "enable_by_default", bus_ibus_impl_set_enable_by_default },
537 * bus_ibus_impl_reload_config
539 * Read config entries (e.g. preload_engines) from the config daemon.
542 bus_ibus_impl_reload_config (BusIBusImpl *ibus)
544 g_assert (BUS_IS_IBUS_IMPL (ibus));
547 for (i = 0; i < G_N_ELEMENTS (bus_ibus_impl_config_items); i++) {
548 GVariant *variant = NULL;
549 if (ibus->config != NULL)
550 variant = ibus_config_get_value (ibus->config,
551 bus_ibus_impl_config_items[i].section,
552 bus_ibus_impl_config_items[i].key);
553 bus_ibus_impl_config_items[i].func (ibus, variant); /* variant could be NULL if the deamon is not ready yet. */
554 if (variant) g_variant_unref (variant);
559 * _config_value_changed_cb:
561 * A callback function to be called when the "ValueChanged" D-Bus signal is sent from the config daemon.
564 _config_value_changed_cb (IBusConfig *config,
570 g_assert (IBUS_IS_CONFIG (config));
574 g_assert (BUS_IS_IBUS_IMPL (ibus));
577 for (i = 0; i < G_N_ELEMENTS (bus_ibus_impl_config_items); i++) {
578 if (g_strcmp0 (bus_ibus_impl_config_items[i].section, section) == 0 &&
579 g_strcmp0 (bus_ibus_impl_config_items[i].key, key) == 0) {
580 bus_ibus_impl_config_items[i].func (ibus, value);
587 _config_destroy_cb (IBusConfig *config,
590 g_assert (IBUS_IS_CONFIG (config));
591 g_assert (BUS_IS_IBUS_IMPL (ibus));
593 g_assert (ibus->config == config);
595 g_object_unref (ibus->config);
600 _registry_changed_cb (BusRegistry *registry,
603 bus_ibus_impl_registry_changed (ibus);
607 * _dbus_name_owner_changed_cb:
609 * A callback function to be called when the name-owner-changed signal is sent to the dbus object.
610 * This usually means a client (e.g. a panel/config/engine process or an application) is connected/disconnected to/from the bus.
613 _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
615 const gchar *old_name,
616 const gchar *new_name,
619 g_assert (BUS_IS_DBUS_IMPL (dbus));
620 g_assert (name != NULL);
621 g_assert (old_name != NULL);
622 g_assert (new_name != NULL);
623 g_assert (BUS_IS_IBUS_IMPL (ibus));
625 if (g_strcmp0 (name, IBUS_SERVICE_PANEL) == 0) {
626 if (g_strcmp0 (new_name, "") != 0) {
627 /* a Panel process is started. */
628 BusConnection *connection;
630 if (ibus->panel != NULL) {
631 ibus_proxy_destroy ((IBusProxy *) ibus->panel);
632 /* panel should be NULL after destroy */
633 g_assert (ibus->panel == NULL);
636 connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
637 g_return_if_fail (connection != NULL);
639 ibus->panel = bus_panel_proxy_new (connection);
641 g_signal_connect (ibus->panel,
643 G_CALLBACK (_panel_destroy_cb),
646 if (ibus->focused_context != NULL) {
647 bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context);
651 else if (g_strcmp0 (name, IBUS_SERVICE_CONFIG) == 0) {
652 if (g_strcmp0 (new_name, "") != 0) {
653 /* a config process is started. */
654 BusConnection *connection;
656 if (ibus->config != NULL) {
657 ibus_proxy_destroy ((IBusProxy *) ibus->config);
658 /* config should be NULL */
659 g_assert (ibus->config == NULL);
662 /* get a connection between ibus-daemon and the config daemon. */
663 connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
664 g_return_if_fail (connection != NULL);
666 ibus->config = g_initable_new (IBUS_TYPE_CONFIG,
669 /* The following properties are necessary to initialize GDBusProxy object
670 * which is a parent of the config object. */
671 "g-object-path", IBUS_PATH_CONFIG,
672 "g-interface-name", IBUS_INTERFACE_CONFIG,
673 "g-connection", bus_connection_get_dbus_connection (connection),
676 g_signal_connect (ibus->config,
678 G_CALLBACK (_config_value_changed_cb),
681 g_signal_connect (ibus->config,
683 G_CALLBACK (_config_destroy_cb),
686 bus_ibus_impl_set_default_preload_engines (ibus);
687 bus_ibus_impl_reload_config (ibus);
691 bus_registry_name_owner_changed (ibus->registry, name, old_name, new_name);
695 * bus_ibus_impl_init:
697 * The constructor of BusIBusImpl. Initialize all member variables of a BusIBusImpl object.
700 bus_ibus_impl_init (BusIBusImpl *ibus)
702 ibus->factory_dict = g_hash_table_new_full (
706 (GDestroyNotify) g_object_unref);
708 ibus->fake_context = bus_input_context_new (NULL, "fake");
709 g_object_ref_sink (ibus->fake_context);
710 bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
711 (IBusService *) ibus->fake_context);
712 bus_input_context_set_capabilities (ibus->fake_context,
713 IBUS_CAP_PREEDIT_TEXT |
715 IBUS_CAP_SURROUNDING_TEXT);
716 g_signal_connect (ibus->fake_context,
718 G_CALLBACK (_context_engine_changed_cb),
720 bus_input_context_focus_in (ibus->fake_context);
722 ibus->engine_list = NULL;
723 ibus->register_engine_list = NULL;
724 ibus->contexts = NULL;
725 ibus->focused_context = NULL;
729 ibus->registry = bus_registry_new ();
731 g_signal_connect (ibus->registry,
733 G_CALLBACK (_registry_changed_cb),
735 #ifdef G_THREADS_ENABLED
736 extern gint g_monitor_timeout;
737 if (g_monitor_timeout != 0) {
738 /* Start the monitor of registry changes. */
739 bus_registry_start_monitor_changes (ibus->registry);
743 ibus->hotkey_profile = ibus_hotkey_profile_new ();
744 ibus->keymap = ibus_keymap_get ("us");
746 ibus->use_sys_layout = FALSE;
747 ibus->embed_preedit_text = TRUE;
748 ibus->enable_by_default = FALSE;
749 ibus->use_global_engine = FALSE;
750 ibus->global_engine_name = NULL;
751 ibus->global_previous_engine_name = NULL;
753 ibus->engines_hotkey_profile = NULL;
754 ibus->hotkey_to_engines_map = NULL;
756 bus_ibus_impl_reload_config (ibus);
758 g_signal_connect (BUS_DEFAULT_DBUS,
759 "name-owner-changed",
760 G_CALLBACK (_dbus_name_owner_changed_cb),
765 * bus_ibus_impl_destroy:
767 * The destructor of BusIBusImpl.
770 bus_ibus_impl_destroy (BusIBusImpl *ibus)
777 bus_registry_stop_all_components (ibus->registry);
783 while ((pid = waitpid (0, &status, WNOHANG)) > 0);
785 if (pid == -1) { /* all children finished */
788 if (pid == 0) { /* no child status changed */
791 if (timeout >= G_USEC_PER_SEC) {
794 old = signal (SIGTERM, SIG_IGN);
795 /* send TERM signal to the whole process group (i.e. engines, panel, and config daemon.) */
796 kill (-getpid (), SIGTERM);
797 signal (SIGTERM, old);
801 g_warning ("Not every child processes exited!");
808 g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
809 g_list_free (ibus->engine_list);
810 ibus->engine_list = NULL;
812 g_list_foreach (ibus->register_engine_list, (GFunc) g_object_unref, NULL);
813 g_list_free (ibus->register_engine_list);
814 ibus->register_engine_list = NULL;
816 if (ibus->factory_dict != NULL) {
817 g_hash_table_destroy (ibus->factory_dict);
818 ibus->factory_dict = NULL;
821 if (ibus->hotkey_profile != NULL) {
822 g_object_unref (ibus->hotkey_profile);
823 ibus->hotkey_profile = NULL;
826 if (ibus->keymap != NULL) {
827 g_object_unref (ibus->keymap);
831 g_free (ibus->global_engine_name);
832 ibus->global_engine_name = NULL;
834 g_free (ibus->global_previous_engine_name);
835 ibus->global_previous_engine_name = NULL;
837 if (ibus->engines_hotkey_profile != NULL) {
838 g_object_unref (ibus->engines_hotkey_profile);
839 ibus->engines_hotkey_profile = NULL;
842 if (ibus->hotkey_to_engines_map) {
843 g_hash_table_unref (ibus->hotkey_to_engines_map);
844 ibus->hotkey_to_engines_map = NULL;
847 if (ibus->fake_context) {
848 g_object_unref (ibus->fake_context);
849 ibus->fake_context = NULL;
853 IBUS_OBJECT_CLASS (bus_ibus_impl_parent_class)->destroy (IBUS_OBJECT (ibus));
859 * Implement the "GetAddress" method call of the org.freedesktop.IBus interface.
862 _ibus_get_address (BusIBusImpl *ibus,
863 GVariant *parameters,
864 GDBusMethodInvocation *invocation)
866 g_dbus_method_invocation_return_value (invocation,
867 g_variant_new ("(s)", bus_server_get_address ()));
870 static IBusEngineDesc *
871 _find_engine_desc_by_name (BusIBusImpl *ibus,
872 const gchar *engine_name)
874 IBusEngineDesc *desc = NULL;
877 /* find engine in registered engine list */
878 for (p = ibus->register_engine_list; p != NULL; p = p->next) {
879 desc = (IBusEngineDesc *) p->data;
880 if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
884 /* find engine in preload engine list */
885 for (p = ibus->engine_list; p != NULL; p = p->next) {
886 desc = (IBusEngineDesc *) p->data;
887 if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
895 * _context_request_engine_cb:
897 * A callback function to be called when the "request-engine" signal is sent to the context.
900 _context_request_engine_cb (BusInputContext *context,
901 const gchar *engine_name,
904 IBusEngineDesc *desc = NULL;
906 /* context should has focus before request an engine */
907 g_return_if_fail (bus_input_context_has_focus (context) ||
908 context == ibus->focused_context);
910 if (engine_name != NULL && engine_name[0] != '\0') {
911 /* request engine by name */
912 desc = _find_engine_desc_by_name (ibus, engine_name);
913 g_return_if_fail (desc != NULL);
916 /* Use global engine if possible. */
917 if (ibus->use_global_engine) {
918 gchar *name = g_strdup (ibus->global_engine_name);
920 name = bus_ibus_impl_load_global_engine_name_from_config (ibus);
923 desc = _find_engine_desc_by_name (ibus, name);
927 /* request default engine */
929 if (ibus->register_engine_list) {
930 desc = (IBusEngineDesc *) ibus->register_engine_list->data;
932 else if (ibus->engine_list) {
933 desc = (IBusEngineDesc *) ibus->engine_list->data;
936 g_return_if_fail (desc != NULL);
939 bus_ibus_impl_set_context_engine_from_desc (ibus, context, desc);
943 * bus_ibus_impl_context_request_next_engine_in_menu:
945 * Process the "next_engine_in_menu" hotkey.
948 bus_ibus_impl_context_request_next_engine_in_menu (BusIBusImpl *ibus,
949 BusInputContext *context)
951 BusEngineProxy *engine;
952 IBusEngineDesc *desc;
953 IBusEngineDesc *next_desc = NULL;
956 engine = bus_input_context_get_engine (context);
957 if (engine == NULL) {
958 _context_request_engine_cb (context, NULL, ibus);
962 desc = bus_engine_proxy_get_desc (engine);
964 p = g_list_find (ibus->register_engine_list, desc);
969 p = g_list_find (ibus->engine_list, desc);
976 next_desc = (IBusEngineDesc*) p->data;
979 if (ibus->register_engine_list) {
980 next_desc = (IBusEngineDesc *) ibus->register_engine_list->data;
982 else if (ibus->engine_list) {
983 next_desc = (IBusEngineDesc *) ibus->engine_list->data;
987 bus_ibus_impl_set_context_engine_from_desc (ibus, context, next_desc);
991 * bus_ibus_impl_context_request_previous_engine:
993 * Process the "previous_engine" hotkey.
996 bus_ibus_impl_context_request_previous_engine (BusIBusImpl *ibus,
997 BusInputContext *context)
999 gchar *engine_name = NULL;
1000 if (!ibus->use_global_engine) {
1001 engine_name = (gchar *) g_object_get_data (G_OBJECT (context), "previous-engine-name");
1004 if (!ibus->global_previous_engine_name) {
1005 ibus->global_previous_engine_name = bus_ibus_impl_load_global_previous_engine_name_from_config (ibus);
1007 engine_name = ibus->global_previous_engine_name;
1011 * If the previous engine name is not found, switch to the next engine
1012 * in the menu. This behavior is better than doing nothing.
1015 bus_ibus_impl_context_request_next_engine_in_menu (ibus, context);
1018 _context_request_engine_cb (context, engine_name, ibus);
1022 bus_ibus_impl_set_context_engine_from_desc (BusIBusImpl *ibus,
1023 BusInputContext *context,
1024 IBusEngineDesc *desc)
1026 bus_input_context_set_engine_by_desc (context,
1028 5000, /* timeout in msec. */
1029 NULL, /* we do not cancel the call. */
1030 NULL, /* use the default callback function. */
1035 * bus_ibus_impl_set_focused_context:
1037 * Set the current focused context.
1040 bus_ibus_impl_set_focused_context (BusIBusImpl *ibus,
1041 BusInputContext *context)
1043 g_assert (BUS_IS_IBUS_IMPL (ibus));
1044 g_assert (context == NULL || BUS_IS_INPUT_CONTEXT (context));
1045 g_assert (context == NULL || bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS);
1047 /* Do noting if it is not focused context. */
1048 if (ibus->focused_context == context) {
1052 BusEngineProxy *engine = NULL;
1054 if (ibus->focused_context) {
1055 if (ibus->use_global_engine) {
1056 /* dettach engine from the focused context */
1057 engine = bus_input_context_get_engine (ibus->focused_context);
1059 g_object_ref (engine);
1060 bus_input_context_set_engine (ibus->focused_context, NULL);
1064 if (ibus->panel != NULL)
1065 bus_panel_proxy_focus_out (ibus->panel, ibus->focused_context);
1067 g_object_unref (ibus->focused_context);
1068 ibus->focused_context = NULL;
1071 if (context == NULL && ibus->use_global_engine) {
1072 context = ibus->fake_context;
1076 ibus->focused_context = (BusInputContext *) g_object_ref (context);
1077 /* attach engine to the focused context */
1078 if (engine != NULL) {
1079 bus_input_context_set_engine (context, engine);
1080 if (bus_engine_proxy_is_enabled (engine))
1081 bus_input_context_enable (context);
1082 g_object_unref (engine);
1085 if (ibus->panel != NULL)
1086 bus_panel_proxy_focus_in (ibus->panel, context);
1092 * _context_engine_changed_cb:
1094 * A callback function to be called when the "engine-changed" signal is sent to the context.
1095 * Update global engine as well if necessary.
1098 _context_engine_changed_cb (BusInputContext *context,
1101 if (!ibus->use_global_engine)
1104 if ((context == ibus->focused_context) ||
1105 (ibus->focused_context == NULL && context == ibus->fake_context)) {
1106 BusEngineProxy *engine = bus_input_context_get_engine (context);
1107 if (engine != NULL) {
1108 /* only set global engine if engine is not NULL */
1109 const gchar *name = ibus_engine_desc_get_name (bus_engine_proxy_get_desc (engine));
1110 if (g_strcmp0 (name, ibus->global_engine_name) == 0)
1112 g_free (ibus->global_previous_engine_name);
1113 ibus->global_previous_engine_name = ibus->global_engine_name;
1114 ibus->global_engine_name = g_strdup (name);
1116 bus_ibus_impl_save_global_engine_name_to_config (ibus);
1117 bus_ibus_impl_save_global_previous_engine_name_to_config (ibus);
1118 bus_ibus_impl_global_engine_changed (ibus);
1124 * _context_focus_in_cb:
1126 * A callback function to be called when the "focus-in" signal is sent to the context.
1127 * If necessary, enables the global engine on the context and update ibus->focused_context.
1130 _context_focus_in_cb (BusInputContext *context,
1133 g_assert (BUS_IS_IBUS_IMPL (ibus));
1134 g_assert (BUS_IS_INPUT_CONTEXT (context));
1136 /* Do nothing if context does not support focus.
1137 * The global engine shoule be detached from the focused context. */
1138 if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
1142 bus_ibus_impl_set_focused_context (ibus, context);
1146 * _context_focus_out_cb:
1148 * A callback function to be called when the "focus-out" signal is sent to the context.
1151 _context_focus_out_cb (BusInputContext *context,
1154 g_assert (BUS_IS_IBUS_IMPL (ibus));
1155 g_assert (BUS_IS_INPUT_CONTEXT (context));
1157 /* Do noting if context does not support focus.
1158 * Actually, the context should emit focus signals, if it does not support focus */
1159 if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
1163 /* Do noting if it is not focused context. */
1164 if (ibus->focused_context != context) {
1169 if (ibus->use_global_engine == FALSE) {
1170 /* Do not change the focused context, if use_global_engine option is enabled.
1171 * If focused context swith to NULL, users can not swith engine in panel anymore.
1173 bus_ibus_impl_set_focused_context (ibus, NULL);
1178 * _context_destroy_cb:
1180 * A callback function to be called when the "destroy" signal is sent to the context.
1183 _context_destroy_cb (BusInputContext *context,
1186 g_assert (BUS_IS_IBUS_IMPL (ibus));
1187 g_assert (BUS_IS_INPUT_CONTEXT (context));
1189 if (context == ibus->focused_context) {
1190 bus_ibus_impl_set_focused_context (ibus, NULL);
1193 ibus->contexts = g_list_remove (ibus->contexts, context);
1194 g_object_unref (context);
1198 * _context_enabled_cb:
1200 * A callback function to be called when the "enabled" signal is sent to the context.
1203 _context_enabled_cb (BusInputContext *context,
1206 /* FIXME implement this. */
1210 * _context_disabled_cb:
1212 * A callback function to be called when the "disabled" signal is sent to the context.
1215 _context_disabled_cb (BusInputContext *context,
1218 /* FIXME implement this. */
1222 * bus_ibus_impl_create_input_context:
1223 * @client: A name of a client. e.g. "gtk-im"
1224 * @returns: A BusInputContext object.
1226 * Create a new BusInputContext object for the client.
1228 static BusInputContext *
1229 bus_ibus_impl_create_input_context (BusIBusImpl *ibus,
1230 BusConnection *connection,
1231 const gchar *client)
1233 BusInputContext *context = bus_input_context_new (connection, client);
1234 g_object_ref_sink (context);
1235 ibus->contexts = g_list_append (ibus->contexts, context);
1237 /* Installs glib signal handlers so that the ibus object could be notified when e.g. an IBus.InputContext D-Bus method is called. */
1238 static const struct {
1242 { "request-engine", G_CALLBACK (_context_request_engine_cb) },
1243 { "engine-changed", G_CALLBACK (_context_engine_changed_cb) },
1244 { "focus-in", G_CALLBACK (_context_focus_in_cb) },
1245 { "focus-out", G_CALLBACK (_context_focus_out_cb) },
1246 { "destroy", G_CALLBACK (_context_destroy_cb) },
1247 { "enabled", G_CALLBACK (_context_enabled_cb) },
1248 { "disabled", G_CALLBACK (_context_disabled_cb) },
1252 for (i = 0; i < G_N_ELEMENTS (signals); i++) {
1253 g_signal_connect (context,
1255 signals[i].callback,
1259 if (ibus->enable_by_default) {
1260 bus_input_context_enable (context);
1263 /* register the context object so that the object could handle IBus.InputContext method calls. */
1264 bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
1265 (IBusService *) context);
1266 g_object_ref (context);
1271 * _ibus_create_input_context:
1273 * Implement the "CreateInputContext" method call of the org.freedesktop.IBus interface.
1276 _ibus_create_input_context (BusIBusImpl *ibus,
1277 GVariant *parameters,
1278 GDBusMethodInvocation *invocation)
1280 const gchar *client_name = NULL; // e.g. "gtk-im"
1281 g_variant_get (parameters, "(&s)", &client_name);
1283 BusConnection *connection =
1284 bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
1285 BusInputContext *context =
1286 bus_ibus_impl_create_input_context (ibus,
1290 const gchar *path = ibus_service_get_object_path ((IBusService *) context);
1291 /* the format-string 'o' is for a D-Bus object path. */
1292 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
1293 g_object_unref (context);
1296 g_dbus_method_invocation_return_error (invocation,
1298 G_DBUS_ERROR_FAILED,
1299 "Create input context failed!");
1304 * _ibus_current_input_context:
1306 * Implement the "CurrentInputContext" method call of the org.freedesktop.IBus interface.
1309 _ibus_current_input_context (BusIBusImpl *ibus,
1310 GVariant *parameters,
1311 GDBusMethodInvocation *invocation)
1313 if (!ibus->focused_context)
1315 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1316 "No focused input context");
1319 const gchar *path = ibus_service_get_object_path ((IBusService *) ibus->focused_context);
1320 /* the format-string 'o' is for a D-Bus object path. */
1321 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
1326 _component_destroy_cb (BusComponent *component,
1329 g_assert (BUS_IS_IBUS_IMPL (ibus));
1330 g_assert (BUS_IS_COMPONENT (component));
1332 ibus->registered_components = g_list_remove (ibus->registered_components, component);
1334 /* remove engines from engine_list */
1335 GList *engines = bus_component_get_engines (component);
1337 for (p = engines; p != NULL; p = p->next) {
1338 if (g_list_find (ibus->register_engine_list, p->data)) {
1339 ibus->register_engine_list = g_list_remove (ibus->register_engine_list, p->data);
1340 g_object_unref (p->data);
1343 g_list_free (engines);
1345 g_object_unref (component);
1347 bus_ibus_impl_update_engines_hotkey_profile (ibus);
1351 * _ibus_register_component:
1353 * Implement the "RegisterComponent" method call of the org.freedesktop.IBus interface.
1356 _ibus_register_component (BusIBusImpl *ibus,
1357 GVariant *parameters,
1358 GDBusMethodInvocation *invocation)
1360 GVariant *variant = g_variant_get_child_value (parameters, 0);
1361 IBusComponent *component = (IBusComponent *) ibus_serializable_deserialize (variant);
1363 if (!IBUS_IS_COMPONENT (component)) {
1365 g_object_unref (component);
1366 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1367 "The first argument should be an IBusComponent.");
1371 BusConnection *connection = bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
1372 BusFactoryProxy *factory = bus_factory_proxy_new (connection);
1374 if (factory == NULL) {
1375 g_object_unref (component);
1376 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1377 "Create factory failed.");
1381 g_object_ref_sink (component);
1383 BusComponent *buscomp = bus_component_new (component, factory);
1384 bus_component_set_destroy_with_factory (buscomp, TRUE);
1385 g_object_unref (component);
1386 g_object_unref (factory);
1388 ibus->registered_components = g_list_append (ibus->registered_components,
1389 g_object_ref_sink (buscomp));
1390 GList *engines = bus_component_get_engines (buscomp);
1391 g_list_foreach (engines, (GFunc) g_object_ref, NULL);
1392 ibus->register_engine_list = g_list_concat (ibus->register_engine_list,
1395 g_signal_connect (buscomp, "destroy", G_CALLBACK (_component_destroy_cb), ibus);
1397 bus_ibus_impl_update_engines_hotkey_profile (ibus);
1399 g_dbus_method_invocation_return_value (invocation, NULL);
1403 * _ibus_list_engines:
1405 * Implement the "ListEngines" method call of the org.freedesktop.IBus interface.
1408 _ibus_list_engines (BusIBusImpl *ibus,
1409 GVariant *parameters,
1410 GDBusMethodInvocation *invocation)
1412 GVariantBuilder builder;
1413 g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1415 GList *engines = bus_registry_get_engines (ibus->registry);
1417 for (p = engines; p != NULL; p = p->next) {
1418 g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1420 g_list_free (engines);
1421 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1425 * _ibus_list_active_engines:
1427 * Implement the "ListActiveEngines" method call of the org.freedesktop.IBus interface.
1430 _ibus_list_active_engines (BusIBusImpl *ibus,
1431 GVariant *parameters,
1432 GDBusMethodInvocation *invocation)
1434 GVariantBuilder builder;
1435 g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1438 for (p = ibus->engine_list; p != NULL; p = p->next) {
1439 g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1441 for (p = ibus->register_engine_list; p != NULL; p = p->next) {
1442 g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1444 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1450 * Implement the "Exit" method call of the org.freedesktop.IBus interface.
1453 _ibus_exit (BusIBusImpl *ibus,
1454 GVariant *parameters,
1455 GDBusMethodInvocation *invocation)
1457 gboolean restart = FALSE;
1458 g_variant_get (parameters, "(b)", &restart);
1460 g_dbus_method_invocation_return_value (invocation, NULL);
1462 /* Make sure the reply has been sent out before exit */
1463 g_dbus_connection_flush_sync (g_dbus_method_invocation_get_connection (invocation),
1472 extern gchar **g_argv;
1476 exe = g_strdup_printf ("/proc/%d/exe", getpid ());
1477 exe = g_file_read_link (exe, NULL);
1480 exe = BINDIR "/ibus-daemon";
1482 /* close all fds except stdin, stdout, stderr */
1483 for (fd = 3; fd <= sysconf (_SC_OPEN_MAX); fd ++) {
1487 execv (exe, g_argv);
1489 /* If the server binary is replaced while the server is running,
1490 * "readlink /proc/[pid]/exe" might return a path with " (deleted)"
1492 const gchar suffix[] = " (deleted)";
1493 if (g_str_has_suffix (exe, suffix)) {
1494 exe [strlen (exe) - sizeof (suffix) + 1] = '\0';
1495 execv (exe, g_argv);
1497 g_warning ("execv %s failed!", g_argv[0]);
1501 /* should not reach here */
1502 g_assert_not_reached ();
1508 * Implement the "Ping" method call of the org.freedesktop.IBus interface.
1511 _ibus_ping (BusIBusImpl *ibus,
1512 GVariant *parameters,
1513 GDBusMethodInvocation *invocation)
1515 g_dbus_method_invocation_return_value (invocation, parameters);
1519 * _ibus_get_use_sys_layout:
1521 * Implement the "GetUseSysLayout" method call of the org.freedesktop.IBus interface.
1524 _ibus_get_use_sys_layout (BusIBusImpl *ibus,
1525 GVariant *parameters,
1526 GDBusMethodInvocation *invocation)
1528 g_dbus_method_invocation_return_value (invocation,
1529 g_variant_new ("(b)", ibus->use_sys_layout));
1533 * _ibus_get_use_global_engine:
1535 * Implement the "GetUseGlobalEngine" method call of the org.freedesktop.IBus interface.
1538 _ibus_get_use_global_engine (BusIBusImpl *ibus,
1539 GVariant *parameters,
1540 GDBusMethodInvocation *invocation)
1542 g_dbus_method_invocation_return_value (invocation,
1543 g_variant_new ("(b)", ibus->use_global_engine));
1547 * _ibus_get_global_engine:
1549 * Implement the "GetGlobalEngine" method call of the org.freedesktop.IBus interface.
1552 _ibus_get_global_engine (BusIBusImpl *ibus,
1553 GVariant *parameters,
1554 GDBusMethodInvocation *invocation)
1556 IBusEngineDesc *desc = NULL;
1559 if (!ibus->use_global_engine)
1561 BusInputContext *context = ibus->focused_context;
1562 if (context == NULL)
1563 context = ibus->fake_context;
1565 desc = bus_input_context_get_engine_desc (context);
1570 GVariant *variant = ibus_serializable_serialize ((IBusSerializable *) desc);
1571 g_dbus_method_invocation_return_value (invocation,
1572 g_variant_new ("(v)", variant));
1576 g_dbus_method_invocation_return_error (invocation,
1577 G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1578 "No global engine.");
1582 _ibus_set_global_engine_ready_cb (BusInputContext *context,
1584 GDBusMethodInvocation *invocation)
1586 GError *error = NULL;
1587 if (!bus_input_context_set_engine_by_desc_finish (context, res, &error)) {
1588 g_error_free (error);
1589 g_dbus_method_invocation_return_error (invocation,
1591 G_DBUS_ERROR_FAILED,
1592 "Set global engine failed.");
1596 g_dbus_method_invocation_return_value (invocation, NULL);
1601 * _ibus_set_global_engine:
1603 * Implement the "SetGlobalEngine" method call of the org.freedesktop.IBus interface.
1606 _ibus_set_global_engine (BusIBusImpl *ibus,
1607 GVariant *parameters,
1608 GDBusMethodInvocation *invocation)
1610 if (!ibus->use_global_engine) {
1611 g_dbus_method_invocation_return_error (invocation,
1612 G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1613 "Global engine feature is disabled.");
1617 BusInputContext *context = ibus->focused_context;
1618 if (context == NULL)
1619 context = ibus->fake_context;
1621 const gchar *new_engine_name = NULL;
1622 g_variant_get (parameters, "(&s)", &new_engine_name);
1623 const gchar *old_engine_name = NULL;
1625 BusEngineProxy *engine = bus_input_context_get_engine (context);
1628 ibus_engine_desc_get_name (bus_engine_proxy_get_desc (engine));
1631 if (g_strcmp0 (new_engine_name, old_engine_name) == 0) {
1632 /* If the user requested the same global engine, then we just enable the
1634 bus_input_context_enable (context);
1635 g_dbus_method_invocation_return_value (invocation, NULL);
1639 IBusEngineDesc *desc = _find_engine_desc_by_name (ibus, new_engine_name);
1641 g_dbus_method_invocation_return_error (invocation,
1643 G_DBUS_ERROR_FAILED,
1644 "Can not find engine %s.",
1649 bus_input_context_set_engine_by_desc (context,
1651 5000, /* timeout in msec. */
1652 NULL, /* we do not cancel the call. */
1653 (GAsyncReadyCallback) _ibus_set_global_engine_ready_cb,
1658 * _ibus_is_global_engine_enabled:
1660 * Implement the "IsGlobalEngineEnabled" method call of the org.freedesktop.IBus interface.
1663 _ibus_is_global_engine_enabled (BusIBusImpl *ibus,
1664 GVariant *parameters,
1665 GDBusMethodInvocation *invocation)
1667 gboolean enabled = FALSE;
1670 if (!ibus->use_global_engine)
1673 BusInputContext *context = ibus->focused_context;
1674 if (context == NULL)
1675 context = ibus->fake_context;
1676 if (context == NULL)
1679 enabled = bus_input_context_is_enabled (context);
1682 g_dbus_method_invocation_return_value (invocation,
1683 g_variant_new ("(b)", enabled));
1687 * bus_ibus_impl_service_method_call:
1689 * Handle a D-Bus method call whose destination and interface name are both "org.freedesktop.IBus"
1692 bus_ibus_impl_service_method_call (IBusService *service,
1693 GDBusConnection *connection,
1694 const gchar *sender,
1695 const gchar *object_path,
1696 const gchar *interface_name,
1697 const gchar *method_name,
1698 GVariant *parameters,
1699 GDBusMethodInvocation *invocation)
1701 if (g_strcmp0 (interface_name, "org.freedesktop.IBus") != 0) {
1702 IBUS_SERVICE_CLASS (bus_ibus_impl_parent_class)->service_method_call (
1703 service, connection, sender, object_path, interface_name, method_name,
1704 parameters, invocation);
1708 /* all methods in the xml definition above should be listed here. */
1709 static const struct {
1710 const gchar *method_name;
1711 void (* method_callback) (BusIBusImpl *, GVariant *, GDBusMethodInvocation *);
1713 /* IBus interface */
1714 { "GetAddress", _ibus_get_address },
1715 { "CreateInputContext", _ibus_create_input_context },
1716 { "CurrentInputContext", _ibus_current_input_context },
1717 { "RegisterComponent", _ibus_register_component },
1718 { "ListEngines", _ibus_list_engines },
1719 { "ListActiveEngines", _ibus_list_active_engines },
1720 { "Exit", _ibus_exit },
1721 { "Ping", _ibus_ping },
1722 { "GetUseSysLayout", _ibus_get_use_sys_layout },
1723 { "GetUseGlobalEngine", _ibus_get_use_global_engine },
1724 { "GetGlobalEngine", _ibus_get_global_engine },
1725 { "SetGlobalEngine", _ibus_set_global_engine },
1726 { "IsGlobalEngineEnabled", _ibus_is_global_engine_enabled },
1730 for (i = 0; i < G_N_ELEMENTS (methods); i++) {
1731 if (g_strcmp0 (methods[i].method_name, method_name) == 0) {
1732 methods[i].method_callback ((BusIBusImpl *) service, parameters, invocation);
1737 /* notreached - unknown method calls that are not in the introspection_xml should be handled by the GDBus library. */
1738 g_return_if_reached ();
1742 bus_ibus_impl_get_default (void)
1744 static BusIBusImpl *ibus = NULL;
1747 ibus = (BusIBusImpl *) g_object_new (BUS_TYPE_IBUS_IMPL,
1748 "object-path", IBUS_PATH_IBUS,
1755 bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
1758 g_assert (BUS_IS_IBUS_IMPL (ibus));
1760 BusFactoryProxy *factory;
1762 factory = (BusFactoryProxy *) g_hash_table_lookup (ibus->factory_dict, path);
1768 bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus)
1770 g_assert (BUS_IS_IBUS_IMPL (ibus));
1772 return ibus->hotkey_profile;
1776 bus_ibus_impl_get_keymap (BusIBusImpl *ibus)
1779 g_assert (BUS_IS_IBUS_IMPL (ibus));
1781 return ibus->keymap;
1785 bus_ibus_impl_get_registry (BusIBusImpl *ibus)
1788 g_assert (BUS_IS_IBUS_IMPL (ibus));
1790 return ibus->registry;
1794 * bus_ibus_impl_emit_signal:
1796 * Send a D-Bus signal to buses (connections) that are listening to the signal.
1799 bus_ibus_impl_emit_signal (BusIBusImpl *ibus,
1800 const gchar *signal_name,
1801 GVariant *parameters)
1804 GDBusMessage *message = g_dbus_message_new_signal ("/org/freedesktop/IBus",
1805 "org.freedesktop.DBus",
1807 g_dbus_message_set_sender (message, "org.freedesktop.DBus");
1809 g_dbus_message_set_body (message, parameters);
1810 bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
1811 g_object_unref (message);
1815 bus_ibus_impl_registry_changed (BusIBusImpl *ibus)
1817 bus_ibus_impl_emit_signal (ibus, "RegistryChanged", NULL);
1821 bus_ibus_impl_global_engine_changed (BusIBusImpl *ibus)
1823 bus_ibus_impl_emit_signal (ibus, "GlobalEngineChanged", NULL);
1827 bus_ibus_impl_filter_keyboard_shortcuts (BusIBusImpl *ibus,
1828 BusInputContext *context,
1832 guint prev_modifiers)
1834 static GQuark trigger = 0;
1835 static GQuark next = 0;
1836 static GQuark previous = 0;
1842 trigger = g_quark_from_static_string ("trigger");
1843 next = g_quark_from_static_string ("next-engine-in-menu");
1844 previous = g_quark_from_static_string ("previous-engine");
1847 /* Try global hotkeys first. */
1848 event = ibus_hotkey_profile_filter_key_event (ibus->hotkey_profile,
1855 if (event == trigger) {
1856 gboolean enabled = bus_input_context_is_enabled (context);
1858 bus_input_context_disable (context);
1861 bus_input_context_enable (context);
1863 return (enabled != bus_input_context_is_enabled (context));
1865 if (event == next) {
1866 if (bus_input_context_is_enabled (context)) {
1867 bus_ibus_impl_context_request_next_engine_in_menu (ibus, context);
1870 bus_input_context_enable (context);
1874 if (event == previous) {
1875 if (bus_input_context_is_enabled (context)) {
1876 bus_ibus_impl_context_request_previous_engine (ibus, context);
1879 bus_input_context_enable (context);
1884 if (!ibus->engines_hotkey_profile || !ibus->hotkey_to_engines_map) {
1888 /* Then try engines hotkeys. */
1889 event = ibus_hotkey_profile_filter_key_event (ibus->engines_hotkey_profile,
1899 engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
1900 GUINT_TO_POINTER (event));
1902 BusEngineProxy *current_engine = bus_input_context_get_engine (context);
1903 IBusEngineDesc *current_engine_desc =
1904 (current_engine ? bus_engine_proxy_get_desc (current_engine) : NULL);
1905 IBusEngineDesc *new_engine_desc = (IBusEngineDesc *) engine_list->data;
1907 g_assert (new_engine_desc);
1909 /* Find out what engine we should switch to. If the current engine has
1910 * the same hotkey, then we should switch to the next engine with the
1911 * same hotkey in the list. Otherwise, we just switch to the first
1912 * engine in the list. */
1913 GList *p = engine_list;
1914 for (; p->next != NULL; p = p->next) {
1915 if (current_engine_desc == (IBusEngineDesc *) p->data) {
1916 new_engine_desc = (IBusEngineDesc *) p->next->data;
1921 if (current_engine_desc != new_engine_desc) {
1922 bus_ibus_impl_set_context_engine_from_desc (ibus, context, new_engine_desc);
1932 * bus_ibus_impl_load_global_engine_name_from_config:
1934 * Retrieve the "global_engine" config from the config daemon. Return NULL if the daemon is not ready.
1937 bus_ibus_impl_load_global_engine_name_from_config (BusIBusImpl *ibus)
1939 g_assert (BUS_IS_IBUS_IMPL (ibus));
1940 g_return_val_if_fail (IBUS_IS_CONFIG (ibus->config), NULL);
1942 GVariant *variant = ibus_config_get_value (ibus->config, "general", "global_engine");
1943 gchar *engine_name = NULL;
1944 if (variant != NULL) {
1945 g_variant_get (variant, "s", &engine_name);
1946 g_variant_unref (variant);
1952 * bus_ibus_impl_save_global_engine_name_to_config:
1954 * Save the "global_engine" config value on the config daemon. No-op if the daemon is not ready.
1957 bus_ibus_impl_save_global_engine_name_to_config (BusIBusImpl *ibus)
1959 g_assert (BUS_IS_IBUS_IMPL (ibus));
1962 ibus->use_global_engine &&
1963 ibus->global_engine_name) {
1964 ibus_config_set_value (ibus->config,
1965 "general", "global_engine",
1966 g_variant_new ("s", ibus->global_engine_name));
1971 * bus_ibus_impl_load_global_previous_engine_name_from_config:
1973 * Retrieve the "global_previous_engine" config from the config daemon. Return NULL if the daemon is not ready.
1976 bus_ibus_impl_load_global_previous_engine_name_from_config (BusIBusImpl *ibus)
1978 g_assert (BUS_IS_IBUS_IMPL (ibus));
1979 g_return_val_if_fail (IBUS_IS_CONFIG (ibus->config), NULL);
1981 GVariant *value = ibus_config_get_value (ibus->config, "general", "global_previous_engine");
1984 gchar *engine_name = NULL;
1985 g_variant_get (value, "(s)", &engine_name);
1986 g_variant_unref (value);
1991 * bus_ibus_impl_save_global_previous_engine_name_to_config:
1993 * Save the "global_previous_engine" config value on the config daemon. No-op if the daemon is not ready.
1996 bus_ibus_impl_save_global_previous_engine_name_to_config (BusIBusImpl *ibus)
1998 g_assert (BUS_IS_IBUS_IMPL (ibus));
2001 ibus->use_global_engine &&
2002 ibus->global_previous_engine_name) {
2003 ibus_config_set_value (ibus->config,
2004 "general", "global_previous_engine",
2005 g_variant_new ("s", ibus->global_previous_engine_name));
2010 * _add_engine_hotkey:
2012 * Check the engine-specific hot key of the engine, and update ibus->engines_hotkey_profile.
2015 _add_engine_hotkey (IBusEngineDesc *engine, BusIBusImpl *ibus)
2017 const gchar *hotkeys;
2018 gchar **hotkey_list;
2031 hotkeys = ibus_engine_desc_get_hotkeys (engine);
2033 if (!hotkeys || !*hotkeys) {
2037 hotkey_list = g_strsplit_set (hotkeys, ";,", 0);
2039 for (p = hotkey_list; p && *p; ++p) {
2040 hotkey = g_strstrip (*p);
2041 if (!*hotkey || !ibus_key_event_from_string (hotkey, &keyval, &modifiers)) {
2045 /* If the hotkey already exists, we won't need to add it again. */
2046 event = ibus_hotkey_profile_lookup_hotkey (ibus->engines_hotkey_profile,
2049 event = g_quark_from_string (hotkey);
2050 ibus_hotkey_profile_add_hotkey (ibus->engines_hotkey_profile,
2051 keyval, modifiers, event);
2054 engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
2055 GUINT_TO_POINTER (event));
2057 /* As we will rebuild the engines hotkey map whenever an engine was
2058 * added or removed, we don't need to hold a reference of the engine
2060 engine_list = g_list_append (engine_list, engine);
2062 /* We need to steal the value before adding it back, otherwise it will
2064 g_hash_table_steal (ibus->hotkey_to_engines_map, GUINT_TO_POINTER (event));
2066 g_hash_table_insert (ibus->hotkey_to_engines_map,
2067 GUINT_TO_POINTER (event), engine_list);
2070 g_strfreev (hotkey_list);
2074 * bus_ibus_impl_update_engines_hotkey_profile:
2076 * Check engine-specific hot keys of all active engines, and update ibus->engines_hotkey_profile.
2079 bus_ibus_impl_update_engines_hotkey_profile (BusIBusImpl *ibus)
2081 if (ibus->engines_hotkey_profile) {
2082 g_object_unref (ibus->engines_hotkey_profile);
2085 if (ibus->hotkey_to_engines_map) {
2086 g_hash_table_unref (ibus->hotkey_to_engines_map);
2089 ibus->engines_hotkey_profile = ibus_hotkey_profile_new ();
2090 ibus->hotkey_to_engines_map =
2091 g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_list_free);
2093 g_list_foreach (ibus->register_engine_list, (GFunc) _add_engine_hotkey, ibus);
2094 g_list_foreach (ibus->engine_list, (GFunc) _add_engine_hotkey, ibus);
2098 bus_ibus_impl_is_use_sys_layout (BusIBusImpl *ibus)
2100 g_assert (BUS_IS_IBUS_IMPL (ibus));
2102 return ibus->use_sys_layout;
2106 bus_ibus_impl_is_embed_preedit_text (BusIBusImpl *ibus)
2108 g_assert (BUS_IS_IBUS_IMPL (ibus));
2110 return ibus->embed_preedit_text;
2114 bus_ibus_impl_get_focused_input_context (BusIBusImpl *ibus)
2116 g_assert (BUS_IS_IBUS_IMPL (ibus));
2118 return ibus->focused_context;