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_set_global_engine (BusIBusImpl *ibus,
160 BusEngineProxy *engine);
161 static void bus_ibus_impl_set_global_engine_by_name
164 static void bus_ibus_impl_engines_maybe_removed
166 static void bus_ibus_impl_registry_changed (BusIBusImpl *ibus);
167 static void bus_ibus_impl_global_engine_changed
169 static void bus_ibus_impl_set_context_engine_from_desc
171 BusInputContext *context,
172 IBusEngineDesc *desc);
173 static gchar *bus_ibus_impl_load_global_engine_name_from_config
175 static void bus_ibus_impl_save_global_engine_name_to_config
178 static gchar *bus_ibus_impl_load_global_previous_engine_name_from_config
180 static void bus_ibus_impl_save_global_previous_engine_name_to_config
182 static void bus_ibus_impl_update_engines_hotkey_profile
184 static BusInputContext
185 *bus_ibus_impl_create_input_context
187 BusConnection *connection,
188 const gchar *client);
189 /* some callback functions */
190 static void _context_engine_changed_cb (BusInputContext *context,
193 /* The interfaces available in this class, which consists of a list of methods this class implements and
194 * a list of signals this class may emit. Method calls to the interface that are not defined in this XML
195 * will be automatically rejected by the GDBus library (see src/ibusservice.c for details.) */
196 static const gchar introspection_xml[] =
198 " <interface name='org.freedesktop.IBus'>\n"
199 " <method name='GetAddress'>\n"
200 " <arg direction='out' type='s' name='address' />\n"
202 " <method name='CreateInputContext'>\n"
203 " <arg direction='in' type='s' name='client_name' />\n"
204 " <arg direction='out' type='o' name='object_path' />\n"
206 " <method name='CurrentInputContext'>\n"
207 " <arg direction='out' type='o' name='object_path' />\n"
209 " <method name='RegisterComponent'>\n"
210 " <arg direction='in' type='v' name='component' />\n"
212 " <method name='ListEngines'>\n"
213 " <arg direction='out' type='av' name='engines' />\n"
215 " <method name='ListActiveEngines'>\n"
216 " <arg direction='out' type='av' name='engines' />\n"
218 " <method name='Exit'>\n"
219 " <arg direction='in' type='b' name='restart' />\n"
221 " <method name='Ping'>\n"
222 " <arg direction='in' type='v' name='data' />\n"
223 " <arg direction='out' type='v' name='data' />\n"
225 " <method name='GetUseSysLayout'>\n"
226 " <arg direction='out' type='b' name='enabled' />\n"
228 " <method name='GetUseGlobalEngine'>\n"
229 " <arg direction='out' type='b' name='enabled' />\n"
231 " <method name='GetGlobalEngine'>\n"
232 " <arg direction='out' type='v' name='desc' />\n"
234 " <method name='SetGlobalEngine'>\n"
235 " <arg direction='in' type='s' name='engine_name' />\n"
237 " <method name='IsGlobalEngineEnabled'>\n"
238 " <arg direction='out' type='b' name='enabled' />\n"
240 " <signal name='RegistryChanged'>\n"
242 " <signal name='GlobalEngineChanged'>\n"
243 " <arg type='s' name='engine_name' />\n"
249 G_DEFINE_TYPE (BusIBusImpl, bus_ibus_impl, IBUS_TYPE_SERVICE)
252 bus_ibus_impl_class_init (BusIBusImplClass *class)
254 IBUS_OBJECT_CLASS (class)->destroy = (IBusObjectDestroyFunc) bus_ibus_impl_destroy;
256 /* override the parent class's implementation. */
257 IBUS_SERVICE_CLASS (class)->service_method_call = bus_ibus_impl_service_method_call;
258 /* 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'.) */
259 ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml);
265 * A callback function which is called when (1) the connection to the panel process is terminated,
266 * or (2) ibus_proxy_destroy (ibus->panel); is called. See src/ibusproxy.c for details.
269 _panel_destroy_cb (BusPanelProxy *panel,
272 g_assert (BUS_IS_PANEL_PROXY (panel));
273 g_assert (BUS_IS_IBUS_IMPL (ibus));
275 g_return_if_fail (ibus->panel == panel);
278 g_object_unref (panel);
282 bus_ibus_impl_set_hotkey (BusIBusImpl *ibus,
286 g_assert (BUS_IS_IBUS_IMPL (ibus));
288 ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
295 g_variant_iter_init (&iter, value);
296 const gchar *str = NULL;
297 while (g_variant_iter_loop (&iter,"&s", &str)) {
298 ibus_hotkey_profile_add_hotkey_from_string (ibus->hotkey_profile,
306 * bus_ibus_impl_set_trigger:
308 * A function to be called when "trigger" config is updated. If the value is NULL, the default trigger (Ctrl+space) is set.
311 bus_ibus_impl_set_trigger (BusIBusImpl *ibus,
314 GQuark hotkey = g_quark_from_static_string ("trigger");
316 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
320 /* set default trigger */
321 ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
322 ibus_hotkey_profile_add_hotkey (ibus->hotkey_profile,
331 * bus_ibus_impl_set_enable_unconditional:
333 * A function to be called when "enable_unconditional" config is updated.
336 bus_ibus_impl_set_enable_unconditional (BusIBusImpl *ibus,
339 GQuark hotkey = g_quark_from_static_string ("enable-unconditional");
340 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
344 * bus_ibus_impl_set_disable_unconditional:
346 * A function to be called when "disable_unconditional" config is updated.
349 bus_ibus_impl_set_disable_unconditional (BusIBusImpl *ibus,
352 GQuark hotkey = g_quark_from_static_string ("disable-unconditional");
353 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
357 * bus_ibus_impl_set_next_engine_in_menu:
359 * A function to be called when "next_engine_in_menu" config is updated.
362 bus_ibus_impl_set_next_engine_in_menu (BusIBusImpl *ibus,
365 GQuark hotkey = g_quark_from_static_string ("next-engine-in-menu");
366 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
370 * bus_ibus_impl_set_previous_engine:
372 * A function to be called when "previous_engine" config is updated.
375 bus_ibus_impl_set_previous_engine (BusIBusImpl *ibus,
378 GQuark hotkey = g_quark_from_static_string ("previous-engine");
379 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
383 * bus_ibus_impl_set_preload_engines:
385 * A function to be called when "preload_engines" config is updated.
388 bus_ibus_impl_set_preload_engines (BusIBusImpl *ibus,
391 GList *engine_list = NULL;
393 g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
394 g_list_free (ibus->engine_list);
396 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_ARRAY) {
398 g_variant_iter_init (&iter, value);
399 const gchar *engine_name = NULL;
400 while (g_variant_iter_loop (&iter, "&s", &engine_name)) {
401 IBusEngineDesc *engine = bus_registry_find_engine_by_name (ibus->registry, engine_name);
402 if (engine == NULL || g_list_find (engine_list, engine) != NULL)
404 engine_list = g_list_append (engine_list, engine);
408 g_list_foreach (engine_list, (GFunc) g_object_ref, NULL);
409 ibus->engine_list = engine_list;
411 if (ibus->engine_list) {
412 BusComponent *component = bus_component_from_engine_desc ((IBusEngineDesc *) ibus->engine_list->data);
413 if (component && !bus_component_is_running (component)) {
414 bus_component_start (component, g_verbose);
418 bus_ibus_impl_engines_maybe_removed (ibus);
419 bus_ibus_impl_update_engines_hotkey_profile (ibus);
423 * bus_ibus_impl_set_use_sys_layout:
425 * A function to be called when "use_system_keyboard_layout" config is updated.
428 bus_ibus_impl_set_use_sys_layout (BusIBusImpl *ibus,
431 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
432 ibus->use_sys_layout = g_variant_get_boolean (value);
437 * bus_ibus_impl_set_embed_preedit_text:
439 * A function to be called when "use_embed_preedit_text" config is updated.
442 bus_ibus_impl_set_embed_preedit_text (BusIBusImpl *ibus,
445 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
446 ibus->embed_preedit_text = g_variant_get_boolean (value);
451 * bus_ibus_impl_set_enable_by_default:
453 * A function to be called when "enable_by_default" config is updated.
456 bus_ibus_impl_set_enable_by_default (BusIBusImpl *ibus,
459 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
460 ibus->enable_by_default = g_variant_get_boolean (value);
465 * bus_ibus_impl_set_use_global_engine:
467 * A function to be called when "use_global_engine" config is updated.
470 bus_ibus_impl_set_use_global_engine (BusIBusImpl *ibus,
473 if (value == NULL || g_variant_classify (value) != G_VARIANT_CLASS_BOOLEAN)
476 gboolean new_value = g_variant_get_boolean (value);
477 if (ibus->use_global_engine == new_value)
481 /* turn on use_global_engine option */
482 ibus->use_global_engine = TRUE;
483 if (ibus->panel && ibus->focused_context == NULL) {
484 bus_panel_proxy_focus_in (ibus->panel, ibus->fake_context);
488 /* turn off use_global_engine option */
489 ibus->use_global_engine = FALSE;
491 /* if fake context has the focus, we should focus out it */
492 if (ibus->panel && ibus->focused_context == NULL) {
493 bus_panel_proxy_focus_out (ibus->panel, ibus->fake_context);
495 /* remove engine in fake context */
496 bus_input_context_set_engine (ibus->fake_context, NULL);
502 _engine_desc_cmp (IBusEngineDesc *desc1,
503 IBusEngineDesc *desc2)
505 return - ((gint) ibus_engine_desc_get_rank (desc1)) +
506 ((gint) ibus_engine_desc_get_rank (desc2));
511 * bus_ibus_impl_set_default_preload_engines:
513 * If the "preload_engines" config variable is not set yet, set the default value which is determined based on a current locale.
516 bus_ibus_impl_set_default_preload_engines (BusIBusImpl *ibus)
519 g_assert (BUS_IS_IBUS_IMPL (ibus));
521 static gboolean done = FALSE;
523 if (done || ibus->config == NULL) {
527 GVariant *variant = ibus_config_get_value (ibus->config, "general", "preload_engines");
528 if (variant != NULL) {
530 g_variant_unref (variant);
536 /* The setlocale call first checks LC_ALL. If it's not available, checks
537 * LC_CTYPE. If it's also not available, checks LANG. */
538 gchar *lang = g_strdup (setlocale (LC_CTYPE, NULL));
543 gchar *p = index (lang, '.');
548 GList *engines = bus_registry_get_engines_by_language (ibus->registry, lang);
549 if (engines == NULL) {
550 p = index (lang, '_');
553 engines = bus_registry_get_engines_by_language (ibus->registry, lang);
558 /* sort engines by rank */
559 engines = g_list_sort (engines, (GCompareFunc) _engine_desc_cmp);
561 GVariantBuilder builder;
562 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
564 for (list = engines; list != NULL; list = list->next) {
565 IBusEngineDesc *desc = (IBusEngineDesc *) list->data;
566 /* ignore engines with rank <= 0 */
567 if (ibus_engine_desc_get_rank (desc) > 0)
568 g_variant_builder_add (&builder, "s", ibus_engine_desc_get_name (desc));
571 GVariant *value = g_variant_builder_end (&builder);
573 if (g_variant_n_children (value) > 0) {
574 ibus_config_set_value (ibus->config,
575 "general", "preload_engines", value);
577 /* We don't update preload_engines with an empty string for safety.
578 * Just unref the floating value. */
579 g_variant_unref (value);
582 g_list_free (engines);
586 /* The list of config entries that are related to ibus-daemon. */
587 const static struct {
590 void (*func) (BusIBusImpl *, GVariant *);
591 } bus_ibus_impl_config_items [] = {
592 { "general/hotkey", "trigger", bus_ibus_impl_set_trigger },
593 { "general/hotkey", "enable_unconditional", bus_ibus_impl_set_enable_unconditional },
594 { "general/hotkey", "disable_unconditional", bus_ibus_impl_set_disable_unconditional },
595 { "general/hotkey", "next_engine_in_menu", bus_ibus_impl_set_next_engine_in_menu },
596 { "general/hotkey", "previous_engine", bus_ibus_impl_set_previous_engine },
597 { "general", "preload_engines", bus_ibus_impl_set_preload_engines },
598 { "general", "use_system_keyboard_layout", bus_ibus_impl_set_use_sys_layout },
599 { "general", "use_global_engine", bus_ibus_impl_set_use_global_engine },
600 { "general", "embed_preedit_text", bus_ibus_impl_set_embed_preedit_text },
601 { "general", "enable_by_default", bus_ibus_impl_set_enable_by_default },
605 * bus_ibus_impl_reload_config
607 * Read config entries (e.g. preload_engines) from the config daemon.
610 bus_ibus_impl_reload_config (BusIBusImpl *ibus)
612 g_assert (BUS_IS_IBUS_IMPL (ibus));
615 for (i = 0; i < G_N_ELEMENTS (bus_ibus_impl_config_items); i++) {
616 GVariant *variant = NULL;
617 if (ibus->config != NULL)
618 variant = ibus_config_get_value (ibus->config,
619 bus_ibus_impl_config_items[i].section,
620 bus_ibus_impl_config_items[i].key);
621 bus_ibus_impl_config_items[i].func (ibus, variant); /* variant could be NULL if the deamon is not ready yet. */
622 if (variant) g_variant_unref (variant);
627 * _config_value_changed_cb:
629 * A callback function to be called when the "ValueChanged" D-Bus signal is sent from the config daemon.
632 _config_value_changed_cb (IBusConfig *config,
638 g_assert (IBUS_IS_CONFIG (config));
642 g_assert (BUS_IS_IBUS_IMPL (ibus));
645 for (i = 0; i < G_N_ELEMENTS (bus_ibus_impl_config_items); i++) {
646 if (g_strcmp0 (bus_ibus_impl_config_items[i].section, section) == 0 &&
647 g_strcmp0 (bus_ibus_impl_config_items[i].key, key) == 0) {
648 bus_ibus_impl_config_items[i].func (ibus, value);
655 * _config_destroy_cb:
657 * A callback function which is called when (1) the connection to the config process is terminated,
658 * or (2) ibus_proxy_destroy (ibus->config); is called. See src/ibusproxy.c for details.
661 _config_destroy_cb (IBusConfig *config,
664 g_assert (IBUS_IS_CONFIG (config));
665 g_assert (BUS_IS_IBUS_IMPL (ibus));
667 g_assert (ibus->config == config);
669 g_object_unref (ibus->config);
674 _registry_changed_cb (BusRegistry *registry,
677 bus_ibus_impl_registry_changed (ibus);
681 * _dbus_name_owner_changed_cb:
683 * A callback function to be called when the name-owner-changed signal is sent to the dbus object.
684 * This usually means a client (e.g. a panel/config/engine process or an application) is connected/disconnected to/from the bus.
687 _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
689 const gchar *old_name,
690 const gchar *new_name,
693 g_assert (BUS_IS_DBUS_IMPL (dbus));
694 g_assert (name != NULL);
695 g_assert (old_name != NULL);
696 g_assert (new_name != NULL);
697 g_assert (BUS_IS_IBUS_IMPL (ibus));
699 if (g_strcmp0 (name, IBUS_SERVICE_PANEL) == 0) {
700 if (g_strcmp0 (new_name, "") != 0) {
701 /* a Panel process is started. */
702 BusConnection *connection;
704 if (ibus->panel != NULL) {
705 ibus_proxy_destroy ((IBusProxy *) ibus->panel);
706 /* panel should be NULL after destroy. See _panel_destroy_cb for details. */
707 g_assert (ibus->panel == NULL);
710 connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
711 g_return_if_fail (connection != NULL);
713 ibus->panel = bus_panel_proxy_new (connection);
715 g_signal_connect (ibus->panel,
717 G_CALLBACK (_panel_destroy_cb),
720 if (ibus->focused_context != NULL) {
721 bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context);
723 else if (ibus->use_global_engine) {
724 bus_panel_proxy_focus_in (ibus->panel, ibus->fake_context);
728 else if (g_strcmp0 (name, IBUS_SERVICE_CONFIG) == 0) {
729 if (g_strcmp0 (new_name, "") != 0) {
730 /* a config process is started. */
731 BusConnection *connection;
733 if (ibus->config != NULL) {
734 ibus_proxy_destroy ((IBusProxy *) ibus->config);
735 /* config should be NULL after destroy. See _config_destroy_cb for details. */
736 g_assert (ibus->config == NULL);
739 /* get a connection between ibus-daemon and the config daemon. */
740 connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
741 g_return_if_fail (connection != NULL);
743 ibus->config = g_initable_new (IBUS_TYPE_CONFIG,
746 /* The following properties are necessary to initialize GDBusProxy object
747 * which is a parent of the config object. */
748 "g-connection", bus_connection_get_dbus_connection (connection),
749 "g-flags", G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
750 "g-interface-name", IBUS_INTERFACE_CONFIG,
751 "g-object-path", IBUS_PATH_CONFIG,
752 "g-default-timeout", g_gdbus_timeout,
755 g_signal_connect (ibus->config,
757 G_CALLBACK (_config_value_changed_cb),
760 g_signal_connect (ibus->config,
762 G_CALLBACK (_config_destroy_cb),
765 bus_ibus_impl_set_default_preload_engines (ibus);
766 bus_ibus_impl_reload_config (ibus);
770 bus_registry_name_owner_changed (ibus->registry, name, old_name, new_name);
774 * bus_ibus_impl_init:
776 * The constructor of BusIBusImpl. Initialize all member variables of a BusIBusImpl object.
779 bus_ibus_impl_init (BusIBusImpl *ibus)
781 ibus->factory_dict = g_hash_table_new_full (
785 (GDestroyNotify) g_object_unref);
787 ibus->fake_context = bus_input_context_new (NULL, "fake");
788 g_object_ref_sink (ibus->fake_context);
789 bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
790 (IBusService *) ibus->fake_context);
791 bus_input_context_set_capabilities (ibus->fake_context,
792 IBUS_CAP_PREEDIT_TEXT |
794 IBUS_CAP_SURROUNDING_TEXT);
795 g_signal_connect (ibus->fake_context,
797 G_CALLBACK (_context_engine_changed_cb),
799 bus_input_context_focus_in (ibus->fake_context);
801 ibus->engine_list = NULL;
802 ibus->register_engine_list = NULL;
803 ibus->contexts = NULL;
804 ibus->focused_context = NULL;
808 ibus->registry = bus_registry_new ();
810 g_signal_connect (ibus->registry,
812 G_CALLBACK (_registry_changed_cb),
814 #ifdef G_THREADS_ENABLED
815 extern gint g_monitor_timeout;
816 if (g_monitor_timeout != 0) {
817 /* Start the monitor of registry changes. */
818 bus_registry_start_monitor_changes (ibus->registry);
822 ibus->hotkey_profile = ibus_hotkey_profile_new ();
823 ibus->keymap = ibus_keymap_get ("us");
825 ibus->use_sys_layout = FALSE;
826 ibus->embed_preedit_text = TRUE;
827 ibus->enable_by_default = FALSE;
828 ibus->use_global_engine = FALSE;
829 ibus->global_engine_name = NULL;
830 ibus->global_previous_engine_name = NULL;
832 ibus->engines_hotkey_profile = NULL;
833 ibus->hotkey_to_engines_map = NULL;
835 bus_ibus_impl_reload_config (ibus);
837 g_signal_connect (BUS_DEFAULT_DBUS,
838 "name-owner-changed",
839 G_CALLBACK (_dbus_name_owner_changed_cb),
844 * bus_ibus_impl_destroy:
846 * The destructor of BusIBusImpl.
849 bus_ibus_impl_destroy (BusIBusImpl *ibus)
856 bus_registry_stop_all_components (ibus->registry);
862 while ((pid = waitpid (0, &status, WNOHANG)) > 0);
864 if (pid == -1) { /* all children finished */
867 if (pid == 0) { /* no child status changed */
870 if (timeout >= G_USEC_PER_SEC) {
873 old = signal (SIGTERM, SIG_IGN);
874 /* send TERM signal to the whole process group (i.e. engines, panel, and config daemon.) */
875 kill (-getpid (), SIGTERM);
876 signal (SIGTERM, old);
880 g_warning ("Not every child processes exited!");
887 g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
888 g_list_free (ibus->engine_list);
889 ibus->engine_list = NULL;
891 g_list_foreach (ibus->register_engine_list, (GFunc) g_object_unref, NULL);
892 g_list_free (ibus->register_engine_list);
893 ibus->register_engine_list = NULL;
895 if (ibus->factory_dict != NULL) {
896 g_hash_table_destroy (ibus->factory_dict);
897 ibus->factory_dict = NULL;
900 if (ibus->hotkey_profile != NULL) {
901 g_object_unref (ibus->hotkey_profile);
902 ibus->hotkey_profile = NULL;
905 if (ibus->keymap != NULL) {
906 g_object_unref (ibus->keymap);
910 g_free (ibus->global_engine_name);
911 ibus->global_engine_name = NULL;
913 g_free (ibus->global_previous_engine_name);
914 ibus->global_previous_engine_name = NULL;
916 if (ibus->engines_hotkey_profile != NULL) {
917 g_object_unref (ibus->engines_hotkey_profile);
918 ibus->engines_hotkey_profile = NULL;
921 if (ibus->hotkey_to_engines_map) {
922 g_hash_table_unref (ibus->hotkey_to_engines_map);
923 ibus->hotkey_to_engines_map = NULL;
926 if (ibus->fake_context) {
927 g_object_unref (ibus->fake_context);
928 ibus->fake_context = NULL;
932 IBUS_OBJECT_CLASS (bus_ibus_impl_parent_class)->destroy (IBUS_OBJECT (ibus));
938 * Implement the "GetAddress" method call of the org.freedesktop.IBus interface.
941 _ibus_get_address (BusIBusImpl *ibus,
942 GVariant *parameters,
943 GDBusMethodInvocation *invocation)
945 g_dbus_method_invocation_return_value (invocation,
946 g_variant_new ("(s)", bus_server_get_address ()));
949 static IBusEngineDesc *
950 _find_engine_desc_by_name (BusIBusImpl *ibus,
951 const gchar *engine_name)
953 IBusEngineDesc *desc = NULL;
956 /* find engine in registered engine list */
957 for (p = ibus->register_engine_list; p != NULL; p = p->next) {
958 desc = (IBusEngineDesc *) p->data;
959 if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
963 /* find engine in preload engine list */
964 for (p = ibus->engine_list; p != NULL; p = p->next) {
965 desc = (IBusEngineDesc *) p->data;
966 if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
974 * _context_request_engine_cb:
976 * A callback function to be called when the "request-engine" signal is sent to the context.
979 _context_request_engine_cb (BusInputContext *context,
980 const gchar *engine_name,
983 IBusEngineDesc *desc = NULL;
985 /* context should has focus before request an engine */
986 g_return_if_fail (bus_input_context_has_focus (context) ||
987 context == ibus->focused_context);
989 if (engine_name != NULL && engine_name[0] != '\0') {
990 /* request engine by name */
991 desc = _find_engine_desc_by_name (ibus, engine_name);
992 g_return_if_fail (desc != NULL);
995 /* Use global engine if possible. */
996 if (ibus->use_global_engine) {
997 gchar *name = g_strdup (ibus->global_engine_name);
999 name = bus_ibus_impl_load_global_engine_name_from_config (ibus);
1002 desc = _find_engine_desc_by_name (ibus, name);
1006 /* request default engine */
1008 if (ibus->register_engine_list) {
1009 desc = (IBusEngineDesc *) ibus->register_engine_list->data;
1011 else if (ibus->engine_list) {
1012 desc = (IBusEngineDesc *) ibus->engine_list->data;
1016 /* no engine is available. the user hasn't ran ibus-setup yet and
1017 * the bus_ibus_impl_set_default_preload_engines() function could
1018 * not find any default engines. another possiblity is that the
1019 * user hasn't installed an engine yet? just give up. */
1020 g_warning ("No engine is available. Run ibus-setup first.");
1025 bus_ibus_impl_set_context_engine_from_desc (ibus, context, desc);
1029 * bus_ibus_impl_context_request_next_engine_in_menu:
1031 * Process the "next_engine_in_menu" hotkey.
1034 bus_ibus_impl_context_request_next_engine_in_menu (BusIBusImpl *ibus,
1035 BusInputContext *context)
1037 BusEngineProxy *engine;
1038 IBusEngineDesc *desc;
1039 IBusEngineDesc *next_desc = NULL;
1042 engine = bus_input_context_get_engine (context);
1043 if (engine == NULL) {
1044 _context_request_engine_cb (context, NULL, ibus);
1048 desc = bus_engine_proxy_get_desc (engine);
1050 p = g_list_find (ibus->register_engine_list, desc);
1055 p = g_list_find (ibus->engine_list, desc);
1062 next_desc = (IBusEngineDesc*) p->data;
1065 if (ibus->register_engine_list) {
1066 next_desc = (IBusEngineDesc *) ibus->register_engine_list->data;
1068 else if (ibus->engine_list) {
1069 next_desc = (IBusEngineDesc *) ibus->engine_list->data;
1073 bus_ibus_impl_set_context_engine_from_desc (ibus, context, next_desc);
1077 * bus_ibus_impl_context_request_previous_engine:
1079 * Process the "previous_engine" hotkey.
1082 bus_ibus_impl_context_request_previous_engine (BusIBusImpl *ibus,
1083 BusInputContext *context)
1085 gchar *engine_name = NULL;
1086 if (!ibus->use_global_engine) {
1087 engine_name = (gchar *) g_object_get_data (G_OBJECT (context), "previous-engine-name");
1090 if (!ibus->global_previous_engine_name) {
1091 ibus->global_previous_engine_name = bus_ibus_impl_load_global_previous_engine_name_from_config (ibus);
1093 engine_name = ibus->global_previous_engine_name;
1097 * If the previous engine name is not found, switch to the next engine
1098 * in the menu. This behavior is better than doing nothing.
1101 bus_ibus_impl_context_request_next_engine_in_menu (ibus, context);
1104 _context_request_engine_cb (context, engine_name, ibus);
1108 bus_ibus_impl_set_context_engine_from_desc (BusIBusImpl *ibus,
1109 BusInputContext *context,
1110 IBusEngineDesc *desc)
1112 bus_input_context_set_engine_by_desc (context,
1114 g_gdbus_timeout, /* timeout in msec. */
1115 NULL, /* we do not cancel the call. */
1116 NULL, /* use the default callback function. */
1121 * bus_ibus_impl_set_focused_context:
1123 * Set the current focused context.
1126 bus_ibus_impl_set_focused_context (BusIBusImpl *ibus,
1127 BusInputContext *context)
1129 g_assert (BUS_IS_IBUS_IMPL (ibus));
1130 g_assert (context == NULL || BUS_IS_INPUT_CONTEXT (context));
1131 g_assert (context == NULL || bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS);
1133 /* Do noting if it is not focused context. */
1134 if (ibus->focused_context == context) {
1138 BusEngineProxy *engine = NULL;
1140 if (ibus->focused_context) {
1141 if (ibus->use_global_engine) {
1142 /* dettach engine from the focused context */
1143 engine = bus_input_context_get_engine (ibus->focused_context);
1145 g_object_ref (engine);
1146 bus_input_context_set_engine (ibus->focused_context, NULL);
1150 if (ibus->panel != NULL)
1151 bus_panel_proxy_focus_out (ibus->panel, ibus->focused_context);
1153 g_object_unref (ibus->focused_context);
1154 ibus->focused_context = NULL;
1157 if (context == NULL && ibus->use_global_engine) {
1158 context = ibus->fake_context;
1162 ibus->focused_context = (BusInputContext *) g_object_ref (context);
1163 /* attach engine to the focused context */
1164 if (engine != NULL) {
1165 bus_input_context_set_engine (context, engine);
1166 if (bus_engine_proxy_is_enabled (engine))
1167 bus_input_context_enable (context);
1168 g_object_unref (engine);
1171 if (ibus->panel != NULL)
1172 bus_panel_proxy_focus_in (ibus->panel, context);
1177 bus_ibus_impl_set_global_engine (BusIBusImpl *ibus,
1178 BusEngineProxy *engine)
1180 BusInputContext *context = NULL;
1182 if (!ibus->use_global_engine)
1185 if (ibus->focused_context) {
1186 bus_input_context_set_engine (ibus->focused_context, engine);
1187 } else if (ibus->fake_context) {
1188 bus_input_context_set_engine (ibus->fake_context, engine);
1193 bus_ibus_impl_set_global_engine_by_name (BusIBusImpl *ibus,
1196 gchar *old_engine_name = NULL;
1198 if (!ibus->use_global_engine)
1201 if (g_strcmp0 (name, ibus->global_engine_name) == 0) {
1202 /* If the user requested the same global engine, then we just enable the
1204 if (ibus->focused_context) {
1205 bus_input_context_enable (ibus->focused_context);
1207 else if (ibus->fake_context) {
1208 bus_input_context_enable (ibus->fake_context);
1213 /* If there is a focused input context, then we just change the engine of
1214 * the focused context, which will then change the global engine
1215 * automatically. Otherwise, we need to change the global engine directly.
1217 if (ibus->focused_context) {
1218 _context_request_engine_cb (ibus->focused_context, name, ibus);
1220 else if (ibus->fake_context) {
1221 _context_request_engine_cb (ibus->fake_context, name, ibus);
1226 bus_ibus_impl_engines_maybe_removed (BusIBusImpl *ibus)
1228 const gchar *old_engine_name = NULL;
1229 GList *engine_list = NULL;
1231 if (!ibus->use_global_engine || ibus->global_engine_name == NULL)
1234 /* The current global engine is not removed, so do nothing. */
1235 if (_find_engine_desc_by_name (ibus, ibus->global_engine_name))
1238 /* If the previous engine is available, then just switch to it. */
1239 if (ibus->global_previous_engine_name &&
1240 _find_engine_desc_by_name (ibus, ibus->global_previous_engine_name)) {
1241 bus_ibus_impl_set_global_engine_by_name (
1242 ibus, ibus->global_previous_engine_name);
1246 /* Just choose one in the list. */
1247 engine_list = ibus->register_engine_list;
1249 engine_list = ibus->engine_list;
1252 IBusEngineDesc *engine_desc = (IBusEngineDesc *)engine_list->data;
1253 bus_ibus_impl_set_global_engine_by_name (ibus,
1254 ibus_engine_desc_get_name (engine_desc));
1258 /* No engine available? Just disable global engine. */
1259 bus_ibus_impl_set_global_engine (ibus, NULL);
1263 * _context_engine_changed_cb:
1265 * A callback function to be called when the "engine-changed" signal is sent to the context.
1266 * Update global engine as well if necessary.
1269 _context_engine_changed_cb (BusInputContext *context,
1272 if (!ibus->use_global_engine)
1275 if ((context == ibus->focused_context) ||
1276 (ibus->focused_context == NULL && context == ibus->fake_context)) {
1277 BusEngineProxy *engine = bus_input_context_get_engine (context);
1278 if (engine != NULL) {
1279 /* only set global engine if engine is not NULL */
1280 const gchar *name = ibus_engine_desc_get_name (bus_engine_proxy_get_desc (engine));
1281 if (g_strcmp0 (name, ibus->global_engine_name) == 0)
1283 g_free (ibus->global_previous_engine_name);
1284 ibus->global_previous_engine_name = ibus->global_engine_name;
1285 ibus->global_engine_name = g_strdup (name);
1287 bus_ibus_impl_save_global_engine_name_to_config (ibus);
1288 bus_ibus_impl_save_global_previous_engine_name_to_config (ibus);
1289 bus_ibus_impl_global_engine_changed (ibus);
1295 * _context_focus_in_cb:
1297 * A callback function to be called when the "focus-in" signal is sent to the context.
1298 * If necessary, enables the global engine on the context and update ibus->focused_context.
1301 _context_focus_in_cb (BusInputContext *context,
1304 g_assert (BUS_IS_IBUS_IMPL (ibus));
1305 g_assert (BUS_IS_INPUT_CONTEXT (context));
1307 /* Do nothing if context does not support focus.
1308 * The global engine shoule be detached from the focused context. */
1309 if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
1313 bus_ibus_impl_set_focused_context (ibus, context);
1317 * _context_focus_out_cb:
1319 * A callback function to be called when the "focus-out" signal is sent to the context.
1322 _context_focus_out_cb (BusInputContext *context,
1325 g_assert (BUS_IS_IBUS_IMPL (ibus));
1326 g_assert (BUS_IS_INPUT_CONTEXT (context));
1328 /* Do noting if context does not support focus.
1329 * Actually, the context should emit focus signals, if it does not support focus */
1330 if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
1334 /* Do noting if it is not focused context. */
1335 if (ibus->focused_context != context) {
1340 if (ibus->use_global_engine == FALSE) {
1341 /* Do not change the focused context, if use_global_engine option is enabled.
1342 * If focused context swith to NULL, users can not swith engine in panel anymore.
1344 bus_ibus_impl_set_focused_context (ibus, NULL);
1349 * _context_destroy_cb:
1351 * A callback function to be called when the "destroy" signal is sent to the context.
1354 _context_destroy_cb (BusInputContext *context,
1357 g_assert (BUS_IS_IBUS_IMPL (ibus));
1358 g_assert (BUS_IS_INPUT_CONTEXT (context));
1360 if (context == ibus->focused_context) {
1361 bus_ibus_impl_set_focused_context (ibus, NULL);
1364 ibus->contexts = g_list_remove (ibus->contexts, context);
1365 g_object_unref (context);
1369 * _context_enabled_cb:
1371 * A callback function to be called when the "enabled" signal is sent to the context.
1374 _context_enabled_cb (BusInputContext *context,
1377 /* FIXME implement this. */
1381 * _context_disabled_cb:
1383 * A callback function to be called when the "disabled" signal is sent to the context.
1386 _context_disabled_cb (BusInputContext *context,
1389 /* FIXME implement this. */
1393 * bus_ibus_impl_create_input_context:
1394 * @client: A name of a client. e.g. "gtk-im"
1395 * @returns: A BusInputContext object.
1397 * Create a new BusInputContext object for the client.
1399 static BusInputContext *
1400 bus_ibus_impl_create_input_context (BusIBusImpl *ibus,
1401 BusConnection *connection,
1402 const gchar *client)
1404 BusInputContext *context = bus_input_context_new (connection, client);
1405 g_object_ref_sink (context);
1406 ibus->contexts = g_list_append (ibus->contexts, context);
1408 /* Installs glib signal handlers so that the ibus object could be notified when e.g. an IBus.InputContext D-Bus method is called. */
1409 static const struct {
1413 { "request-engine", G_CALLBACK (_context_request_engine_cb) },
1414 { "engine-changed", G_CALLBACK (_context_engine_changed_cb) },
1415 { "focus-in", G_CALLBACK (_context_focus_in_cb) },
1416 { "focus-out", G_CALLBACK (_context_focus_out_cb) },
1417 { "destroy", G_CALLBACK (_context_destroy_cb) },
1418 { "enabled", G_CALLBACK (_context_enabled_cb) },
1419 { "disabled", G_CALLBACK (_context_disabled_cb) },
1423 for (i = 0; i < G_N_ELEMENTS (signals); i++) {
1424 g_signal_connect (context,
1426 signals[i].callback,
1430 if (ibus->enable_by_default) {
1431 bus_input_context_enable (context);
1434 /* register the context object so that the object could handle IBus.InputContext method calls. */
1435 bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
1436 (IBusService *) context);
1437 g_object_ref (context);
1442 * _ibus_create_input_context:
1444 * Implement the "CreateInputContext" method call of the org.freedesktop.IBus interface.
1447 _ibus_create_input_context (BusIBusImpl *ibus,
1448 GVariant *parameters,
1449 GDBusMethodInvocation *invocation)
1451 const gchar *client_name = NULL; // e.g. "gtk-im"
1452 g_variant_get (parameters, "(&s)", &client_name);
1454 BusConnection *connection =
1455 bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
1456 BusInputContext *context =
1457 bus_ibus_impl_create_input_context (ibus,
1461 const gchar *path = ibus_service_get_object_path ((IBusService *) context);
1462 /* the format-string 'o' is for a D-Bus object path. */
1463 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
1464 g_object_unref (context);
1467 g_dbus_method_invocation_return_error (invocation,
1469 G_DBUS_ERROR_FAILED,
1470 "Create input context failed!");
1475 * _ibus_current_input_context:
1477 * Implement the "CurrentInputContext" method call of the org.freedesktop.IBus interface.
1480 _ibus_current_input_context (BusIBusImpl *ibus,
1481 GVariant *parameters,
1482 GDBusMethodInvocation *invocation)
1484 if (!ibus->focused_context)
1486 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1487 "No focused input context");
1490 const gchar *path = ibus_service_get_object_path ((IBusService *) ibus->focused_context);
1491 /* the format-string 'o' is for a D-Bus object path. */
1492 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
1497 _component_destroy_cb (BusComponent *component,
1500 g_assert (BUS_IS_IBUS_IMPL (ibus));
1501 g_assert (BUS_IS_COMPONENT (component));
1503 ibus->registered_components = g_list_remove (ibus->registered_components, component);
1505 /* remove engines from engine_list */
1506 GList *engines = bus_component_get_engines (component);
1508 for (p = engines; p != NULL; p = p->next) {
1509 if (g_list_find (ibus->register_engine_list, p->data)) {
1510 ibus->register_engine_list = g_list_remove (ibus->register_engine_list, p->data);
1511 g_object_unref (p->data);
1514 g_list_free (engines);
1516 g_object_unref (component);
1518 bus_ibus_impl_engines_maybe_removed (ibus);
1519 bus_ibus_impl_update_engines_hotkey_profile (ibus);
1523 * _ibus_register_component:
1525 * Implement the "RegisterComponent" method call of the org.freedesktop.IBus interface.
1528 _ibus_register_component (BusIBusImpl *ibus,
1529 GVariant *parameters,
1530 GDBusMethodInvocation *invocation)
1532 GVariant *variant = g_variant_get_child_value (parameters, 0);
1533 IBusComponent *component = (IBusComponent *) ibus_serializable_deserialize (variant);
1535 if (!IBUS_IS_COMPONENT (component)) {
1537 g_object_unref (component);
1538 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1539 "The first argument should be an IBusComponent.");
1543 BusConnection *connection = bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
1544 BusFactoryProxy *factory = bus_factory_proxy_new (connection);
1546 if (factory == NULL) {
1547 g_object_unref (component);
1548 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1549 "Create factory failed.");
1553 g_object_ref_sink (component);
1555 BusComponent *buscomp = bus_component_new (component, factory);
1556 bus_component_set_destroy_with_factory (buscomp, TRUE);
1557 g_object_unref (component);
1558 g_object_unref (factory);
1560 ibus->registered_components = g_list_append (ibus->registered_components,
1561 g_object_ref_sink (buscomp));
1562 GList *engines = bus_component_get_engines (buscomp);
1563 g_list_foreach (engines, (GFunc) g_object_ref, NULL);
1564 ibus->register_engine_list = g_list_concat (ibus->register_engine_list,
1567 g_signal_connect (buscomp, "destroy", G_CALLBACK (_component_destroy_cb), ibus);
1569 bus_ibus_impl_update_engines_hotkey_profile (ibus);
1571 g_dbus_method_invocation_return_value (invocation, NULL);
1575 * _ibus_list_engines:
1577 * Implement the "ListEngines" method call of the org.freedesktop.IBus interface.
1580 _ibus_list_engines (BusIBusImpl *ibus,
1581 GVariant *parameters,
1582 GDBusMethodInvocation *invocation)
1584 GVariantBuilder builder;
1585 g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1587 GList *engines = bus_registry_get_engines (ibus->registry);
1589 for (p = engines; p != NULL; p = p->next) {
1590 g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1592 g_list_free (engines);
1593 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1597 * _ibus_list_active_engines:
1599 * Implement the "ListActiveEngines" method call of the org.freedesktop.IBus interface.
1602 _ibus_list_active_engines (BusIBusImpl *ibus,
1603 GVariant *parameters,
1604 GDBusMethodInvocation *invocation)
1606 GVariantBuilder builder;
1607 g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1610 for (p = ibus->engine_list; p != NULL; p = p->next) {
1611 g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1613 for (p = ibus->register_engine_list; p != NULL; p = p->next) {
1614 g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1616 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1622 * Implement the "Exit" method call of the org.freedesktop.IBus interface.
1625 _ibus_exit (BusIBusImpl *ibus,
1626 GVariant *parameters,
1627 GDBusMethodInvocation *invocation)
1629 gboolean restart = FALSE;
1630 g_variant_get (parameters, "(b)", &restart);
1632 g_dbus_method_invocation_return_value (invocation, NULL);
1634 /* Make sure the reply has been sent out before exit */
1635 g_dbus_connection_flush_sync (g_dbus_method_invocation_get_connection (invocation),
1644 extern gchar **g_argv;
1648 exe = g_strdup_printf ("/proc/%d/exe", getpid ());
1649 exe = g_file_read_link (exe, NULL);
1652 exe = BINDIR "/ibus-daemon";
1654 /* close all fds except stdin, stdout, stderr */
1655 for (fd = 3; fd <= sysconf (_SC_OPEN_MAX); fd ++) {
1659 execv (exe, g_argv);
1661 /* If the server binary is replaced while the server is running,
1662 * "readlink /proc/[pid]/exe" might return a path with " (deleted)"
1664 const gchar suffix[] = " (deleted)";
1665 if (g_str_has_suffix (exe, suffix)) {
1666 exe [strlen (exe) - sizeof (suffix) + 1] = '\0';
1667 execv (exe, g_argv);
1669 g_warning ("execv %s failed!", g_argv[0]);
1673 /* should not reach here */
1674 g_assert_not_reached ();
1680 * Implement the "Ping" method call of the org.freedesktop.IBus interface.
1683 _ibus_ping (BusIBusImpl *ibus,
1684 GVariant *parameters,
1685 GDBusMethodInvocation *invocation)
1687 g_dbus_method_invocation_return_value (invocation, parameters);
1691 * _ibus_get_use_sys_layout:
1693 * Implement the "GetUseSysLayout" method call of the org.freedesktop.IBus interface.
1696 _ibus_get_use_sys_layout (BusIBusImpl *ibus,
1697 GVariant *parameters,
1698 GDBusMethodInvocation *invocation)
1700 g_dbus_method_invocation_return_value (invocation,
1701 g_variant_new ("(b)", ibus->use_sys_layout));
1705 * _ibus_get_use_global_engine:
1707 * Implement the "GetUseGlobalEngine" method call of the org.freedesktop.IBus interface.
1710 _ibus_get_use_global_engine (BusIBusImpl *ibus,
1711 GVariant *parameters,
1712 GDBusMethodInvocation *invocation)
1714 g_dbus_method_invocation_return_value (invocation,
1715 g_variant_new ("(b)", ibus->use_global_engine));
1719 * _ibus_get_global_engine:
1721 * Implement the "GetGlobalEngine" method call of the org.freedesktop.IBus interface.
1724 _ibus_get_global_engine (BusIBusImpl *ibus,
1725 GVariant *parameters,
1726 GDBusMethodInvocation *invocation)
1728 IBusEngineDesc *desc = NULL;
1731 if (!ibus->use_global_engine)
1733 BusInputContext *context = ibus->focused_context;
1734 if (context == NULL)
1735 context = ibus->fake_context;
1737 desc = bus_input_context_get_engine_desc (context);
1742 GVariant *variant = ibus_serializable_serialize ((IBusSerializable *) desc);
1743 g_dbus_method_invocation_return_value (invocation,
1744 g_variant_new ("(v)", variant));
1748 g_dbus_method_invocation_return_error (invocation,
1749 G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1750 "No global engine.");
1753 struct _SetGlobalEngineData {
1755 GDBusMethodInvocation *invocation;
1757 typedef struct _SetGlobalEngineData SetGlobalEngineData;
1760 _ibus_set_global_engine_ready_cb (BusInputContext *context,
1762 SetGlobalEngineData *data)
1764 BusIBusImpl *ibus = data->ibus;
1766 GError *error = NULL;
1767 if (!bus_input_context_set_engine_by_desc_finish (context, res, &error)) {
1768 g_error_free (error);
1769 g_dbus_method_invocation_return_error (data->invocation,
1771 G_DBUS_ERROR_FAILED,
1772 "Set global engine failed.");
1776 g_dbus_method_invocation_return_value (data->invocation, NULL);
1778 if (ibus->use_global_engine && (context != ibus->focused_context)) {
1779 /* context and ibus->focused_context don't match. This means that
1780 * the focus is moved before _ibus_set_global_engine() asynchronous
1781 * call finishes. In this case, the engine for the context currently
1782 * being focused hasn't been updated. Update the engine here so that
1783 * subsequent _ibus_get_global_engine() call could return a
1784 * consistent engine name. */
1785 BusEngineProxy *engine = bus_input_context_get_engine (context);
1786 if (engine && ibus->focused_context != NULL) {
1787 g_object_ref (engine);
1788 bus_input_context_set_engine (context, NULL);
1789 bus_input_context_set_engine (ibus->focused_context, engine);
1790 g_object_unref (engine);
1795 g_object_unref (ibus);
1796 g_slice_free (SetGlobalEngineData, data);
1800 * _ibus_set_global_engine:
1802 * Implement the "SetGlobalEngine" method call of the org.freedesktop.IBus interface.
1805 _ibus_set_global_engine (BusIBusImpl *ibus,
1806 GVariant *parameters,
1807 GDBusMethodInvocation *invocation)
1809 if (!ibus->use_global_engine) {
1810 g_dbus_method_invocation_return_error (invocation,
1811 G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1812 "Global engine feature is disabled.");
1816 BusInputContext *context = ibus->focused_context;
1817 if (context == NULL)
1818 context = ibus->fake_context;
1820 const gchar *engine_name = NULL;
1821 g_variant_get (parameters, "(&s)", &engine_name);
1823 IBusEngineDesc *desc = _find_engine_desc_by_name (ibus, engine_name);
1825 g_dbus_method_invocation_return_error (invocation,
1827 G_DBUS_ERROR_FAILED,
1828 "Can not find engine %s.",
1833 SetGlobalEngineData *data = g_slice_new0 (SetGlobalEngineData);
1834 data->ibus = g_object_ref (ibus);
1835 data->invocation = invocation;
1836 bus_input_context_set_engine_by_desc (context,
1838 g_gdbus_timeout, /* timeout in msec. */
1839 NULL, /* we do not cancel the call. */
1840 (GAsyncReadyCallback) _ibus_set_global_engine_ready_cb,
1845 * _ibus_is_global_engine_enabled:
1847 * Implement the "IsGlobalEngineEnabled" method call of the org.freedesktop.IBus interface.
1850 _ibus_is_global_engine_enabled (BusIBusImpl *ibus,
1851 GVariant *parameters,
1852 GDBusMethodInvocation *invocation)
1854 gboolean enabled = FALSE;
1857 if (!ibus->use_global_engine)
1860 BusInputContext *context = ibus->focused_context;
1861 if (context == NULL)
1862 context = ibus->fake_context;
1863 if (context == NULL)
1866 enabled = bus_input_context_is_enabled (context);
1869 g_dbus_method_invocation_return_value (invocation,
1870 g_variant_new ("(b)", enabled));
1874 * bus_ibus_impl_service_method_call:
1876 * Handle a D-Bus method call whose destination and interface name are both "org.freedesktop.IBus"
1879 bus_ibus_impl_service_method_call (IBusService *service,
1880 GDBusConnection *connection,
1881 const gchar *sender,
1882 const gchar *object_path,
1883 const gchar *interface_name,
1884 const gchar *method_name,
1885 GVariant *parameters,
1886 GDBusMethodInvocation *invocation)
1888 if (g_strcmp0 (interface_name, "org.freedesktop.IBus") != 0) {
1889 IBUS_SERVICE_CLASS (bus_ibus_impl_parent_class)->service_method_call (
1890 service, connection, sender, object_path, interface_name, method_name,
1891 parameters, invocation);
1895 /* all methods in the xml definition above should be listed here. */
1896 static const struct {
1897 const gchar *method_name;
1898 void (* method_callback) (BusIBusImpl *, GVariant *, GDBusMethodInvocation *);
1900 /* IBus interface */
1901 { "GetAddress", _ibus_get_address },
1902 { "CreateInputContext", _ibus_create_input_context },
1903 { "CurrentInputContext", _ibus_current_input_context },
1904 { "RegisterComponent", _ibus_register_component },
1905 { "ListEngines", _ibus_list_engines },
1906 { "ListActiveEngines", _ibus_list_active_engines },
1907 { "Exit", _ibus_exit },
1908 { "Ping", _ibus_ping },
1909 { "GetUseSysLayout", _ibus_get_use_sys_layout },
1910 { "GetUseGlobalEngine", _ibus_get_use_global_engine },
1911 { "GetGlobalEngine", _ibus_get_global_engine },
1912 { "SetGlobalEngine", _ibus_set_global_engine },
1913 { "IsGlobalEngineEnabled", _ibus_is_global_engine_enabled },
1917 for (i = 0; i < G_N_ELEMENTS (methods); i++) {
1918 if (g_strcmp0 (methods[i].method_name, method_name) == 0) {
1919 methods[i].method_callback ((BusIBusImpl *) service, parameters, invocation);
1924 /* notreached - unknown method calls that are not in the introspection_xml should be handled by the GDBus library. */
1925 g_return_if_reached ();
1929 bus_ibus_impl_get_default (void)
1931 static BusIBusImpl *ibus = NULL;
1934 ibus = (BusIBusImpl *) g_object_new (BUS_TYPE_IBUS_IMPL,
1935 "object-path", IBUS_PATH_IBUS,
1942 bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
1945 g_assert (BUS_IS_IBUS_IMPL (ibus));
1947 BusFactoryProxy *factory;
1949 factory = (BusFactoryProxy *) g_hash_table_lookup (ibus->factory_dict, path);
1955 bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus)
1957 g_assert (BUS_IS_IBUS_IMPL (ibus));
1959 return ibus->hotkey_profile;
1963 bus_ibus_impl_get_keymap (BusIBusImpl *ibus)
1966 g_assert (BUS_IS_IBUS_IMPL (ibus));
1968 return ibus->keymap;
1972 bus_ibus_impl_get_registry (BusIBusImpl *ibus)
1975 g_assert (BUS_IS_IBUS_IMPL (ibus));
1977 return ibus->registry;
1981 * bus_ibus_impl_emit_signal:
1983 * Send a D-Bus signal to buses (connections) that are listening to the signal.
1986 bus_ibus_impl_emit_signal (BusIBusImpl *ibus,
1987 const gchar *signal_name,
1988 GVariant *parameters)
1990 static guint32 serial = 0;
1991 GDBusMessage *message = g_dbus_message_new_signal ("/org/freedesktop/IBus",
1992 "org.freedesktop.IBus",
1994 /* set a non-zero serial to make libdbus happy */
1995 g_dbus_message_set_serial (message, ++serial);
1996 g_dbus_message_set_sender (message, "org.freedesktop.IBus");
1998 g_dbus_message_set_body (message, parameters);
1999 bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
2000 g_object_unref (message);
2004 bus_ibus_impl_registry_changed (BusIBusImpl *ibus)
2006 bus_ibus_impl_emit_signal (ibus, "RegistryChanged", NULL);
2010 bus_ibus_impl_global_engine_changed (BusIBusImpl *ibus)
2012 const gchar *name = ibus->global_engine_name ? ibus->global_engine_name : "";
2013 bus_ibus_impl_emit_signal (ibus, "GlobalEngineChanged",
2014 g_variant_new ("(s)", name));
2018 bus_ibus_impl_filter_keyboard_shortcuts (BusIBusImpl *ibus,
2019 BusInputContext *context,
2023 guint prev_modifiers)
2025 static GQuark trigger = 0;
2026 static GQuark enable_unconditional = 0;
2027 static GQuark disable_unconditional = 0;
2028 static GQuark next = 0;
2029 static GQuark previous = 0;
2035 trigger = g_quark_from_static_string ("trigger");
2036 enable_unconditional = g_quark_from_static_string ("enable-unconditional");
2037 disable_unconditional = g_quark_from_static_string ("disable-unconditional");
2038 next = g_quark_from_static_string ("next-engine-in-menu");
2039 previous = g_quark_from_static_string ("previous-engine");
2042 /* Try global hotkeys first. */
2043 event = ibus_hotkey_profile_filter_key_event (ibus->hotkey_profile,
2050 if (event == trigger) {
2051 gboolean enabled = bus_input_context_is_enabled (context);
2053 bus_input_context_disable (context);
2056 bus_input_context_enable (context);
2058 return (enabled != bus_input_context_is_enabled (context));
2060 if (event == enable_unconditional) {
2061 gboolean enabled = bus_input_context_is_enabled (context);
2063 bus_input_context_enable (context);
2065 return bus_input_context_is_enabled (context);
2067 if (event == disable_unconditional) {
2068 gboolean enabled = bus_input_context_is_enabled (context);
2070 bus_input_context_disable (context);
2072 return !bus_input_context_is_enabled (context);
2074 if (event == next) {
2075 if (bus_input_context_is_enabled (context)) {
2076 bus_ibus_impl_context_request_next_engine_in_menu (ibus, context);
2079 bus_input_context_enable (context);
2083 if (event == previous) {
2084 if (bus_input_context_is_enabled (context)) {
2085 bus_ibus_impl_context_request_previous_engine (ibus, context);
2088 bus_input_context_enable (context);
2093 if (!ibus->engines_hotkey_profile || !ibus->hotkey_to_engines_map) {
2097 /* Then try engines hotkeys. */
2098 event = ibus_hotkey_profile_filter_key_event (ibus->engines_hotkey_profile,
2108 engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
2109 GUINT_TO_POINTER (event));
2111 BusEngineProxy *current_engine = bus_input_context_get_engine (context);
2112 IBusEngineDesc *current_engine_desc =
2113 (current_engine ? bus_engine_proxy_get_desc (current_engine) : NULL);
2114 IBusEngineDesc *new_engine_desc = (IBusEngineDesc *) engine_list->data;
2116 g_assert (new_engine_desc);
2118 /* Find out what engine we should switch to. If the current engine has
2119 * the same hotkey, then we should switch to the next engine with the
2120 * same hotkey in the list. Otherwise, we just switch to the first
2121 * engine in the list. */
2122 GList *p = engine_list;
2123 for (; p->next != NULL; p = p->next) {
2124 if (current_engine_desc == (IBusEngineDesc *) p->data) {
2125 new_engine_desc = (IBusEngineDesc *) p->next->data;
2130 if (current_engine_desc != new_engine_desc) {
2131 bus_ibus_impl_set_context_engine_from_desc (ibus, context, new_engine_desc);
2141 * bus_ibus_impl_load_global_engine_name_from_config:
2143 * Retrieve the "global_engine" config from the config daemon. Return NULL if the daemon is not ready.
2146 bus_ibus_impl_load_global_engine_name_from_config (BusIBusImpl *ibus)
2148 g_assert (BUS_IS_IBUS_IMPL (ibus));
2149 if (ibus->config == NULL) {
2150 /* the config component is not started yet. */
2153 g_assert (IBUS_IS_CONFIG (ibus->config));
2155 GVariant *variant = ibus_config_get_value (ibus->config, "general", "global_engine");
2156 gchar *engine_name = NULL;
2157 if (variant != NULL) {
2158 g_variant_get (variant, "s", &engine_name);
2159 g_variant_unref (variant);
2165 * bus_ibus_impl_save_global_engine_name_to_config:
2167 * Save the "global_engine" config value on the config daemon. No-op if the daemon is not ready.
2170 bus_ibus_impl_save_global_engine_name_to_config (BusIBusImpl *ibus)
2172 g_assert (BUS_IS_IBUS_IMPL (ibus));
2175 ibus->use_global_engine &&
2176 ibus->global_engine_name) {
2177 ibus_config_set_value (ibus->config,
2178 "general", "global_engine",
2179 g_variant_new ("s", ibus->global_engine_name));
2184 * bus_ibus_impl_load_global_previous_engine_name_from_config:
2186 * Retrieve the "global_previous_engine" config from the config daemon. Return NULL if the daemon is not ready.
2189 bus_ibus_impl_load_global_previous_engine_name_from_config (BusIBusImpl *ibus)
2191 g_assert (BUS_IS_IBUS_IMPL (ibus));
2192 if (ibus->config == NULL) {
2193 /* the config component is not started yet. */
2196 g_assert (IBUS_IS_CONFIG (ibus->config));
2198 GVariant *value = ibus_config_get_value (ibus->config, "general", "global_previous_engine");
2201 gchar *engine_name = NULL;
2202 g_variant_get (value, "(s)", &engine_name);
2203 g_variant_unref (value);
2208 * bus_ibus_impl_save_global_previous_engine_name_to_config:
2210 * Save the "global_previous_engine" config value on the config daemon. No-op if the daemon is not ready.
2213 bus_ibus_impl_save_global_previous_engine_name_to_config (BusIBusImpl *ibus)
2215 g_assert (BUS_IS_IBUS_IMPL (ibus));
2218 ibus->use_global_engine &&
2219 ibus->global_previous_engine_name) {
2220 ibus_config_set_value (ibus->config,
2221 "general", "global_previous_engine",
2222 g_variant_new ("s", ibus->global_previous_engine_name));
2227 * _add_engine_hotkey:
2229 * Check the engine-specific hot key of the engine, and update ibus->engines_hotkey_profile.
2232 _add_engine_hotkey (IBusEngineDesc *engine, BusIBusImpl *ibus)
2234 const gchar *hotkeys;
2235 gchar **hotkey_list;
2248 hotkeys = ibus_engine_desc_get_hotkeys (engine);
2250 if (!hotkeys || !*hotkeys) {
2254 hotkey_list = g_strsplit_set (hotkeys, ";,", 0);
2256 for (p = hotkey_list; p && *p; ++p) {
2257 hotkey = g_strstrip (*p);
2258 if (!*hotkey || !ibus_key_event_from_string (hotkey, &keyval, &modifiers)) {
2262 /* If the hotkey already exists, we won't need to add it again. */
2263 event = ibus_hotkey_profile_lookup_hotkey (ibus->engines_hotkey_profile,
2266 event = g_quark_from_string (hotkey);
2267 ibus_hotkey_profile_add_hotkey (ibus->engines_hotkey_profile,
2268 keyval, modifiers, event);
2271 engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
2272 GUINT_TO_POINTER (event));
2274 /* As we will rebuild the engines hotkey map whenever an engine was
2275 * added or removed, we don't need to hold a reference of the engine
2277 engine_list = g_list_append (engine_list, engine);
2279 /* We need to steal the value before adding it back, otherwise it will
2281 g_hash_table_steal (ibus->hotkey_to_engines_map, GUINT_TO_POINTER (event));
2283 g_hash_table_insert (ibus->hotkey_to_engines_map,
2284 GUINT_TO_POINTER (event), engine_list);
2287 g_strfreev (hotkey_list);
2291 * bus_ibus_impl_update_engines_hotkey_profile:
2293 * Check engine-specific hot keys of all active engines, and update ibus->engines_hotkey_profile.
2296 bus_ibus_impl_update_engines_hotkey_profile (BusIBusImpl *ibus)
2298 if (ibus->engines_hotkey_profile) {
2299 g_object_unref (ibus->engines_hotkey_profile);
2302 if (ibus->hotkey_to_engines_map) {
2303 g_hash_table_unref (ibus->hotkey_to_engines_map);
2306 ibus->engines_hotkey_profile = ibus_hotkey_profile_new ();
2307 ibus->hotkey_to_engines_map =
2308 g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_list_free);
2310 g_list_foreach (ibus->register_engine_list, (GFunc) _add_engine_hotkey, ibus);
2311 g_list_foreach (ibus->engine_list, (GFunc) _add_engine_hotkey, ibus);
2315 bus_ibus_impl_is_use_sys_layout (BusIBusImpl *ibus)
2317 g_assert (BUS_IS_IBUS_IMPL (ibus));
2319 return ibus->use_sys_layout;
2323 bus_ibus_impl_is_embed_preedit_text (BusIBusImpl *ibus)
2325 g_assert (BUS_IS_IBUS_IMPL (ibus));
2327 return ibus->embed_preedit_text;
2331 bus_ibus_impl_get_focused_input_context (BusIBusImpl *ibus)
2333 g_assert (BUS_IS_IBUS_IMPL (ibus));
2335 return ibus->focused_context;