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"
236 " <arg type='s' name='engine_name' />\n"
242 G_DEFINE_TYPE (BusIBusImpl, bus_ibus_impl, IBUS_TYPE_SERVICE)
245 bus_ibus_impl_class_init (BusIBusImplClass *class)
247 IBUS_OBJECT_CLASS (class)->destroy = (IBusObjectDestroyFunc) bus_ibus_impl_destroy;
249 /* override the parent class's implementation. */
250 IBUS_SERVICE_CLASS (class)->service_method_call = bus_ibus_impl_service_method_call;
251 /* 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'.) */
252 ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml);
258 * A callback function which is called when (1) the connection to the panel process is terminated,
259 * or (2) ibus_proxy_destroy (ibus->panel); is called. See src/ibusproxy.c for details.
262 _panel_destroy_cb (BusPanelProxy *panel,
265 g_assert (BUS_IS_PANEL_PROXY (panel));
266 g_assert (BUS_IS_IBUS_IMPL (ibus));
268 g_return_if_fail (ibus->panel == panel);
271 g_object_unref (panel);
275 bus_ibus_impl_set_hotkey (BusIBusImpl *ibus,
279 g_assert (BUS_IS_IBUS_IMPL (ibus));
281 ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
288 g_variant_iter_init (&iter, value);
289 const gchar *str = NULL;
290 while (g_variant_iter_loop (&iter,"&s", &str)) {
291 ibus_hotkey_profile_add_hotkey_from_string (ibus->hotkey_profile,
299 * bus_ibus_impl_set_trigger:
301 * A function to be called when "trigger" config is updated. If the value is NULL, the default trigger (Ctrl+space) is set.
304 bus_ibus_impl_set_trigger (BusIBusImpl *ibus,
307 GQuark hotkey = g_quark_from_static_string ("trigger");
309 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
313 /* set default trigger */
314 ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
315 ibus_hotkey_profile_add_hotkey (ibus->hotkey_profile,
324 * bus_ibus_impl_set_enable_unconditional:
326 * A function to be called when "enable_unconditional" config is updated.
329 bus_ibus_impl_set_enable_unconditional (BusIBusImpl *ibus,
332 GQuark hotkey = g_quark_from_static_string ("enable-unconditional");
333 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
337 * bus_ibus_impl_set_disable_unconditional:
339 * A function to be called when "disable_unconditional" config is updated.
342 bus_ibus_impl_set_disable_unconditional (BusIBusImpl *ibus,
345 GQuark hotkey = g_quark_from_static_string ("disable-unconditional");
346 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
350 * bus_ibus_impl_set_next_engine_in_menu:
352 * A function to be called when "next_engine_in_menu" config is updated.
355 bus_ibus_impl_set_next_engine_in_menu (BusIBusImpl *ibus,
358 GQuark hotkey = g_quark_from_static_string ("next-engine-in-menu");
359 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
363 * bus_ibus_impl_set_previous_engine:
365 * A function to be called when "previous_engine" config is updated.
368 bus_ibus_impl_set_previous_engine (BusIBusImpl *ibus,
371 GQuark hotkey = g_quark_from_static_string ("previous-engine");
372 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
376 * bus_ibus_impl_set_preload_engines:
378 * A function to be called when "preload_engines" config is updated.
381 bus_ibus_impl_set_preload_engines (BusIBusImpl *ibus,
384 GList *engine_list = NULL;
386 g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
387 g_list_free (ibus->engine_list);
389 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_ARRAY) {
391 g_variant_iter_init (&iter, value);
392 const gchar *engine_name = NULL;
393 while (g_variant_iter_loop (&iter, "&s", &engine_name)) {
394 IBusEngineDesc *engine = bus_registry_find_engine_by_name (ibus->registry, engine_name);
395 if (engine == NULL || g_list_find (engine_list, engine) != NULL)
397 engine_list = g_list_append (engine_list, engine);
401 g_list_foreach (engine_list, (GFunc) g_object_ref, NULL);
402 ibus->engine_list = engine_list;
404 if (ibus->engine_list) {
405 BusComponent *component = bus_component_from_engine_desc ((IBusEngineDesc *) ibus->engine_list->data);
406 if (component && !bus_component_is_running (component)) {
407 bus_component_start (component, g_verbose);
411 bus_ibus_impl_update_engines_hotkey_profile (ibus);
415 * bus_ibus_impl_set_use_sys_layout:
417 * A function to be called when "use_system_keyboard_layout" config is updated.
420 bus_ibus_impl_set_use_sys_layout (BusIBusImpl *ibus,
423 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
424 ibus->use_sys_layout = g_variant_get_boolean (value);
429 * bus_ibus_impl_set_embed_preedit_text:
431 * A function to be called when "use_embed_preedit_text" config is updated.
434 bus_ibus_impl_set_embed_preedit_text (BusIBusImpl *ibus,
437 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
438 ibus->embed_preedit_text = g_variant_get_boolean (value);
443 * bus_ibus_impl_set_enable_by_default:
445 * A function to be called when "enable_by_default" config is updated.
448 bus_ibus_impl_set_enable_by_default (BusIBusImpl *ibus,
451 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
452 ibus->enable_by_default = g_variant_get_boolean (value);
457 * bus_ibus_impl_set_use_global_engine:
459 * A function to be called when "use_global_engine" config is updated.
462 bus_ibus_impl_set_use_global_engine (BusIBusImpl *ibus,
465 if (value == NULL || g_variant_classify (value) != G_VARIANT_CLASS_BOOLEAN)
468 gboolean new_value = g_variant_get_boolean (value);
469 if (ibus->use_global_engine == new_value)
473 /* turn on use_global_engine option */
474 ibus->use_global_engine = TRUE;
475 if (ibus->panel && ibus->focused_context == NULL) {
476 bus_panel_proxy_focus_in (ibus->panel, ibus->fake_context);
480 /* turn off use_global_engine option */
481 ibus->use_global_engine = FALSE;
483 /* if fake context has the focus, we should focus out it */
484 if (ibus->panel && ibus->focused_context == NULL) {
485 bus_panel_proxy_focus_out (ibus->panel, ibus->fake_context);
487 /* remove engine in fake context */
488 bus_input_context_set_engine (ibus->fake_context, NULL);
494 _engine_desc_cmp (IBusEngineDesc *desc1,
495 IBusEngineDesc *desc2)
497 return - ((gint) ibus_engine_desc_get_rank (desc1)) +
498 ((gint) ibus_engine_desc_get_rank (desc2));
503 * bus_ibus_impl_set_default_preload_engines:
505 * If the "preload_engines" config variable is not set yet, set the default value which is determined based on a current locale.
508 bus_ibus_impl_set_default_preload_engines (BusIBusImpl *ibus)
511 g_assert (BUS_IS_IBUS_IMPL (ibus));
513 static gboolean done = FALSE;
515 if (done || ibus->config == NULL) {
519 GVariant *variant = ibus_config_get_value (ibus->config, "general", "preload_engines");
520 if (variant != NULL) {
522 g_variant_unref (variant);
528 /* The setlocale call first checks LC_ALL. If it's not available, checks
529 * LC_CTYPE. If it's also not available, checks LANG. */
530 gchar *lang = g_strdup (setlocale (LC_CTYPE, NULL));
535 gchar *p = index (lang, '.');
540 GList *engines = bus_registry_get_engines_by_language (ibus->registry, lang);
541 if (engines == NULL) {
542 p = index (lang, '_');
545 engines = bus_registry_get_engines_by_language (ibus->registry, lang);
550 /* sort engines by rank */
551 engines = g_list_sort (engines, (GCompareFunc) _engine_desc_cmp);
553 GVariantBuilder builder;
554 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
556 for (list = engines; list != NULL; list = list->next) {
557 IBusEngineDesc *desc = (IBusEngineDesc *) list->data;
558 /* ignore engines with rank <= 0 */
559 if (ibus_engine_desc_get_rank (desc) > 0)
560 g_variant_builder_add (&builder, "s", ibus_engine_desc_get_name (desc));
563 GVariant *value = g_variant_builder_end (&builder);
565 if (g_variant_n_children (value) > 0) {
566 ibus_config_set_value (ibus->config,
567 "general", "preload_engines", value);
569 /* We don't update preload_engines with an empty string for safety.
570 * Just unref the floating value. */
571 g_variant_unref (value);
574 g_list_free (engines);
578 /* The list of config entries that are related to ibus-daemon. */
579 const static struct {
582 void (*func) (BusIBusImpl *, GVariant *);
583 } bus_ibus_impl_config_items [] = {
584 { "general/hotkey", "trigger", bus_ibus_impl_set_trigger },
585 { "general/hotkey", "enable_unconditional", bus_ibus_impl_set_enable_unconditional },
586 { "general/hotkey", "disable_unconditional", bus_ibus_impl_set_disable_unconditional },
587 { "general/hotkey", "next_engine_in_menu", bus_ibus_impl_set_next_engine_in_menu },
588 { "general/hotkey", "previous_engine", bus_ibus_impl_set_previous_engine },
589 { "general", "preload_engines", bus_ibus_impl_set_preload_engines },
590 { "general", "use_system_keyboard_layout", bus_ibus_impl_set_use_sys_layout },
591 { "general", "use_global_engine", bus_ibus_impl_set_use_global_engine },
592 { "general", "embed_preedit_text", bus_ibus_impl_set_embed_preedit_text },
593 { "general", "enable_by_default", bus_ibus_impl_set_enable_by_default },
597 * bus_ibus_impl_reload_config
599 * Read config entries (e.g. preload_engines) from the config daemon.
602 bus_ibus_impl_reload_config (BusIBusImpl *ibus)
604 g_assert (BUS_IS_IBUS_IMPL (ibus));
607 for (i = 0; i < G_N_ELEMENTS (bus_ibus_impl_config_items); i++) {
608 GVariant *variant = NULL;
609 if (ibus->config != NULL)
610 variant = ibus_config_get_value (ibus->config,
611 bus_ibus_impl_config_items[i].section,
612 bus_ibus_impl_config_items[i].key);
613 bus_ibus_impl_config_items[i].func (ibus, variant); /* variant could be NULL if the deamon is not ready yet. */
614 if (variant) g_variant_unref (variant);
619 * _config_value_changed_cb:
621 * A callback function to be called when the "ValueChanged" D-Bus signal is sent from the config daemon.
624 _config_value_changed_cb (IBusConfig *config,
630 g_assert (IBUS_IS_CONFIG (config));
634 g_assert (BUS_IS_IBUS_IMPL (ibus));
637 for (i = 0; i < G_N_ELEMENTS (bus_ibus_impl_config_items); i++) {
638 if (g_strcmp0 (bus_ibus_impl_config_items[i].section, section) == 0 &&
639 g_strcmp0 (bus_ibus_impl_config_items[i].key, key) == 0) {
640 bus_ibus_impl_config_items[i].func (ibus, value);
647 * _config_destroy_cb:
649 * A callback function which is called when (1) the connection to the config process is terminated,
650 * or (2) ibus_proxy_destroy (ibus->config); is called. See src/ibusproxy.c for details.
653 _config_destroy_cb (IBusConfig *config,
656 g_assert (IBUS_IS_CONFIG (config));
657 g_assert (BUS_IS_IBUS_IMPL (ibus));
659 g_assert (ibus->config == config);
661 g_object_unref (ibus->config);
666 _registry_changed_cb (BusRegistry *registry,
669 bus_ibus_impl_registry_changed (ibus);
673 * _dbus_name_owner_changed_cb:
675 * A callback function to be called when the name-owner-changed signal is sent to the dbus object.
676 * This usually means a client (e.g. a panel/config/engine process or an application) is connected/disconnected to/from the bus.
679 _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
681 const gchar *old_name,
682 const gchar *new_name,
685 g_assert (BUS_IS_DBUS_IMPL (dbus));
686 g_assert (name != NULL);
687 g_assert (old_name != NULL);
688 g_assert (new_name != NULL);
689 g_assert (BUS_IS_IBUS_IMPL (ibus));
691 if (g_strcmp0 (name, IBUS_SERVICE_PANEL) == 0) {
692 if (g_strcmp0 (new_name, "") != 0) {
693 /* a Panel process is started. */
694 BusConnection *connection;
696 if (ibus->panel != NULL) {
697 ibus_proxy_destroy ((IBusProxy *) ibus->panel);
698 /* panel should be NULL after destroy. See _panel_destroy_cb for details. */
699 g_assert (ibus->panel == NULL);
702 connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
703 g_return_if_fail (connection != NULL);
705 ibus->panel = bus_panel_proxy_new (connection);
707 g_signal_connect (ibus->panel,
709 G_CALLBACK (_panel_destroy_cb),
712 if (ibus->focused_context != NULL) {
713 bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context);
715 else if (ibus->use_global_engine) {
716 bus_panel_proxy_focus_in (ibus->panel, ibus->fake_context);
720 else if (g_strcmp0 (name, IBUS_SERVICE_CONFIG) == 0) {
721 if (g_strcmp0 (new_name, "") != 0) {
722 /* a config process is started. */
723 BusConnection *connection;
725 if (ibus->config != NULL) {
726 ibus_proxy_destroy ((IBusProxy *) ibus->config);
727 /* config should be NULL after destroy. See _config_destroy_cb for details. */
728 g_assert (ibus->config == NULL);
731 /* get a connection between ibus-daemon and the config daemon. */
732 connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
733 g_return_if_fail (connection != NULL);
735 ibus->config = g_initable_new (IBUS_TYPE_CONFIG,
738 /* The following properties are necessary to initialize GDBusProxy object
739 * which is a parent of the config object. */
740 "g-connection", bus_connection_get_dbus_connection (connection),
741 "g-flags", G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
742 "g-interface-name", IBUS_INTERFACE_CONFIG,
743 "g-object-path", IBUS_PATH_CONFIG,
744 "g-default-timeout", g_gdbus_timeout,
747 g_signal_connect (ibus->config,
749 G_CALLBACK (_config_value_changed_cb),
752 g_signal_connect (ibus->config,
754 G_CALLBACK (_config_destroy_cb),
757 bus_ibus_impl_set_default_preload_engines (ibus);
758 bus_ibus_impl_reload_config (ibus);
762 bus_registry_name_owner_changed (ibus->registry, name, old_name, new_name);
766 * bus_ibus_impl_init:
768 * The constructor of BusIBusImpl. Initialize all member variables of a BusIBusImpl object.
771 bus_ibus_impl_init (BusIBusImpl *ibus)
773 ibus->factory_dict = g_hash_table_new_full (
777 (GDestroyNotify) g_object_unref);
779 ibus->fake_context = bus_input_context_new (NULL, "fake");
780 g_object_ref_sink (ibus->fake_context);
781 bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
782 (IBusService *) ibus->fake_context);
783 bus_input_context_set_capabilities (ibus->fake_context,
784 IBUS_CAP_PREEDIT_TEXT |
786 IBUS_CAP_SURROUNDING_TEXT);
787 g_signal_connect (ibus->fake_context,
789 G_CALLBACK (_context_engine_changed_cb),
791 bus_input_context_focus_in (ibus->fake_context);
793 ibus->engine_list = NULL;
794 ibus->register_engine_list = NULL;
795 ibus->contexts = NULL;
796 ibus->focused_context = NULL;
800 ibus->registry = bus_registry_new ();
802 g_signal_connect (ibus->registry,
804 G_CALLBACK (_registry_changed_cb),
806 #ifdef G_THREADS_ENABLED
807 extern gint g_monitor_timeout;
808 if (g_monitor_timeout != 0) {
809 /* Start the monitor of registry changes. */
810 bus_registry_start_monitor_changes (ibus->registry);
814 ibus->hotkey_profile = ibus_hotkey_profile_new ();
815 ibus->keymap = ibus_keymap_get ("us");
817 ibus->use_sys_layout = FALSE;
818 ibus->embed_preedit_text = TRUE;
819 ibus->enable_by_default = FALSE;
820 ibus->use_global_engine = FALSE;
821 ibus->global_engine_name = NULL;
822 ibus->global_previous_engine_name = NULL;
824 ibus->engines_hotkey_profile = NULL;
825 ibus->hotkey_to_engines_map = NULL;
827 bus_ibus_impl_reload_config (ibus);
829 g_signal_connect (BUS_DEFAULT_DBUS,
830 "name-owner-changed",
831 G_CALLBACK (_dbus_name_owner_changed_cb),
836 * bus_ibus_impl_destroy:
838 * The destructor of BusIBusImpl.
841 bus_ibus_impl_destroy (BusIBusImpl *ibus)
848 bus_registry_stop_all_components (ibus->registry);
854 while ((pid = waitpid (0, &status, WNOHANG)) > 0);
856 if (pid == -1) { /* all children finished */
859 if (pid == 0) { /* no child status changed */
862 if (timeout >= G_USEC_PER_SEC) {
865 old = signal (SIGTERM, SIG_IGN);
866 /* send TERM signal to the whole process group (i.e. engines, panel, and config daemon.) */
867 kill (-getpid (), SIGTERM);
868 signal (SIGTERM, old);
872 g_warning ("Not every child processes exited!");
879 g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
880 g_list_free (ibus->engine_list);
881 ibus->engine_list = NULL;
883 g_list_foreach (ibus->register_engine_list, (GFunc) g_object_unref, NULL);
884 g_list_free (ibus->register_engine_list);
885 ibus->register_engine_list = NULL;
887 if (ibus->factory_dict != NULL) {
888 g_hash_table_destroy (ibus->factory_dict);
889 ibus->factory_dict = NULL;
892 if (ibus->hotkey_profile != NULL) {
893 g_object_unref (ibus->hotkey_profile);
894 ibus->hotkey_profile = NULL;
897 if (ibus->keymap != NULL) {
898 g_object_unref (ibus->keymap);
902 g_free (ibus->global_engine_name);
903 ibus->global_engine_name = NULL;
905 g_free (ibus->global_previous_engine_name);
906 ibus->global_previous_engine_name = NULL;
908 if (ibus->engines_hotkey_profile != NULL) {
909 g_object_unref (ibus->engines_hotkey_profile);
910 ibus->engines_hotkey_profile = NULL;
913 if (ibus->hotkey_to_engines_map) {
914 g_hash_table_unref (ibus->hotkey_to_engines_map);
915 ibus->hotkey_to_engines_map = NULL;
918 if (ibus->fake_context) {
919 g_object_unref (ibus->fake_context);
920 ibus->fake_context = NULL;
924 IBUS_OBJECT_CLASS (bus_ibus_impl_parent_class)->destroy (IBUS_OBJECT (ibus));
930 * Implement the "GetAddress" method call of the org.freedesktop.IBus interface.
933 _ibus_get_address (BusIBusImpl *ibus,
934 GVariant *parameters,
935 GDBusMethodInvocation *invocation)
937 g_dbus_method_invocation_return_value (invocation,
938 g_variant_new ("(s)", bus_server_get_address ()));
941 static IBusEngineDesc *
942 _find_engine_desc_by_name (BusIBusImpl *ibus,
943 const gchar *engine_name)
945 IBusEngineDesc *desc = NULL;
948 /* find engine in registered engine list */
949 for (p = ibus->register_engine_list; p != NULL; p = p->next) {
950 desc = (IBusEngineDesc *) p->data;
951 if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
955 /* find engine in preload engine list */
956 for (p = ibus->engine_list; p != NULL; p = p->next) {
957 desc = (IBusEngineDesc *) p->data;
958 if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
966 * _context_request_engine_cb:
968 * A callback function to be called when the "request-engine" signal is sent to the context.
971 _context_request_engine_cb (BusInputContext *context,
972 const gchar *engine_name,
975 IBusEngineDesc *desc = NULL;
977 /* context should has focus before request an engine */
978 g_return_if_fail (bus_input_context_has_focus (context) ||
979 context == ibus->focused_context);
981 if (engine_name != NULL && engine_name[0] != '\0') {
982 /* request engine by name */
983 desc = _find_engine_desc_by_name (ibus, engine_name);
984 g_return_if_fail (desc != NULL);
987 /* Use global engine if possible. */
988 if (ibus->use_global_engine) {
989 gchar *name = g_strdup (ibus->global_engine_name);
991 name = bus_ibus_impl_load_global_engine_name_from_config (ibus);
994 desc = _find_engine_desc_by_name (ibus, name);
998 /* request default engine */
1000 if (ibus->register_engine_list) {
1001 desc = (IBusEngineDesc *) ibus->register_engine_list->data;
1003 else if (ibus->engine_list) {
1004 desc = (IBusEngineDesc *) ibus->engine_list->data;
1008 /* no engine is available. the user hasn't ran ibus-setup yet and
1009 * the bus_ibus_impl_set_default_preload_engines() function could
1010 * not find any default engines. another possiblity is that the
1011 * user hasn't installed an engine yet? just give up. */
1012 g_warning ("No engine is available. Run ibus-setup first.");
1017 bus_ibus_impl_set_context_engine_from_desc (ibus, context, desc);
1021 * bus_ibus_impl_context_request_next_engine_in_menu:
1023 * Process the "next_engine_in_menu" hotkey.
1026 bus_ibus_impl_context_request_next_engine_in_menu (BusIBusImpl *ibus,
1027 BusInputContext *context)
1029 BusEngineProxy *engine;
1030 IBusEngineDesc *desc;
1031 IBusEngineDesc *next_desc = NULL;
1034 engine = bus_input_context_get_engine (context);
1035 if (engine == NULL) {
1036 _context_request_engine_cb (context, NULL, ibus);
1040 desc = bus_engine_proxy_get_desc (engine);
1042 p = g_list_find (ibus->register_engine_list, desc);
1047 p = g_list_find (ibus->engine_list, desc);
1054 next_desc = (IBusEngineDesc*) p->data;
1057 if (ibus->register_engine_list) {
1058 next_desc = (IBusEngineDesc *) ibus->register_engine_list->data;
1060 else if (ibus->engine_list) {
1061 next_desc = (IBusEngineDesc *) ibus->engine_list->data;
1065 bus_ibus_impl_set_context_engine_from_desc (ibus, context, next_desc);
1069 * bus_ibus_impl_context_request_previous_engine:
1071 * Process the "previous_engine" hotkey.
1074 bus_ibus_impl_context_request_previous_engine (BusIBusImpl *ibus,
1075 BusInputContext *context)
1077 gchar *engine_name = NULL;
1078 if (!ibus->use_global_engine) {
1079 engine_name = (gchar *) g_object_get_data (G_OBJECT (context), "previous-engine-name");
1082 if (!ibus->global_previous_engine_name) {
1083 ibus->global_previous_engine_name = bus_ibus_impl_load_global_previous_engine_name_from_config (ibus);
1085 engine_name = ibus->global_previous_engine_name;
1089 * If the previous engine name is not found, switch to the next engine
1090 * in the menu. This behavior is better than doing nothing.
1093 bus_ibus_impl_context_request_next_engine_in_menu (ibus, context);
1096 _context_request_engine_cb (context, engine_name, ibus);
1100 bus_ibus_impl_set_context_engine_from_desc (BusIBusImpl *ibus,
1101 BusInputContext *context,
1102 IBusEngineDesc *desc)
1104 bus_input_context_set_engine_by_desc (context,
1106 g_gdbus_timeout, /* timeout in msec. */
1107 NULL, /* we do not cancel the call. */
1108 NULL, /* use the default callback function. */
1113 * bus_ibus_impl_set_focused_context:
1115 * Set the current focused context.
1118 bus_ibus_impl_set_focused_context (BusIBusImpl *ibus,
1119 BusInputContext *context)
1121 g_assert (BUS_IS_IBUS_IMPL (ibus));
1122 g_assert (context == NULL || BUS_IS_INPUT_CONTEXT (context));
1123 g_assert (context == NULL || bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS);
1125 /* Do noting if it is not focused context. */
1126 if (ibus->focused_context == context) {
1130 BusEngineProxy *engine = NULL;
1132 if (ibus->focused_context) {
1133 if (ibus->use_global_engine) {
1134 /* dettach engine from the focused context */
1135 engine = bus_input_context_get_engine (ibus->focused_context);
1137 g_object_ref (engine);
1138 bus_input_context_set_engine (ibus->focused_context, NULL);
1142 if (ibus->panel != NULL)
1143 bus_panel_proxy_focus_out (ibus->panel, ibus->focused_context);
1145 g_object_unref (ibus->focused_context);
1146 ibus->focused_context = NULL;
1149 if (context == NULL && ibus->use_global_engine) {
1150 context = ibus->fake_context;
1154 ibus->focused_context = (BusInputContext *) g_object_ref (context);
1155 /* attach engine to the focused context */
1156 if (engine != NULL) {
1157 bus_input_context_set_engine (context, engine);
1158 if (bus_engine_proxy_is_enabled (engine))
1159 bus_input_context_enable (context);
1160 g_object_unref (engine);
1163 if (ibus->panel != NULL)
1164 bus_panel_proxy_focus_in (ibus->panel, context);
1170 * _context_engine_changed_cb:
1172 * A callback function to be called when the "engine-changed" signal is sent to the context.
1173 * Update global engine as well if necessary.
1176 _context_engine_changed_cb (BusInputContext *context,
1179 if (!ibus->use_global_engine)
1182 if ((context == ibus->focused_context) ||
1183 (ibus->focused_context == NULL && context == ibus->fake_context)) {
1184 BusEngineProxy *engine = bus_input_context_get_engine (context);
1185 if (engine != NULL) {
1186 /* only set global engine if engine is not NULL */
1187 const gchar *name = ibus_engine_desc_get_name (bus_engine_proxy_get_desc (engine));
1188 if (g_strcmp0 (name, ibus->global_engine_name) == 0)
1190 g_free (ibus->global_previous_engine_name);
1191 ibus->global_previous_engine_name = ibus->global_engine_name;
1192 ibus->global_engine_name = g_strdup (name);
1194 bus_ibus_impl_save_global_engine_name_to_config (ibus);
1195 bus_ibus_impl_save_global_previous_engine_name_to_config (ibus);
1196 bus_ibus_impl_global_engine_changed (ibus);
1202 * _context_focus_in_cb:
1204 * A callback function to be called when the "focus-in" signal is sent to the context.
1205 * If necessary, enables the global engine on the context and update ibus->focused_context.
1208 _context_focus_in_cb (BusInputContext *context,
1211 g_assert (BUS_IS_IBUS_IMPL (ibus));
1212 g_assert (BUS_IS_INPUT_CONTEXT (context));
1214 /* Do nothing if context does not support focus.
1215 * The global engine shoule be detached from the focused context. */
1216 if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
1220 bus_ibus_impl_set_focused_context (ibus, context);
1224 * _context_focus_out_cb:
1226 * A callback function to be called when the "focus-out" signal is sent to the context.
1229 _context_focus_out_cb (BusInputContext *context,
1232 g_assert (BUS_IS_IBUS_IMPL (ibus));
1233 g_assert (BUS_IS_INPUT_CONTEXT (context));
1235 /* Do noting if context does not support focus.
1236 * Actually, the context should emit focus signals, if it does not support focus */
1237 if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
1241 /* Do noting if it is not focused context. */
1242 if (ibus->focused_context != context) {
1247 if (ibus->use_global_engine == FALSE) {
1248 /* Do not change the focused context, if use_global_engine option is enabled.
1249 * If focused context swith to NULL, users can not swith engine in panel anymore.
1251 bus_ibus_impl_set_focused_context (ibus, NULL);
1256 * _context_destroy_cb:
1258 * A callback function to be called when the "destroy" signal is sent to the context.
1261 _context_destroy_cb (BusInputContext *context,
1264 g_assert (BUS_IS_IBUS_IMPL (ibus));
1265 g_assert (BUS_IS_INPUT_CONTEXT (context));
1267 if (context == ibus->focused_context) {
1268 bus_ibus_impl_set_focused_context (ibus, NULL);
1271 ibus->contexts = g_list_remove (ibus->contexts, context);
1272 g_object_unref (context);
1276 * _context_enabled_cb:
1278 * A callback function to be called when the "enabled" signal is sent to the context.
1281 _context_enabled_cb (BusInputContext *context,
1284 /* FIXME implement this. */
1288 * _context_disabled_cb:
1290 * A callback function to be called when the "disabled" signal is sent to the context.
1293 _context_disabled_cb (BusInputContext *context,
1296 /* FIXME implement this. */
1300 * bus_ibus_impl_create_input_context:
1301 * @client: A name of a client. e.g. "gtk-im"
1302 * @returns: A BusInputContext object.
1304 * Create a new BusInputContext object for the client.
1306 static BusInputContext *
1307 bus_ibus_impl_create_input_context (BusIBusImpl *ibus,
1308 BusConnection *connection,
1309 const gchar *client)
1311 BusInputContext *context = bus_input_context_new (connection, client);
1312 g_object_ref_sink (context);
1313 ibus->contexts = g_list_append (ibus->contexts, context);
1315 /* Installs glib signal handlers so that the ibus object could be notified when e.g. an IBus.InputContext D-Bus method is called. */
1316 static const struct {
1320 { "request-engine", G_CALLBACK (_context_request_engine_cb) },
1321 { "engine-changed", G_CALLBACK (_context_engine_changed_cb) },
1322 { "focus-in", G_CALLBACK (_context_focus_in_cb) },
1323 { "focus-out", G_CALLBACK (_context_focus_out_cb) },
1324 { "destroy", G_CALLBACK (_context_destroy_cb) },
1325 { "enabled", G_CALLBACK (_context_enabled_cb) },
1326 { "disabled", G_CALLBACK (_context_disabled_cb) },
1330 for (i = 0; i < G_N_ELEMENTS (signals); i++) {
1331 g_signal_connect (context,
1333 signals[i].callback,
1337 if (ibus->enable_by_default) {
1338 bus_input_context_enable (context);
1341 /* register the context object so that the object could handle IBus.InputContext method calls. */
1342 bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
1343 (IBusService *) context);
1344 g_object_ref (context);
1349 * _ibus_create_input_context:
1351 * Implement the "CreateInputContext" method call of the org.freedesktop.IBus interface.
1354 _ibus_create_input_context (BusIBusImpl *ibus,
1355 GVariant *parameters,
1356 GDBusMethodInvocation *invocation)
1358 const gchar *client_name = NULL; // e.g. "gtk-im"
1359 g_variant_get (parameters, "(&s)", &client_name);
1361 BusConnection *connection =
1362 bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
1363 BusInputContext *context =
1364 bus_ibus_impl_create_input_context (ibus,
1368 const gchar *path = ibus_service_get_object_path ((IBusService *) context);
1369 /* the format-string 'o' is for a D-Bus object path. */
1370 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
1371 g_object_unref (context);
1374 g_dbus_method_invocation_return_error (invocation,
1376 G_DBUS_ERROR_FAILED,
1377 "Create input context failed!");
1382 * _ibus_current_input_context:
1384 * Implement the "CurrentInputContext" method call of the org.freedesktop.IBus interface.
1387 _ibus_current_input_context (BusIBusImpl *ibus,
1388 GVariant *parameters,
1389 GDBusMethodInvocation *invocation)
1391 if (!ibus->focused_context)
1393 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1394 "No focused input context");
1397 const gchar *path = ibus_service_get_object_path ((IBusService *) ibus->focused_context);
1398 /* the format-string 'o' is for a D-Bus object path. */
1399 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
1404 _component_destroy_cb (BusComponent *component,
1407 g_assert (BUS_IS_IBUS_IMPL (ibus));
1408 g_assert (BUS_IS_COMPONENT (component));
1410 ibus->registered_components = g_list_remove (ibus->registered_components, component);
1412 /* remove engines from engine_list */
1413 GList *engines = bus_component_get_engines (component);
1415 for (p = engines; p != NULL; p = p->next) {
1416 if (g_list_find (ibus->register_engine_list, p->data)) {
1417 ibus->register_engine_list = g_list_remove (ibus->register_engine_list, p->data);
1418 g_object_unref (p->data);
1421 g_list_free (engines);
1423 g_object_unref (component);
1425 bus_ibus_impl_update_engines_hotkey_profile (ibus);
1429 * _ibus_register_component:
1431 * Implement the "RegisterComponent" method call of the org.freedesktop.IBus interface.
1434 _ibus_register_component (BusIBusImpl *ibus,
1435 GVariant *parameters,
1436 GDBusMethodInvocation *invocation)
1438 GVariant *variant = g_variant_get_child_value (parameters, 0);
1439 IBusComponent *component = (IBusComponent *) ibus_serializable_deserialize (variant);
1441 if (!IBUS_IS_COMPONENT (component)) {
1443 g_object_unref (component);
1444 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1445 "The first argument should be an IBusComponent.");
1449 BusConnection *connection = bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
1450 BusFactoryProxy *factory = bus_factory_proxy_new (connection);
1452 if (factory == NULL) {
1453 g_object_unref (component);
1454 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1455 "Create factory failed.");
1459 g_object_ref_sink (component);
1461 BusComponent *buscomp = bus_component_new (component, factory);
1462 bus_component_set_destroy_with_factory (buscomp, TRUE);
1463 g_object_unref (component);
1464 g_object_unref (factory);
1466 ibus->registered_components = g_list_append (ibus->registered_components,
1467 g_object_ref_sink (buscomp));
1468 GList *engines = bus_component_get_engines (buscomp);
1469 g_list_foreach (engines, (GFunc) g_object_ref, NULL);
1470 ibus->register_engine_list = g_list_concat (ibus->register_engine_list,
1473 g_signal_connect (buscomp, "destroy", G_CALLBACK (_component_destroy_cb), ibus);
1475 bus_ibus_impl_update_engines_hotkey_profile (ibus);
1477 g_dbus_method_invocation_return_value (invocation, NULL);
1481 * _ibus_list_engines:
1483 * Implement the "ListEngines" method call of the org.freedesktop.IBus interface.
1486 _ibus_list_engines (BusIBusImpl *ibus,
1487 GVariant *parameters,
1488 GDBusMethodInvocation *invocation)
1490 GVariantBuilder builder;
1491 g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1493 GList *engines = bus_registry_get_engines (ibus->registry);
1495 for (p = engines; p != NULL; p = p->next) {
1496 g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1498 g_list_free (engines);
1499 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1503 * _ibus_list_active_engines:
1505 * Implement the "ListActiveEngines" method call of the org.freedesktop.IBus interface.
1508 _ibus_list_active_engines (BusIBusImpl *ibus,
1509 GVariant *parameters,
1510 GDBusMethodInvocation *invocation)
1512 GVariantBuilder builder;
1513 g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1516 for (p = ibus->engine_list; p != NULL; p = p->next) {
1517 g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1519 for (p = ibus->register_engine_list; p != NULL; p = p->next) {
1520 g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1522 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1528 * Implement the "Exit" method call of the org.freedesktop.IBus interface.
1531 _ibus_exit (BusIBusImpl *ibus,
1532 GVariant *parameters,
1533 GDBusMethodInvocation *invocation)
1535 gboolean restart = FALSE;
1536 g_variant_get (parameters, "(b)", &restart);
1538 g_dbus_method_invocation_return_value (invocation, NULL);
1540 /* Make sure the reply has been sent out before exit */
1541 g_dbus_connection_flush_sync (g_dbus_method_invocation_get_connection (invocation),
1550 extern gchar **g_argv;
1554 exe = g_strdup_printf ("/proc/%d/exe", getpid ());
1555 exe = g_file_read_link (exe, NULL);
1558 exe = BINDIR "/ibus-daemon";
1560 /* close all fds except stdin, stdout, stderr */
1561 for (fd = 3; fd <= sysconf (_SC_OPEN_MAX); fd ++) {
1565 execv (exe, g_argv);
1567 /* If the server binary is replaced while the server is running,
1568 * "readlink /proc/[pid]/exe" might return a path with " (deleted)"
1570 const gchar suffix[] = " (deleted)";
1571 if (g_str_has_suffix (exe, suffix)) {
1572 exe [strlen (exe) - sizeof (suffix) + 1] = '\0';
1573 execv (exe, g_argv);
1575 g_warning ("execv %s failed!", g_argv[0]);
1579 /* should not reach here */
1580 g_assert_not_reached ();
1586 * Implement the "Ping" method call of the org.freedesktop.IBus interface.
1589 _ibus_ping (BusIBusImpl *ibus,
1590 GVariant *parameters,
1591 GDBusMethodInvocation *invocation)
1593 g_dbus_method_invocation_return_value (invocation, parameters);
1597 * _ibus_get_use_sys_layout:
1599 * Implement the "GetUseSysLayout" method call of the org.freedesktop.IBus interface.
1602 _ibus_get_use_sys_layout (BusIBusImpl *ibus,
1603 GVariant *parameters,
1604 GDBusMethodInvocation *invocation)
1606 g_dbus_method_invocation_return_value (invocation,
1607 g_variant_new ("(b)", ibus->use_sys_layout));
1611 * _ibus_get_use_global_engine:
1613 * Implement the "GetUseGlobalEngine" method call of the org.freedesktop.IBus interface.
1616 _ibus_get_use_global_engine (BusIBusImpl *ibus,
1617 GVariant *parameters,
1618 GDBusMethodInvocation *invocation)
1620 g_dbus_method_invocation_return_value (invocation,
1621 g_variant_new ("(b)", ibus->use_global_engine));
1625 * _ibus_get_global_engine:
1627 * Implement the "GetGlobalEngine" method call of the org.freedesktop.IBus interface.
1630 _ibus_get_global_engine (BusIBusImpl *ibus,
1631 GVariant *parameters,
1632 GDBusMethodInvocation *invocation)
1634 IBusEngineDesc *desc = NULL;
1637 if (!ibus->use_global_engine)
1639 BusInputContext *context = ibus->focused_context;
1640 if (context == NULL)
1641 context = ibus->fake_context;
1643 desc = bus_input_context_get_engine_desc (context);
1648 GVariant *variant = ibus_serializable_serialize ((IBusSerializable *) desc);
1649 g_dbus_method_invocation_return_value (invocation,
1650 g_variant_new ("(v)", variant));
1654 g_dbus_method_invocation_return_error (invocation,
1655 G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1656 "No global engine.");
1659 struct _SetGlobalEngineData {
1661 GDBusMethodInvocation *invocation;
1663 typedef struct _SetGlobalEngineData SetGlobalEngineData;
1666 _ibus_set_global_engine_ready_cb (BusInputContext *context,
1668 SetGlobalEngineData *data)
1670 BusIBusImpl *ibus = data->ibus;
1672 GError *error = NULL;
1673 if (!bus_input_context_set_engine_by_desc_finish (context, res, &error)) {
1674 g_error_free (error);
1675 g_dbus_method_invocation_return_error (data->invocation,
1677 G_DBUS_ERROR_FAILED,
1678 "Set global engine failed.");
1682 g_dbus_method_invocation_return_value (data->invocation, NULL);
1684 if (ibus->use_global_engine && (context != ibus->focused_context)) {
1685 /* context and ibus->focused_context don't match. This means that
1686 * the focus is moved before _ibus_set_global_engine() asynchronous
1687 * call finishes. In this case, the engine for the context currently
1688 * being focused hasn't been updated. Update the engine here so that
1689 * subsequent _ibus_get_global_engine() call could return a
1690 * consistent engine name. */
1691 BusEngineProxy *engine = bus_input_context_get_engine (context);
1692 if (engine && ibus->focused_context != NULL) {
1693 g_object_ref (engine);
1694 bus_input_context_set_engine (context, NULL);
1695 bus_input_context_set_engine (ibus->focused_context, engine);
1696 g_object_unref (engine);
1701 g_object_unref (ibus);
1702 g_slice_free (SetGlobalEngineData, data);
1706 * _ibus_set_global_engine:
1708 * Implement the "SetGlobalEngine" method call of the org.freedesktop.IBus interface.
1711 _ibus_set_global_engine (BusIBusImpl *ibus,
1712 GVariant *parameters,
1713 GDBusMethodInvocation *invocation)
1715 if (!ibus->use_global_engine) {
1716 g_dbus_method_invocation_return_error (invocation,
1717 G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1718 "Global engine feature is disabled.");
1722 BusInputContext *context = ibus->focused_context;
1723 if (context == NULL)
1724 context = ibus->fake_context;
1726 const gchar *new_engine_name = NULL;
1727 g_variant_get (parameters, "(&s)", &new_engine_name);
1728 const gchar *old_engine_name = NULL;
1730 BusEngineProxy *engine = bus_input_context_get_engine (context);
1733 ibus_engine_desc_get_name (bus_engine_proxy_get_desc (engine));
1736 if (g_strcmp0 (new_engine_name, old_engine_name) == 0) {
1737 /* If the user requested the same global engine, then we just enable the
1739 bus_input_context_enable (context);
1740 g_dbus_method_invocation_return_value (invocation, NULL);
1744 IBusEngineDesc *desc = _find_engine_desc_by_name (ibus, new_engine_name);
1746 g_dbus_method_invocation_return_error (invocation,
1748 G_DBUS_ERROR_FAILED,
1749 "Can not find engine %s.",
1754 SetGlobalEngineData *data = g_slice_new0 (SetGlobalEngineData);
1755 data->ibus = g_object_ref (ibus);
1756 data->invocation = invocation;
1757 bus_input_context_set_engine_by_desc (context,
1759 g_gdbus_timeout, /* timeout in msec. */
1760 NULL, /* we do not cancel the call. */
1761 (GAsyncReadyCallback) _ibus_set_global_engine_ready_cb,
1766 * _ibus_is_global_engine_enabled:
1768 * Implement the "IsGlobalEngineEnabled" method call of the org.freedesktop.IBus interface.
1771 _ibus_is_global_engine_enabled (BusIBusImpl *ibus,
1772 GVariant *parameters,
1773 GDBusMethodInvocation *invocation)
1775 gboolean enabled = FALSE;
1778 if (!ibus->use_global_engine)
1781 BusInputContext *context = ibus->focused_context;
1782 if (context == NULL)
1783 context = ibus->fake_context;
1784 if (context == NULL)
1787 enabled = bus_input_context_is_enabled (context);
1790 g_dbus_method_invocation_return_value (invocation,
1791 g_variant_new ("(b)", enabled));
1795 * bus_ibus_impl_service_method_call:
1797 * Handle a D-Bus method call whose destination and interface name are both "org.freedesktop.IBus"
1800 bus_ibus_impl_service_method_call (IBusService *service,
1801 GDBusConnection *connection,
1802 const gchar *sender,
1803 const gchar *object_path,
1804 const gchar *interface_name,
1805 const gchar *method_name,
1806 GVariant *parameters,
1807 GDBusMethodInvocation *invocation)
1809 if (g_strcmp0 (interface_name, "org.freedesktop.IBus") != 0) {
1810 IBUS_SERVICE_CLASS (bus_ibus_impl_parent_class)->service_method_call (
1811 service, connection, sender, object_path, interface_name, method_name,
1812 parameters, invocation);
1816 /* all methods in the xml definition above should be listed here. */
1817 static const struct {
1818 const gchar *method_name;
1819 void (* method_callback) (BusIBusImpl *, GVariant *, GDBusMethodInvocation *);
1821 /* IBus interface */
1822 { "GetAddress", _ibus_get_address },
1823 { "CreateInputContext", _ibus_create_input_context },
1824 { "CurrentInputContext", _ibus_current_input_context },
1825 { "RegisterComponent", _ibus_register_component },
1826 { "ListEngines", _ibus_list_engines },
1827 { "ListActiveEngines", _ibus_list_active_engines },
1828 { "Exit", _ibus_exit },
1829 { "Ping", _ibus_ping },
1830 { "GetUseSysLayout", _ibus_get_use_sys_layout },
1831 { "GetUseGlobalEngine", _ibus_get_use_global_engine },
1832 { "GetGlobalEngine", _ibus_get_global_engine },
1833 { "SetGlobalEngine", _ibus_set_global_engine },
1834 { "IsGlobalEngineEnabled", _ibus_is_global_engine_enabled },
1838 for (i = 0; i < G_N_ELEMENTS (methods); i++) {
1839 if (g_strcmp0 (methods[i].method_name, method_name) == 0) {
1840 methods[i].method_callback ((BusIBusImpl *) service, parameters, invocation);
1845 /* notreached - unknown method calls that are not in the introspection_xml should be handled by the GDBus library. */
1846 g_return_if_reached ();
1850 bus_ibus_impl_get_default (void)
1852 static BusIBusImpl *ibus = NULL;
1855 ibus = (BusIBusImpl *) g_object_new (BUS_TYPE_IBUS_IMPL,
1856 "object-path", IBUS_PATH_IBUS,
1863 bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
1866 g_assert (BUS_IS_IBUS_IMPL (ibus));
1868 BusFactoryProxy *factory;
1870 factory = (BusFactoryProxy *) g_hash_table_lookup (ibus->factory_dict, path);
1876 bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus)
1878 g_assert (BUS_IS_IBUS_IMPL (ibus));
1880 return ibus->hotkey_profile;
1884 bus_ibus_impl_get_keymap (BusIBusImpl *ibus)
1887 g_assert (BUS_IS_IBUS_IMPL (ibus));
1889 return ibus->keymap;
1893 bus_ibus_impl_get_registry (BusIBusImpl *ibus)
1896 g_assert (BUS_IS_IBUS_IMPL (ibus));
1898 return ibus->registry;
1902 * bus_ibus_impl_emit_signal:
1904 * Send a D-Bus signal to buses (connections) that are listening to the signal.
1907 bus_ibus_impl_emit_signal (BusIBusImpl *ibus,
1908 const gchar *signal_name,
1909 GVariant *parameters)
1911 static guint32 serial = 0;
1912 GDBusMessage *message = g_dbus_message_new_signal ("/org/freedesktop/IBus",
1913 "org.freedesktop.IBus",
1915 /* set a non-zero serial to make libdbus happy */
1916 g_dbus_message_set_serial (message, ++serial);
1917 g_dbus_message_set_sender (message, "org.freedesktop.IBus");
1919 g_dbus_message_set_body (message, parameters);
1920 bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
1921 g_object_unref (message);
1925 bus_ibus_impl_registry_changed (BusIBusImpl *ibus)
1927 bus_ibus_impl_emit_signal (ibus, "RegistryChanged", NULL);
1931 bus_ibus_impl_global_engine_changed (BusIBusImpl *ibus)
1933 const gchar *name = ibus->global_engine_name ? ibus->global_engine_name : "";
1934 bus_ibus_impl_emit_signal (ibus, "GlobalEngineChanged",
1935 g_variant_new ("(s)", name));
1939 bus_ibus_impl_filter_keyboard_shortcuts (BusIBusImpl *ibus,
1940 BusInputContext *context,
1944 guint prev_modifiers)
1946 static GQuark trigger = 0;
1947 static GQuark enable_unconditional = 0;
1948 static GQuark disable_unconditional = 0;
1949 static GQuark next = 0;
1950 static GQuark previous = 0;
1956 trigger = g_quark_from_static_string ("trigger");
1957 enable_unconditional = g_quark_from_static_string ("enable-unconditional");
1958 disable_unconditional = g_quark_from_static_string ("disable-unconditional");
1959 next = g_quark_from_static_string ("next-engine-in-menu");
1960 previous = g_quark_from_static_string ("previous-engine");
1963 /* Try global hotkeys first. */
1964 event = ibus_hotkey_profile_filter_key_event (ibus->hotkey_profile,
1971 if (event == trigger) {
1972 gboolean enabled = bus_input_context_is_enabled (context);
1974 bus_input_context_disable (context);
1977 bus_input_context_enable (context);
1979 return (enabled != bus_input_context_is_enabled (context));
1981 if (event == enable_unconditional) {
1982 gboolean enabled = bus_input_context_is_enabled (context);
1984 bus_input_context_enable (context);
1986 return bus_input_context_is_enabled (context);
1988 if (event == disable_unconditional) {
1989 gboolean enabled = bus_input_context_is_enabled (context);
1991 bus_input_context_disable (context);
1993 return !bus_input_context_is_enabled (context);
1995 if (event == next) {
1996 if (bus_input_context_is_enabled (context)) {
1997 bus_ibus_impl_context_request_next_engine_in_menu (ibus, context);
2000 bus_input_context_enable (context);
2004 if (event == previous) {
2005 if (bus_input_context_is_enabled (context)) {
2006 bus_ibus_impl_context_request_previous_engine (ibus, context);
2009 bus_input_context_enable (context);
2014 if (!ibus->engines_hotkey_profile || !ibus->hotkey_to_engines_map) {
2018 /* Then try engines hotkeys. */
2019 event = ibus_hotkey_profile_filter_key_event (ibus->engines_hotkey_profile,
2029 engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
2030 GUINT_TO_POINTER (event));
2032 BusEngineProxy *current_engine = bus_input_context_get_engine (context);
2033 IBusEngineDesc *current_engine_desc =
2034 (current_engine ? bus_engine_proxy_get_desc (current_engine) : NULL);
2035 IBusEngineDesc *new_engine_desc = (IBusEngineDesc *) engine_list->data;
2037 g_assert (new_engine_desc);
2039 /* Find out what engine we should switch to. If the current engine has
2040 * the same hotkey, then we should switch to the next engine with the
2041 * same hotkey in the list. Otherwise, we just switch to the first
2042 * engine in the list. */
2043 GList *p = engine_list;
2044 for (; p->next != NULL; p = p->next) {
2045 if (current_engine_desc == (IBusEngineDesc *) p->data) {
2046 new_engine_desc = (IBusEngineDesc *) p->next->data;
2051 if (current_engine_desc != new_engine_desc) {
2052 bus_ibus_impl_set_context_engine_from_desc (ibus, context, new_engine_desc);
2062 * bus_ibus_impl_load_global_engine_name_from_config:
2064 * Retrieve the "global_engine" config from the config daemon. Return NULL if the daemon is not ready.
2067 bus_ibus_impl_load_global_engine_name_from_config (BusIBusImpl *ibus)
2069 g_assert (BUS_IS_IBUS_IMPL (ibus));
2070 if (ibus->config == NULL) {
2071 /* the config component is not started yet. */
2074 g_assert (IBUS_IS_CONFIG (ibus->config));
2076 GVariant *variant = ibus_config_get_value (ibus->config, "general", "global_engine");
2077 gchar *engine_name = NULL;
2078 if (variant != NULL) {
2079 g_variant_get (variant, "s", &engine_name);
2080 g_variant_unref (variant);
2086 * bus_ibus_impl_save_global_engine_name_to_config:
2088 * Save the "global_engine" config value on the config daemon. No-op if the daemon is not ready.
2091 bus_ibus_impl_save_global_engine_name_to_config (BusIBusImpl *ibus)
2093 g_assert (BUS_IS_IBUS_IMPL (ibus));
2096 ibus->use_global_engine &&
2097 ibus->global_engine_name) {
2098 ibus_config_set_value (ibus->config,
2099 "general", "global_engine",
2100 g_variant_new ("s", ibus->global_engine_name));
2105 * bus_ibus_impl_load_global_previous_engine_name_from_config:
2107 * Retrieve the "global_previous_engine" config from the config daemon. Return NULL if the daemon is not ready.
2110 bus_ibus_impl_load_global_previous_engine_name_from_config (BusIBusImpl *ibus)
2112 g_assert (BUS_IS_IBUS_IMPL (ibus));
2113 if (ibus->config == NULL) {
2114 /* the config component is not started yet. */
2117 g_assert (IBUS_IS_CONFIG (ibus->config));
2119 GVariant *value = ibus_config_get_value (ibus->config, "general", "global_previous_engine");
2122 gchar *engine_name = NULL;
2123 g_variant_get (value, "(s)", &engine_name);
2124 g_variant_unref (value);
2129 * bus_ibus_impl_save_global_previous_engine_name_to_config:
2131 * Save the "global_previous_engine" config value on the config daemon. No-op if the daemon is not ready.
2134 bus_ibus_impl_save_global_previous_engine_name_to_config (BusIBusImpl *ibus)
2136 g_assert (BUS_IS_IBUS_IMPL (ibus));
2139 ibus->use_global_engine &&
2140 ibus->global_previous_engine_name) {
2141 ibus_config_set_value (ibus->config,
2142 "general", "global_previous_engine",
2143 g_variant_new ("s", ibus->global_previous_engine_name));
2148 * _add_engine_hotkey:
2150 * Check the engine-specific hot key of the engine, and update ibus->engines_hotkey_profile.
2153 _add_engine_hotkey (IBusEngineDesc *engine, BusIBusImpl *ibus)
2155 const gchar *hotkeys;
2156 gchar **hotkey_list;
2169 hotkeys = ibus_engine_desc_get_hotkeys (engine);
2171 if (!hotkeys || !*hotkeys) {
2175 hotkey_list = g_strsplit_set (hotkeys, ";,", 0);
2177 for (p = hotkey_list; p && *p; ++p) {
2178 hotkey = g_strstrip (*p);
2179 if (!*hotkey || !ibus_key_event_from_string (hotkey, &keyval, &modifiers)) {
2183 /* If the hotkey already exists, we won't need to add it again. */
2184 event = ibus_hotkey_profile_lookup_hotkey (ibus->engines_hotkey_profile,
2187 event = g_quark_from_string (hotkey);
2188 ibus_hotkey_profile_add_hotkey (ibus->engines_hotkey_profile,
2189 keyval, modifiers, event);
2192 engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
2193 GUINT_TO_POINTER (event));
2195 /* As we will rebuild the engines hotkey map whenever an engine was
2196 * added or removed, we don't need to hold a reference of the engine
2198 engine_list = g_list_append (engine_list, engine);
2200 /* We need to steal the value before adding it back, otherwise it will
2202 g_hash_table_steal (ibus->hotkey_to_engines_map, GUINT_TO_POINTER (event));
2204 g_hash_table_insert (ibus->hotkey_to_engines_map,
2205 GUINT_TO_POINTER (event), engine_list);
2208 g_strfreev (hotkey_list);
2212 * bus_ibus_impl_update_engines_hotkey_profile:
2214 * Check engine-specific hot keys of all active engines, and update ibus->engines_hotkey_profile.
2217 bus_ibus_impl_update_engines_hotkey_profile (BusIBusImpl *ibus)
2219 if (ibus->engines_hotkey_profile) {
2220 g_object_unref (ibus->engines_hotkey_profile);
2223 if (ibus->hotkey_to_engines_map) {
2224 g_hash_table_unref (ibus->hotkey_to_engines_map);
2227 ibus->engines_hotkey_profile = ibus_hotkey_profile_new ();
2228 ibus->hotkey_to_engines_map =
2229 g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_list_free);
2231 g_list_foreach (ibus->register_engine_list, (GFunc) _add_engine_hotkey, ibus);
2232 g_list_foreach (ibus->engine_list, (GFunc) _add_engine_hotkey, ibus);
2236 bus_ibus_impl_is_use_sys_layout (BusIBusImpl *ibus)
2238 g_assert (BUS_IS_IBUS_IMPL (ibus));
2240 return ibus->use_sys_layout;
2244 bus_ibus_impl_is_embed_preedit_text (BusIBusImpl *ibus)
2246 g_assert (BUS_IS_IBUS_IMPL (ibus));
2248 return ibus->embed_preedit_text;
2252 bus_ibus_impl_get_focused_input_context (BusIBusImpl *ibus)
2254 g_assert (BUS_IS_IBUS_IMPL (ibus));
2256 return ibus->focused_context;