1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 /* vim:set et sts=4: */
3 /* ibus - The Input Bus
4 * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
5 * Copyright (C) 2008-2010 Red Hat, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
24 #include <sys/types.h>
35 #include "connection.h"
37 #include "factoryproxy.h"
38 #include "panelproxy.h"
39 #include "inputcontext.h"
44 /* instance members */
45 GHashTable *factory_dict;
47 /* registered components */
48 GList *registered_components;
51 /* a fake input context for global engine support */
52 BusInputContext *fake_context;
54 /* a list of engines that are preloaded. */
56 /* a list of engines that are started by a user (without the --ibus command line flag.) */
57 GList *register_engine_list;
59 /* if TRUE, ibus-daemon uses a keysym translated by the system (i.e. XKB) as-is.
60 * otherwise, ibus-daemon itself converts keycode into keysym. */
61 gboolean use_sys_layout;
63 gboolean embed_preedit_text;
64 gboolean enable_by_default;
66 BusRegistry *registry;
68 BusInputContext *focused_context;
72 /* global hotkeys such as "trigger" and "next_engine_in_menu" */
73 IBusHotkeyProfile *hotkey_profile;
74 /* a default keymap of ibus-daemon (usually "us") which is used only when use_sys_layout is FALSE. */
77 gboolean use_global_engine;
78 gchar *global_engine_name;
79 gchar *global_previous_engine_name;
81 /* engine-specific hotkeys */
82 IBusHotkeyProfile *engines_hotkey_profile;
83 GHashTable *hotkey_to_engines_map;
86 struct _BusIBusImplClass {
87 IBusServiceClass parent;
101 static guint _signals[LAST_SIGNAL] = { 0 };
104 /* functions prototype */
105 static void bus_ibus_impl_destroy (BusIBusImpl *ibus);
106 static void bus_ibus_impl_service_method_call
107 (IBusService *service,
108 GDBusConnection *connection,
110 const gchar *object_path,
111 const gchar *interface_name,
112 const gchar *method_name,
113 GVariant *parameters,
114 GDBusMethodInvocation
116 /* TODO use property to replace some getter and setter in future */
118 static GVariant *ibus_ibus_impl_service_get_property
119 (IBusService *service,
120 GDBusConnection *connection,
122 const gchar *object_path,
123 const gchar *interface_name,
124 const gchar *property_name,
126 static gboolean ibus_ibus_impl_service_set_property
127 (IBusService *service,
128 GDBusConnection *connection,
130 const gchar *object_path,
131 const gchar *interface_name,
132 const gchar *property_name,
136 static void bus_ibus_impl_set_trigger (BusIBusImpl *ibus,
138 static void bus_ibus_impl_set_next_engine_in_menu
141 static void bus_ibus_impl_set_previous_engine
144 static void bus_ibus_impl_set_preload_engines
147 static void bus_ibus_impl_set_use_sys_layout
150 static void bus_ibus_impl_set_embed_preedit_text
153 static void bus_ibus_impl_set_enable_by_default
156 static void bus_ibus_impl_set_use_global_engine
159 static void bus_ibus_impl_registry_changed (BusIBusImpl *ibus);
160 static void bus_ibus_impl_global_engine_changed
162 static void bus_ibus_impl_set_context_engine_from_desc
164 BusInputContext *context,
165 IBusEngineDesc *desc);
166 static gchar *bus_ibus_impl_load_global_engine_name_from_config
168 static void bus_ibus_impl_save_global_engine_name_to_config
171 static gchar *bus_ibus_impl_load_global_previous_engine_name_from_config
173 static void bus_ibus_impl_save_global_previous_engine_name_to_config
175 static void bus_ibus_impl_update_engines_hotkey_profile
177 static BusInputContext
178 *bus_ibus_impl_create_input_context
180 BusConnection *connection,
181 const gchar *client);
182 /* some callback functions */
183 static void _context_engine_changed_cb (BusInputContext *context,
186 /* The interfaces available in this class, which consists of a list of methods this class implements and
187 * a list of signals this class may emit. Method calls to the interface that are not defined in this XML
188 * will be automatically rejected by the GDBus library (see src/ibusservice.c for details.) */
189 static const gchar introspection_xml[] =
191 " <interface name='org.freedesktop.IBus'>\n"
192 " <method name='GetAddress'>\n"
193 " <arg direction='out' type='s' name='address' />\n"
195 " <method name='CreateInputContext'>\n"
196 " <arg direction='in' type='s' name='client_name' />\n"
197 " <arg direction='out' type='o' name='object_path' />\n"
199 " <method name='CurrentInputContext'>\n"
200 " <arg direction='out' type='o' name='object_path' />\n"
202 " <method name='RegisterComponent'>\n"
203 " <arg direction='in' type='v' name='component' />\n"
205 " <method name='ListEngines'>\n"
206 " <arg direction='out' type='av' name='engines' />\n"
208 " <method name='ListActiveEngines'>\n"
209 " <arg direction='out' type='av' name='engines' />\n"
211 " <method name='Exit'>\n"
212 " <arg direction='in' type='b' name='restart' />\n"
214 " <method name='Ping'>\n"
215 " <arg direction='in' type='v' name='data' />\n"
216 " <arg direction='out' type='v' name='data' />\n"
218 " <method name='GetUseSysLayout'>\n"
219 " <arg direction='out' type='b' name='enabled' />\n"
221 " <method name='GetUseGlobalEngine'>\n"
222 " <arg direction='out' type='b' name='enabled' />\n"
224 " <method name='GetGlobalEngine'>\n"
225 " <arg direction='out' type='v' name='desc' />\n"
227 " <method name='SetGlobalEngine'>\n"
228 " <arg direction='in' type='s' name='engine_name' />\n"
230 " <method name='IsGlobalEngineEnabled'>\n"
231 " <arg direction='out' type='b' name='enabled' />\n"
233 " <signal name='RegistryChanged'>\n"
235 " <signal name='GlobalEngineChanged'>\n"
241 G_DEFINE_TYPE (BusIBusImpl, bus_ibus_impl, IBUS_TYPE_SERVICE)
244 bus_ibus_impl_class_init (BusIBusImplClass *class)
246 IBUS_OBJECT_CLASS (class)->destroy = (IBusObjectDestroyFunc) bus_ibus_impl_destroy;
248 /* override the parent class's implementation. */
249 IBUS_SERVICE_CLASS (class)->service_method_call = bus_ibus_impl_service_method_call;
250 /* register the xml so that bus_ibus_impl_service_method_call will be called on a method call defined in the xml (e.g. 'GetAddress'.) */
251 ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml);
257 * A callback function which is called when (1) the connection to the panel process is terminated,
258 * or (2) ibus_proxy_destroy (ibus->panel); is called. See src/ibusproxy.c for details.
261 _panel_destroy_cb (BusPanelProxy *panel,
264 g_assert (BUS_IS_PANEL_PROXY (panel));
265 g_assert (BUS_IS_IBUS_IMPL (ibus));
267 g_return_if_fail (ibus->panel == panel);
270 g_object_unref (panel);
274 bus_ibus_impl_set_hotkey (BusIBusImpl *ibus,
278 g_assert (BUS_IS_IBUS_IMPL (ibus));
280 ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
287 g_variant_iter_init (&iter, value);
288 const gchar *str = NULL;
289 while (g_variant_iter_loop (&iter,"&s", &str)) {
290 ibus_hotkey_profile_add_hotkey_from_string (ibus->hotkey_profile,
298 * bus_ibus_impl_set_trigger:
300 * A function to be called when "trigger" config is updated. If the value is NULL, the default trigger (Ctrl+space) is set.
303 bus_ibus_impl_set_trigger (BusIBusImpl *ibus,
306 GQuark hotkey = g_quark_from_static_string ("trigger");
308 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
312 /* set default trigger */
313 ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
314 ibus_hotkey_profile_add_hotkey (ibus->hotkey_profile,
323 * bus_ibus_impl_set_next_engine_in_menu:
325 * A function to be called when "next_engine_in_menu" config is updated.
328 bus_ibus_impl_set_next_engine_in_menu (BusIBusImpl *ibus,
331 GQuark hotkey = g_quark_from_static_string ("next-engine-in-menu");
332 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
336 * bus_ibus_impl_set_previous_engine:
338 * A function to be called when "previous_engine" config is updated.
341 bus_ibus_impl_set_previous_engine (BusIBusImpl *ibus,
344 GQuark hotkey = g_quark_from_static_string ("previous-engine");
345 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
349 * bus_ibus_impl_set_preload_engines:
351 * A function to be called when "preload_engines" config is updated.
354 bus_ibus_impl_set_preload_engines (BusIBusImpl *ibus,
357 GList *engine_list = NULL;
359 g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
360 g_list_free (ibus->engine_list);
362 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_ARRAY) {
364 g_variant_iter_init (&iter, value);
365 const gchar *engine_name = NULL;
366 while (g_variant_iter_loop (&iter, "&s", &engine_name)) {
367 IBusEngineDesc *engine = bus_registry_find_engine_by_name (ibus->registry, engine_name);
368 if (engine == NULL || g_list_find (engine_list, engine) != NULL)
370 engine_list = g_list_append (engine_list, engine);
374 g_list_foreach (engine_list, (GFunc) g_object_ref, NULL);
375 ibus->engine_list = engine_list;
377 if (ibus->engine_list) {
378 BusComponent *component = bus_component_from_engine_desc ((IBusEngineDesc *) ibus->engine_list->data);
379 if (component && !bus_component_is_running (component)) {
380 bus_component_start (component, g_verbose);
384 bus_ibus_impl_update_engines_hotkey_profile (ibus);
388 * bus_ibus_impl_set_use_sys_layout:
390 * A function to be called when "use_system_keyboard_layout" config is updated.
393 bus_ibus_impl_set_use_sys_layout (BusIBusImpl *ibus,
396 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
397 ibus->use_sys_layout = g_variant_get_boolean (value);
402 * bus_ibus_impl_set_embed_preedit_text:
404 * A function to be called when "use_embed_preedit_text" config is updated.
407 bus_ibus_impl_set_embed_preedit_text (BusIBusImpl *ibus,
410 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
411 ibus->embed_preedit_text = g_variant_get_boolean (value);
416 * bus_ibus_impl_set_enable_by_default:
418 * A function to be called when "enable_by_default" config is updated.
421 bus_ibus_impl_set_enable_by_default (BusIBusImpl *ibus,
424 if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
425 ibus->enable_by_default = g_variant_get_boolean (value);
430 * bus_ibus_impl_set_use_global_engine:
432 * A function to be called when "use_global_engine" config is updated.
435 bus_ibus_impl_set_use_global_engine (BusIBusImpl *ibus,
438 if (value == NULL || g_variant_classify (value) != G_VARIANT_CLASS_BOOLEAN)
441 gboolean new_value = g_variant_get_boolean (value);
442 if (ibus->use_global_engine == new_value)
446 /* turn on use_global_engine option */
447 ibus->use_global_engine = TRUE;
450 /* turn off use_global_engine option */
451 ibus->use_global_engine = FALSE;
453 /* if fake context has the focus, we should focus out it */
454 if (ibus->panel && ibus->focused_context == NULL) {
455 bus_panel_proxy_focus_out (ibus->panel, ibus->fake_context);
457 /* remove engine in fake context */
458 bus_input_context_set_engine (ibus->fake_context, NULL);
463 _engine_desc_cmp (IBusEngineDesc *desc1,
464 IBusEngineDesc *desc2)
466 return - ((gint) ibus_engine_desc_get_rank (desc1)) +
467 ((gint) ibus_engine_desc_get_rank (desc2));
471 * bus_ibus_impl_set_default_preload_engines:
473 * If the "preload_engines" config variable is not set yet, set the default value which is determined based on a current locale (LC_ALL).
476 bus_ibus_impl_set_default_preload_engines (BusIBusImpl *ibus)
478 g_assert (BUS_IS_IBUS_IMPL (ibus));
480 static gboolean done = FALSE;
482 if (done || ibus->config == NULL) {
486 GVariant *variant = ibus_config_get_value (ibus->config, "general", "preload_engines");
487 if (variant != NULL) {
489 g_variant_unref (variant);
494 gchar *lang = g_strdup (setlocale (LC_ALL, NULL));
495 gchar *p = index (lang, '.');
500 GList *engines = bus_registry_get_engines_by_language (ibus->registry, lang);
501 if (engines == NULL) {
502 p = index (lang, '_');
505 engines = bus_registry_get_engines_by_language (ibus->registry, lang);
510 /* sort engines by rank */
511 engines = g_list_sort (engines, (GCompareFunc) _engine_desc_cmp);
513 GVariantBuilder builder;
514 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
516 for (list = engines; list != NULL; list = list->next) {
517 IBusEngineDesc *desc = (IBusEngineDesc *) list->data;
518 /* ignore engines with rank <= 0 */
519 if (ibus_engine_desc_get_rank (desc) > 0)
520 g_variant_builder_add (&builder, "s", ibus_engine_desc_get_name (desc));
523 GVariant *value = g_variant_builder_end (&builder);
525 if (g_variant_n_children (value) > 0) {
526 ibus_config_set_value (ibus->config,
527 "general", "preload_engines", value);
529 /* We don't update preload_engines with an empty string for safety.
530 * Just unref the floating value. */
531 g_variant_unref (value);
534 g_list_free (engines);
537 /* The list of config entries that are related to ibus-daemon. */
538 const static struct {
541 void (*func) (BusIBusImpl *, GVariant *);
542 } bus_ibus_impl_config_items [] = {
543 { "general/hotkey", "trigger", bus_ibus_impl_set_trigger },
544 { "general/hotkey", "next_engine_in_menu", bus_ibus_impl_set_next_engine_in_menu },
545 { "general/hotkey", "previous_engine", bus_ibus_impl_set_previous_engine },
546 { "general", "preload_engines", bus_ibus_impl_set_preload_engines },
547 { "general", "use_system_keyboard_layout", bus_ibus_impl_set_use_sys_layout },
548 { "general", "use_global_engine", bus_ibus_impl_set_use_global_engine },
549 { "general", "embed_preedit_text", bus_ibus_impl_set_embed_preedit_text },
550 { "general", "enable_by_default", bus_ibus_impl_set_enable_by_default },
554 * bus_ibus_impl_reload_config
556 * Read config entries (e.g. preload_engines) from the config daemon.
559 bus_ibus_impl_reload_config (BusIBusImpl *ibus)
561 g_assert (BUS_IS_IBUS_IMPL (ibus));
564 for (i = 0; i < G_N_ELEMENTS (bus_ibus_impl_config_items); i++) {
565 GVariant *variant = NULL;
566 if (ibus->config != NULL)
567 variant = ibus_config_get_value (ibus->config,
568 bus_ibus_impl_config_items[i].section,
569 bus_ibus_impl_config_items[i].key);
570 bus_ibus_impl_config_items[i].func (ibus, variant); /* variant could be NULL if the deamon is not ready yet. */
571 if (variant) g_variant_unref (variant);
576 * _config_value_changed_cb:
578 * A callback function to be called when the "ValueChanged" D-Bus signal is sent from the config daemon.
581 _config_value_changed_cb (IBusConfig *config,
587 g_assert (IBUS_IS_CONFIG (config));
591 g_assert (BUS_IS_IBUS_IMPL (ibus));
594 for (i = 0; i < G_N_ELEMENTS (bus_ibus_impl_config_items); i++) {
595 if (g_strcmp0 (bus_ibus_impl_config_items[i].section, section) == 0 &&
596 g_strcmp0 (bus_ibus_impl_config_items[i].key, key) == 0) {
597 bus_ibus_impl_config_items[i].func (ibus, value);
604 * _config_destroy_cb:
606 * A callback function which is called when (1) the connection to the config process is terminated,
607 * or (2) ibus_proxy_destroy (ibus->config); is called. See src/ibusproxy.c for details.
610 _config_destroy_cb (IBusConfig *config,
613 g_assert (IBUS_IS_CONFIG (config));
614 g_assert (BUS_IS_IBUS_IMPL (ibus));
616 g_assert (ibus->config == config);
618 g_object_unref (ibus->config);
623 _registry_changed_cb (BusRegistry *registry,
626 bus_ibus_impl_registry_changed (ibus);
630 * _dbus_name_owner_changed_cb:
632 * A callback function to be called when the name-owner-changed signal is sent to the dbus object.
633 * This usually means a client (e.g. a panel/config/engine process or an application) is connected/disconnected to/from the bus.
636 _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
638 const gchar *old_name,
639 const gchar *new_name,
642 g_assert (BUS_IS_DBUS_IMPL (dbus));
643 g_assert (name != NULL);
644 g_assert (old_name != NULL);
645 g_assert (new_name != NULL);
646 g_assert (BUS_IS_IBUS_IMPL (ibus));
648 if (g_strcmp0 (name, IBUS_SERVICE_PANEL) == 0) {
649 if (g_strcmp0 (new_name, "") != 0) {
650 /* a Panel process is started. */
651 BusConnection *connection;
653 if (ibus->panel != NULL) {
654 ibus_proxy_destroy ((IBusProxy *) ibus->panel);
655 /* panel should be NULL after destroy. See _panel_destroy_cb for details. */
656 g_assert (ibus->panel == NULL);
659 connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
660 g_return_if_fail (connection != NULL);
662 ibus->panel = bus_panel_proxy_new (connection);
664 g_signal_connect (ibus->panel,
666 G_CALLBACK (_panel_destroy_cb),
669 if (ibus->focused_context != NULL) {
670 bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context);
674 else if (g_strcmp0 (name, IBUS_SERVICE_CONFIG) == 0) {
675 if (g_strcmp0 (new_name, "") != 0) {
676 /* a config process is started. */
677 BusConnection *connection;
679 if (ibus->config != NULL) {
680 ibus_proxy_destroy ((IBusProxy *) ibus->config);
681 /* config should be NULL after destroy. See _config_destroy_cb for details. */
682 g_assert (ibus->config == NULL);
685 /* get a connection between ibus-daemon and the config daemon. */
686 connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
687 g_return_if_fail (connection != NULL);
689 ibus->config = g_initable_new (IBUS_TYPE_CONFIG,
692 /* The following properties are necessary to initialize GDBusProxy object
693 * which is a parent of the config object. */
694 "g-connection", bus_connection_get_dbus_connection (connection),
695 "g-flags", G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
696 "g-interface-name", IBUS_INTERFACE_CONFIG,
697 "g-object-path", IBUS_PATH_CONFIG,
698 "g-default-timeout", g_gdbus_timeout,
701 g_signal_connect (ibus->config,
703 G_CALLBACK (_config_value_changed_cb),
706 g_signal_connect (ibus->config,
708 G_CALLBACK (_config_destroy_cb),
711 bus_ibus_impl_set_default_preload_engines (ibus);
712 bus_ibus_impl_reload_config (ibus);
716 bus_registry_name_owner_changed (ibus->registry, name, old_name, new_name);
720 * bus_ibus_impl_init:
722 * The constructor of BusIBusImpl. Initialize all member variables of a BusIBusImpl object.
725 bus_ibus_impl_init (BusIBusImpl *ibus)
727 ibus->factory_dict = g_hash_table_new_full (
731 (GDestroyNotify) g_object_unref);
733 ibus->fake_context = bus_input_context_new (NULL, "fake");
734 g_object_ref_sink (ibus->fake_context);
735 bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
736 (IBusService *) ibus->fake_context);
737 bus_input_context_set_capabilities (ibus->fake_context,
738 IBUS_CAP_PREEDIT_TEXT |
740 IBUS_CAP_SURROUNDING_TEXT);
741 g_signal_connect (ibus->fake_context,
743 G_CALLBACK (_context_engine_changed_cb),
745 bus_input_context_focus_in (ibus->fake_context);
747 ibus->engine_list = NULL;
748 ibus->register_engine_list = NULL;
749 ibus->contexts = NULL;
750 ibus->focused_context = NULL;
754 ibus->registry = bus_registry_new ();
756 g_signal_connect (ibus->registry,
758 G_CALLBACK (_registry_changed_cb),
760 #ifdef G_THREADS_ENABLED
761 extern gint g_monitor_timeout;
762 if (g_monitor_timeout != 0) {
763 /* Start the monitor of registry changes. */
764 bus_registry_start_monitor_changes (ibus->registry);
768 ibus->hotkey_profile = ibus_hotkey_profile_new ();
769 ibus->keymap = ibus_keymap_get ("us");
771 ibus->use_sys_layout = FALSE;
772 ibus->embed_preedit_text = TRUE;
773 ibus->enable_by_default = FALSE;
774 ibus->use_global_engine = FALSE;
775 ibus->global_engine_name = NULL;
776 ibus->global_previous_engine_name = NULL;
778 ibus->engines_hotkey_profile = NULL;
779 ibus->hotkey_to_engines_map = NULL;
781 bus_ibus_impl_reload_config (ibus);
783 g_signal_connect (BUS_DEFAULT_DBUS,
784 "name-owner-changed",
785 G_CALLBACK (_dbus_name_owner_changed_cb),
790 * bus_ibus_impl_destroy:
792 * The destructor of BusIBusImpl.
795 bus_ibus_impl_destroy (BusIBusImpl *ibus)
802 bus_registry_stop_all_components (ibus->registry);
808 while ((pid = waitpid (0, &status, WNOHANG)) > 0);
810 if (pid == -1) { /* all children finished */
813 if (pid == 0) { /* no child status changed */
816 if (timeout >= G_USEC_PER_SEC) {
819 old = signal (SIGTERM, SIG_IGN);
820 /* send TERM signal to the whole process group (i.e. engines, panel, and config daemon.) */
821 kill (-getpid (), SIGTERM);
822 signal (SIGTERM, old);
826 g_warning ("Not every child processes exited!");
833 g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
834 g_list_free (ibus->engine_list);
835 ibus->engine_list = NULL;
837 g_list_foreach (ibus->register_engine_list, (GFunc) g_object_unref, NULL);
838 g_list_free (ibus->register_engine_list);
839 ibus->register_engine_list = NULL;
841 if (ibus->factory_dict != NULL) {
842 g_hash_table_destroy (ibus->factory_dict);
843 ibus->factory_dict = NULL;
846 if (ibus->hotkey_profile != NULL) {
847 g_object_unref (ibus->hotkey_profile);
848 ibus->hotkey_profile = NULL;
851 if (ibus->keymap != NULL) {
852 g_object_unref (ibus->keymap);
856 g_free (ibus->global_engine_name);
857 ibus->global_engine_name = NULL;
859 g_free (ibus->global_previous_engine_name);
860 ibus->global_previous_engine_name = NULL;
862 if (ibus->engines_hotkey_profile != NULL) {
863 g_object_unref (ibus->engines_hotkey_profile);
864 ibus->engines_hotkey_profile = NULL;
867 if (ibus->hotkey_to_engines_map) {
868 g_hash_table_unref (ibus->hotkey_to_engines_map);
869 ibus->hotkey_to_engines_map = NULL;
872 if (ibus->fake_context) {
873 g_object_unref (ibus->fake_context);
874 ibus->fake_context = NULL;
878 IBUS_OBJECT_CLASS (bus_ibus_impl_parent_class)->destroy (IBUS_OBJECT (ibus));
884 * Implement the "GetAddress" method call of the org.freedesktop.IBus interface.
887 _ibus_get_address (BusIBusImpl *ibus,
888 GVariant *parameters,
889 GDBusMethodInvocation *invocation)
891 g_dbus_method_invocation_return_value (invocation,
892 g_variant_new ("(s)", bus_server_get_address ()));
895 static IBusEngineDesc *
896 _find_engine_desc_by_name (BusIBusImpl *ibus,
897 const gchar *engine_name)
899 IBusEngineDesc *desc = NULL;
902 /* find engine in registered engine list */
903 for (p = ibus->register_engine_list; p != NULL; p = p->next) {
904 desc = (IBusEngineDesc *) p->data;
905 if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
909 /* find engine in preload engine list */
910 for (p = ibus->engine_list; p != NULL; p = p->next) {
911 desc = (IBusEngineDesc *) p->data;
912 if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
920 * _context_request_engine_cb:
922 * A callback function to be called when the "request-engine" signal is sent to the context.
925 _context_request_engine_cb (BusInputContext *context,
926 const gchar *engine_name,
929 IBusEngineDesc *desc = NULL;
931 /* context should has focus before request an engine */
932 g_return_if_fail (bus_input_context_has_focus (context) ||
933 context == ibus->focused_context);
935 if (engine_name != NULL && engine_name[0] != '\0') {
936 /* request engine by name */
937 desc = _find_engine_desc_by_name (ibus, engine_name);
938 g_return_if_fail (desc != NULL);
941 /* Use global engine if possible. */
942 if (ibus->use_global_engine) {
943 gchar *name = g_strdup (ibus->global_engine_name);
945 name = bus_ibus_impl_load_global_engine_name_from_config (ibus);
948 desc = _find_engine_desc_by_name (ibus, name);
952 /* request default engine */
954 if (ibus->register_engine_list) {
955 desc = (IBusEngineDesc *) ibus->register_engine_list->data;
957 else if (ibus->engine_list) {
958 desc = (IBusEngineDesc *) ibus->engine_list->data;
962 /* no engine is available. the user hasn't ran ibus-setup yet and
963 * the bus_ibus_impl_set_default_preload_engines() function could
964 * not find any default engines. another possiblity is that the
965 * user hasn't installed an engine yet? just give up. */
966 g_warning ("No engine is available. Run ibus-setup first.");
971 bus_ibus_impl_set_context_engine_from_desc (ibus, context, desc);
975 * bus_ibus_impl_context_request_next_engine_in_menu:
977 * Process the "next_engine_in_menu" hotkey.
980 bus_ibus_impl_context_request_next_engine_in_menu (BusIBusImpl *ibus,
981 BusInputContext *context)
983 BusEngineProxy *engine;
984 IBusEngineDesc *desc;
985 IBusEngineDesc *next_desc = NULL;
988 engine = bus_input_context_get_engine (context);
989 if (engine == NULL) {
990 _context_request_engine_cb (context, NULL, ibus);
994 desc = bus_engine_proxy_get_desc (engine);
996 p = g_list_find (ibus->register_engine_list, desc);
1001 p = g_list_find (ibus->engine_list, desc);
1008 next_desc = (IBusEngineDesc*) p->data;
1011 if (ibus->register_engine_list) {
1012 next_desc = (IBusEngineDesc *) ibus->register_engine_list->data;
1014 else if (ibus->engine_list) {
1015 next_desc = (IBusEngineDesc *) ibus->engine_list->data;
1019 bus_ibus_impl_set_context_engine_from_desc (ibus, context, next_desc);
1023 * bus_ibus_impl_context_request_previous_engine:
1025 * Process the "previous_engine" hotkey.
1028 bus_ibus_impl_context_request_previous_engine (BusIBusImpl *ibus,
1029 BusInputContext *context)
1031 gchar *engine_name = NULL;
1032 if (!ibus->use_global_engine) {
1033 engine_name = (gchar *) g_object_get_data (G_OBJECT (context), "previous-engine-name");
1036 if (!ibus->global_previous_engine_name) {
1037 ibus->global_previous_engine_name = bus_ibus_impl_load_global_previous_engine_name_from_config (ibus);
1039 engine_name = ibus->global_previous_engine_name;
1043 * If the previous engine name is not found, switch to the next engine
1044 * in the menu. This behavior is better than doing nothing.
1047 bus_ibus_impl_context_request_next_engine_in_menu (ibus, context);
1050 _context_request_engine_cb (context, engine_name, ibus);
1054 bus_ibus_impl_set_context_engine_from_desc (BusIBusImpl *ibus,
1055 BusInputContext *context,
1056 IBusEngineDesc *desc)
1058 bus_input_context_set_engine_by_desc (context,
1060 g_gdbus_timeout, /* timeout in msec. */
1061 NULL, /* we do not cancel the call. */
1062 NULL, /* use the default callback function. */
1067 * bus_ibus_impl_set_focused_context:
1069 * Set the current focused context.
1072 bus_ibus_impl_set_focused_context (BusIBusImpl *ibus,
1073 BusInputContext *context)
1075 g_assert (BUS_IS_IBUS_IMPL (ibus));
1076 g_assert (context == NULL || BUS_IS_INPUT_CONTEXT (context));
1077 g_assert (context == NULL || bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS);
1079 /* Do noting if it is not focused context. */
1080 if (ibus->focused_context == context) {
1084 BusEngineProxy *engine = NULL;
1086 if (ibus->focused_context) {
1087 if (ibus->use_global_engine) {
1088 /* dettach engine from the focused context */
1089 engine = bus_input_context_get_engine (ibus->focused_context);
1091 g_object_ref (engine);
1092 bus_input_context_set_engine (ibus->focused_context, NULL);
1096 if (ibus->panel != NULL)
1097 bus_panel_proxy_focus_out (ibus->panel, ibus->focused_context);
1099 g_object_unref (ibus->focused_context);
1100 ibus->focused_context = NULL;
1103 if (context == NULL && ibus->use_global_engine) {
1104 context = ibus->fake_context;
1108 ibus->focused_context = (BusInputContext *) g_object_ref (context);
1109 /* attach engine to the focused context */
1110 if (engine != NULL) {
1111 bus_input_context_set_engine (context, engine);
1112 if (bus_engine_proxy_is_enabled (engine))
1113 bus_input_context_enable (context);
1114 g_object_unref (engine);
1117 if (ibus->panel != NULL)
1118 bus_panel_proxy_focus_in (ibus->panel, context);
1124 * _context_engine_changed_cb:
1126 * A callback function to be called when the "engine-changed" signal is sent to the context.
1127 * Update global engine as well if necessary.
1130 _context_engine_changed_cb (BusInputContext *context,
1133 if (!ibus->use_global_engine)
1136 if ((context == ibus->focused_context) ||
1137 (ibus->focused_context == NULL && context == ibus->fake_context)) {
1138 BusEngineProxy *engine = bus_input_context_get_engine (context);
1139 if (engine != NULL) {
1140 /* only set global engine if engine is not NULL */
1141 const gchar *name = ibus_engine_desc_get_name (bus_engine_proxy_get_desc (engine));
1142 if (g_strcmp0 (name, ibus->global_engine_name) == 0)
1144 g_free (ibus->global_previous_engine_name);
1145 ibus->global_previous_engine_name = ibus->global_engine_name;
1146 ibus->global_engine_name = g_strdup (name);
1148 bus_ibus_impl_save_global_engine_name_to_config (ibus);
1149 bus_ibus_impl_save_global_previous_engine_name_to_config (ibus);
1150 bus_ibus_impl_global_engine_changed (ibus);
1156 * _context_focus_in_cb:
1158 * A callback function to be called when the "focus-in" signal is sent to the context.
1159 * If necessary, enables the global engine on the context and update ibus->focused_context.
1162 _context_focus_in_cb (BusInputContext *context,
1165 g_assert (BUS_IS_IBUS_IMPL (ibus));
1166 g_assert (BUS_IS_INPUT_CONTEXT (context));
1168 /* Do nothing if context does not support focus.
1169 * The global engine shoule be detached from the focused context. */
1170 if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
1174 bus_ibus_impl_set_focused_context (ibus, context);
1178 * _context_focus_out_cb:
1180 * A callback function to be called when the "focus-out" signal is sent to the context.
1183 _context_focus_out_cb (BusInputContext *context,
1186 g_assert (BUS_IS_IBUS_IMPL (ibus));
1187 g_assert (BUS_IS_INPUT_CONTEXT (context));
1189 /* Do noting if context does not support focus.
1190 * Actually, the context should emit focus signals, if it does not support focus */
1191 if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
1195 /* Do noting if it is not focused context. */
1196 if (ibus->focused_context != context) {
1201 if (ibus->use_global_engine == FALSE) {
1202 /* Do not change the focused context, if use_global_engine option is enabled.
1203 * If focused context swith to NULL, users can not swith engine in panel anymore.
1205 bus_ibus_impl_set_focused_context (ibus, NULL);
1210 * _context_destroy_cb:
1212 * A callback function to be called when the "destroy" signal is sent to the context.
1215 _context_destroy_cb (BusInputContext *context,
1218 g_assert (BUS_IS_IBUS_IMPL (ibus));
1219 g_assert (BUS_IS_INPUT_CONTEXT (context));
1221 if (context == ibus->focused_context) {
1222 bus_ibus_impl_set_focused_context (ibus, NULL);
1225 ibus->contexts = g_list_remove (ibus->contexts, context);
1226 g_object_unref (context);
1230 * _context_enabled_cb:
1232 * A callback function to be called when the "enabled" signal is sent to the context.
1235 _context_enabled_cb (BusInputContext *context,
1238 /* FIXME implement this. */
1242 * _context_disabled_cb:
1244 * A callback function to be called when the "disabled" signal is sent to the context.
1247 _context_disabled_cb (BusInputContext *context,
1250 /* FIXME implement this. */
1254 * bus_ibus_impl_create_input_context:
1255 * @client: A name of a client. e.g. "gtk-im"
1256 * @returns: A BusInputContext object.
1258 * Create a new BusInputContext object for the client.
1260 static BusInputContext *
1261 bus_ibus_impl_create_input_context (BusIBusImpl *ibus,
1262 BusConnection *connection,
1263 const gchar *client)
1265 BusInputContext *context = bus_input_context_new (connection, client);
1266 g_object_ref_sink (context);
1267 ibus->contexts = g_list_append (ibus->contexts, context);
1269 /* Installs glib signal handlers so that the ibus object could be notified when e.g. an IBus.InputContext D-Bus method is called. */
1270 static const struct {
1274 { "request-engine", G_CALLBACK (_context_request_engine_cb) },
1275 { "engine-changed", G_CALLBACK (_context_engine_changed_cb) },
1276 { "focus-in", G_CALLBACK (_context_focus_in_cb) },
1277 { "focus-out", G_CALLBACK (_context_focus_out_cb) },
1278 { "destroy", G_CALLBACK (_context_destroy_cb) },
1279 { "enabled", G_CALLBACK (_context_enabled_cb) },
1280 { "disabled", G_CALLBACK (_context_disabled_cb) },
1284 for (i = 0; i < G_N_ELEMENTS (signals); i++) {
1285 g_signal_connect (context,
1287 signals[i].callback,
1291 if (ibus->enable_by_default) {
1292 bus_input_context_enable (context);
1295 /* register the context object so that the object could handle IBus.InputContext method calls. */
1296 bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
1297 (IBusService *) context);
1298 g_object_ref (context);
1303 * _ibus_create_input_context:
1305 * Implement the "CreateInputContext" method call of the org.freedesktop.IBus interface.
1308 _ibus_create_input_context (BusIBusImpl *ibus,
1309 GVariant *parameters,
1310 GDBusMethodInvocation *invocation)
1312 const gchar *client_name = NULL; // e.g. "gtk-im"
1313 g_variant_get (parameters, "(&s)", &client_name);
1315 BusConnection *connection =
1316 bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
1317 BusInputContext *context =
1318 bus_ibus_impl_create_input_context (ibus,
1322 const gchar *path = ibus_service_get_object_path ((IBusService *) context);
1323 /* the format-string 'o' is for a D-Bus object path. */
1324 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
1325 g_object_unref (context);
1328 g_dbus_method_invocation_return_error (invocation,
1330 G_DBUS_ERROR_FAILED,
1331 "Create input context failed!");
1336 * _ibus_current_input_context:
1338 * Implement the "CurrentInputContext" method call of the org.freedesktop.IBus interface.
1341 _ibus_current_input_context (BusIBusImpl *ibus,
1342 GVariant *parameters,
1343 GDBusMethodInvocation *invocation)
1345 if (!ibus->focused_context)
1347 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1348 "No focused input context");
1351 const gchar *path = ibus_service_get_object_path ((IBusService *) ibus->focused_context);
1352 /* the format-string 'o' is for a D-Bus object path. */
1353 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
1358 _component_destroy_cb (BusComponent *component,
1361 g_assert (BUS_IS_IBUS_IMPL (ibus));
1362 g_assert (BUS_IS_COMPONENT (component));
1364 ibus->registered_components = g_list_remove (ibus->registered_components, component);
1366 /* remove engines from engine_list */
1367 GList *engines = bus_component_get_engines (component);
1369 for (p = engines; p != NULL; p = p->next) {
1370 if (g_list_find (ibus->register_engine_list, p->data)) {
1371 ibus->register_engine_list = g_list_remove (ibus->register_engine_list, p->data);
1372 g_object_unref (p->data);
1375 g_list_free (engines);
1377 g_object_unref (component);
1379 bus_ibus_impl_update_engines_hotkey_profile (ibus);
1383 * _ibus_register_component:
1385 * Implement the "RegisterComponent" method call of the org.freedesktop.IBus interface.
1388 _ibus_register_component (BusIBusImpl *ibus,
1389 GVariant *parameters,
1390 GDBusMethodInvocation *invocation)
1392 GVariant *variant = g_variant_get_child_value (parameters, 0);
1393 IBusComponent *component = (IBusComponent *) ibus_serializable_deserialize (variant);
1395 if (!IBUS_IS_COMPONENT (component)) {
1397 g_object_unref (component);
1398 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1399 "The first argument should be an IBusComponent.");
1403 BusConnection *connection = bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
1404 BusFactoryProxy *factory = bus_factory_proxy_new (connection);
1406 if (factory == NULL) {
1407 g_object_unref (component);
1408 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1409 "Create factory failed.");
1413 g_object_ref_sink (component);
1415 BusComponent *buscomp = bus_component_new (component, factory);
1416 bus_component_set_destroy_with_factory (buscomp, TRUE);
1417 g_object_unref (component);
1418 g_object_unref (factory);
1420 ibus->registered_components = g_list_append (ibus->registered_components,
1421 g_object_ref_sink (buscomp));
1422 GList *engines = bus_component_get_engines (buscomp);
1423 g_list_foreach (engines, (GFunc) g_object_ref, NULL);
1424 ibus->register_engine_list = g_list_concat (ibus->register_engine_list,
1427 g_signal_connect (buscomp, "destroy", G_CALLBACK (_component_destroy_cb), ibus);
1429 bus_ibus_impl_update_engines_hotkey_profile (ibus);
1431 g_dbus_method_invocation_return_value (invocation, NULL);
1435 * _ibus_list_engines:
1437 * Implement the "ListEngines" method call of the org.freedesktop.IBus interface.
1440 _ibus_list_engines (BusIBusImpl *ibus,
1441 GVariant *parameters,
1442 GDBusMethodInvocation *invocation)
1444 GVariantBuilder builder;
1445 g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1447 GList *engines = bus_registry_get_engines (ibus->registry);
1449 for (p = engines; p != NULL; p = p->next) {
1450 g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1452 g_list_free (engines);
1453 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1457 * _ibus_list_active_engines:
1459 * Implement the "ListActiveEngines" method call of the org.freedesktop.IBus interface.
1462 _ibus_list_active_engines (BusIBusImpl *ibus,
1463 GVariant *parameters,
1464 GDBusMethodInvocation *invocation)
1466 GVariantBuilder builder;
1467 g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1470 for (p = ibus->engine_list; p != NULL; p = p->next) {
1471 g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1473 for (p = ibus->register_engine_list; p != NULL; p = p->next) {
1474 g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1476 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1482 * Implement the "Exit" method call of the org.freedesktop.IBus interface.
1485 _ibus_exit (BusIBusImpl *ibus,
1486 GVariant *parameters,
1487 GDBusMethodInvocation *invocation)
1489 gboolean restart = FALSE;
1490 g_variant_get (parameters, "(b)", &restart);
1492 g_dbus_method_invocation_return_value (invocation, NULL);
1494 /* Make sure the reply has been sent out before exit */
1495 g_dbus_connection_flush_sync (g_dbus_method_invocation_get_connection (invocation),
1504 extern gchar **g_argv;
1508 exe = g_strdup_printf ("/proc/%d/exe", getpid ());
1509 exe = g_file_read_link (exe, NULL);
1512 exe = BINDIR "/ibus-daemon";
1514 /* close all fds except stdin, stdout, stderr */
1515 for (fd = 3; fd <= sysconf (_SC_OPEN_MAX); fd ++) {
1519 execv (exe, g_argv);
1521 /* If the server binary is replaced while the server is running,
1522 * "readlink /proc/[pid]/exe" might return a path with " (deleted)"
1524 const gchar suffix[] = " (deleted)";
1525 if (g_str_has_suffix (exe, suffix)) {
1526 exe [strlen (exe) - sizeof (suffix) + 1] = '\0';
1527 execv (exe, g_argv);
1529 g_warning ("execv %s failed!", g_argv[0]);
1533 /* should not reach here */
1534 g_assert_not_reached ();
1540 * Implement the "Ping" method call of the org.freedesktop.IBus interface.
1543 _ibus_ping (BusIBusImpl *ibus,
1544 GVariant *parameters,
1545 GDBusMethodInvocation *invocation)
1547 g_dbus_method_invocation_return_value (invocation, parameters);
1551 * _ibus_get_use_sys_layout:
1553 * Implement the "GetUseSysLayout" method call of the org.freedesktop.IBus interface.
1556 _ibus_get_use_sys_layout (BusIBusImpl *ibus,
1557 GVariant *parameters,
1558 GDBusMethodInvocation *invocation)
1560 g_dbus_method_invocation_return_value (invocation,
1561 g_variant_new ("(b)", ibus->use_sys_layout));
1565 * _ibus_get_use_global_engine:
1567 * Implement the "GetUseGlobalEngine" method call of the org.freedesktop.IBus interface.
1570 _ibus_get_use_global_engine (BusIBusImpl *ibus,
1571 GVariant *parameters,
1572 GDBusMethodInvocation *invocation)
1574 g_dbus_method_invocation_return_value (invocation,
1575 g_variant_new ("(b)", ibus->use_global_engine));
1579 * _ibus_get_global_engine:
1581 * Implement the "GetGlobalEngine" method call of the org.freedesktop.IBus interface.
1584 _ibus_get_global_engine (BusIBusImpl *ibus,
1585 GVariant *parameters,
1586 GDBusMethodInvocation *invocation)
1588 IBusEngineDesc *desc = NULL;
1591 if (!ibus->use_global_engine)
1593 BusInputContext *context = ibus->focused_context;
1594 if (context == NULL)
1595 context = ibus->fake_context;
1597 desc = bus_input_context_get_engine_desc (context);
1602 GVariant *variant = ibus_serializable_serialize ((IBusSerializable *) desc);
1603 g_dbus_method_invocation_return_value (invocation,
1604 g_variant_new ("(v)", variant));
1608 g_dbus_method_invocation_return_error (invocation,
1609 G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1610 "No global engine.");
1614 _ibus_set_global_engine_ready_cb (BusInputContext *context,
1616 GDBusMethodInvocation *invocation)
1618 GError *error = NULL;
1619 if (!bus_input_context_set_engine_by_desc_finish (context, res, &error)) {
1620 g_error_free (error);
1621 g_dbus_method_invocation_return_error (invocation,
1623 G_DBUS_ERROR_FAILED,
1624 "Set global engine failed.");
1628 g_dbus_method_invocation_return_value (invocation, NULL);
1633 * _ibus_set_global_engine:
1635 * Implement the "SetGlobalEngine" method call of the org.freedesktop.IBus interface.
1638 _ibus_set_global_engine (BusIBusImpl *ibus,
1639 GVariant *parameters,
1640 GDBusMethodInvocation *invocation)
1642 if (!ibus->use_global_engine) {
1643 g_dbus_method_invocation_return_error (invocation,
1644 G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1645 "Global engine feature is disabled.");
1649 BusInputContext *context = ibus->focused_context;
1650 if (context == NULL)
1651 context = ibus->fake_context;
1653 const gchar *new_engine_name = NULL;
1654 g_variant_get (parameters, "(&s)", &new_engine_name);
1655 const gchar *old_engine_name = NULL;
1657 BusEngineProxy *engine = bus_input_context_get_engine (context);
1660 ibus_engine_desc_get_name (bus_engine_proxy_get_desc (engine));
1663 if (g_strcmp0 (new_engine_name, old_engine_name) == 0) {
1664 /* If the user requested the same global engine, then we just enable the
1666 bus_input_context_enable (context);
1667 g_dbus_method_invocation_return_value (invocation, NULL);
1671 IBusEngineDesc *desc = _find_engine_desc_by_name (ibus, new_engine_name);
1673 g_dbus_method_invocation_return_error (invocation,
1675 G_DBUS_ERROR_FAILED,
1676 "Can not find engine %s.",
1681 bus_input_context_set_engine_by_desc (context,
1683 g_gdbus_timeout, /* timeout in msec. */
1684 NULL, /* we do not cancel the call. */
1685 (GAsyncReadyCallback) _ibus_set_global_engine_ready_cb,
1690 * _ibus_is_global_engine_enabled:
1692 * Implement the "IsGlobalEngineEnabled" method call of the org.freedesktop.IBus interface.
1695 _ibus_is_global_engine_enabled (BusIBusImpl *ibus,
1696 GVariant *parameters,
1697 GDBusMethodInvocation *invocation)
1699 gboolean enabled = FALSE;
1702 if (!ibus->use_global_engine)
1705 BusInputContext *context = ibus->focused_context;
1706 if (context == NULL)
1707 context = ibus->fake_context;
1708 if (context == NULL)
1711 enabled = bus_input_context_is_enabled (context);
1714 g_dbus_method_invocation_return_value (invocation,
1715 g_variant_new ("(b)", enabled));
1719 * bus_ibus_impl_service_method_call:
1721 * Handle a D-Bus method call whose destination and interface name are both "org.freedesktop.IBus"
1724 bus_ibus_impl_service_method_call (IBusService *service,
1725 GDBusConnection *connection,
1726 const gchar *sender,
1727 const gchar *object_path,
1728 const gchar *interface_name,
1729 const gchar *method_name,
1730 GVariant *parameters,
1731 GDBusMethodInvocation *invocation)
1733 if (g_strcmp0 (interface_name, "org.freedesktop.IBus") != 0) {
1734 IBUS_SERVICE_CLASS (bus_ibus_impl_parent_class)->service_method_call (
1735 service, connection, sender, object_path, interface_name, method_name,
1736 parameters, invocation);
1740 /* all methods in the xml definition above should be listed here. */
1741 static const struct {
1742 const gchar *method_name;
1743 void (* method_callback) (BusIBusImpl *, GVariant *, GDBusMethodInvocation *);
1745 /* IBus interface */
1746 { "GetAddress", _ibus_get_address },
1747 { "CreateInputContext", _ibus_create_input_context },
1748 { "CurrentInputContext", _ibus_current_input_context },
1749 { "RegisterComponent", _ibus_register_component },
1750 { "ListEngines", _ibus_list_engines },
1751 { "ListActiveEngines", _ibus_list_active_engines },
1752 { "Exit", _ibus_exit },
1753 { "Ping", _ibus_ping },
1754 { "GetUseSysLayout", _ibus_get_use_sys_layout },
1755 { "GetUseGlobalEngine", _ibus_get_use_global_engine },
1756 { "GetGlobalEngine", _ibus_get_global_engine },
1757 { "SetGlobalEngine", _ibus_set_global_engine },
1758 { "IsGlobalEngineEnabled", _ibus_is_global_engine_enabled },
1762 for (i = 0; i < G_N_ELEMENTS (methods); i++) {
1763 if (g_strcmp0 (methods[i].method_name, method_name) == 0) {
1764 methods[i].method_callback ((BusIBusImpl *) service, parameters, invocation);
1769 /* notreached - unknown method calls that are not in the introspection_xml should be handled by the GDBus library. */
1770 g_return_if_reached ();
1774 bus_ibus_impl_get_default (void)
1776 static BusIBusImpl *ibus = NULL;
1779 ibus = (BusIBusImpl *) g_object_new (BUS_TYPE_IBUS_IMPL,
1780 "object-path", IBUS_PATH_IBUS,
1787 bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
1790 g_assert (BUS_IS_IBUS_IMPL (ibus));
1792 BusFactoryProxy *factory;
1794 factory = (BusFactoryProxy *) g_hash_table_lookup (ibus->factory_dict, path);
1800 bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus)
1802 g_assert (BUS_IS_IBUS_IMPL (ibus));
1804 return ibus->hotkey_profile;
1808 bus_ibus_impl_get_keymap (BusIBusImpl *ibus)
1811 g_assert (BUS_IS_IBUS_IMPL (ibus));
1813 return ibus->keymap;
1817 bus_ibus_impl_get_registry (BusIBusImpl *ibus)
1820 g_assert (BUS_IS_IBUS_IMPL (ibus));
1822 return ibus->registry;
1826 * bus_ibus_impl_emit_signal:
1828 * Send a D-Bus signal to buses (connections) that are listening to the signal.
1831 bus_ibus_impl_emit_signal (BusIBusImpl *ibus,
1832 const gchar *signal_name,
1833 GVariant *parameters)
1835 static guint32 serial = 0;
1836 GDBusMessage *message = g_dbus_message_new_signal ("/org/freedesktop/IBus",
1837 "org.freedesktop.IBus",
1839 /* set a non-zero serial to make libdbus happy */
1840 g_dbus_message_set_serial (message, ++serial);
1841 g_dbus_message_set_sender (message, "org.freedesktop.IBus");
1843 g_dbus_message_set_body (message, parameters);
1844 bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
1845 g_object_unref (message);
1849 bus_ibus_impl_registry_changed (BusIBusImpl *ibus)
1851 bus_ibus_impl_emit_signal (ibus, "RegistryChanged", NULL);
1855 bus_ibus_impl_global_engine_changed (BusIBusImpl *ibus)
1857 bus_ibus_impl_emit_signal (ibus, "GlobalEngineChanged", NULL);
1861 bus_ibus_impl_filter_keyboard_shortcuts (BusIBusImpl *ibus,
1862 BusInputContext *context,
1866 guint prev_modifiers)
1868 static GQuark trigger = 0;
1869 static GQuark next = 0;
1870 static GQuark previous = 0;
1876 trigger = g_quark_from_static_string ("trigger");
1877 next = g_quark_from_static_string ("next-engine-in-menu");
1878 previous = g_quark_from_static_string ("previous-engine");
1881 /* Try global hotkeys first. */
1882 event = ibus_hotkey_profile_filter_key_event (ibus->hotkey_profile,
1889 if (event == trigger) {
1890 gboolean enabled = bus_input_context_is_enabled (context);
1892 bus_input_context_disable (context);
1895 bus_input_context_enable (context);
1897 return (enabled != bus_input_context_is_enabled (context));
1899 if (event == next) {
1900 if (bus_input_context_is_enabled (context)) {
1901 bus_ibus_impl_context_request_next_engine_in_menu (ibus, context);
1904 bus_input_context_enable (context);
1908 if (event == previous) {
1909 if (bus_input_context_is_enabled (context)) {
1910 bus_ibus_impl_context_request_previous_engine (ibus, context);
1913 bus_input_context_enable (context);
1918 if (!ibus->engines_hotkey_profile || !ibus->hotkey_to_engines_map) {
1922 /* Then try engines hotkeys. */
1923 event = ibus_hotkey_profile_filter_key_event (ibus->engines_hotkey_profile,
1933 engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
1934 GUINT_TO_POINTER (event));
1936 BusEngineProxy *current_engine = bus_input_context_get_engine (context);
1937 IBusEngineDesc *current_engine_desc =
1938 (current_engine ? bus_engine_proxy_get_desc (current_engine) : NULL);
1939 IBusEngineDesc *new_engine_desc = (IBusEngineDesc *) engine_list->data;
1941 g_assert (new_engine_desc);
1943 /* Find out what engine we should switch to. If the current engine has
1944 * the same hotkey, then we should switch to the next engine with the
1945 * same hotkey in the list. Otherwise, we just switch to the first
1946 * engine in the list. */
1947 GList *p = engine_list;
1948 for (; p->next != NULL; p = p->next) {
1949 if (current_engine_desc == (IBusEngineDesc *) p->data) {
1950 new_engine_desc = (IBusEngineDesc *) p->next->data;
1955 if (current_engine_desc != new_engine_desc) {
1956 bus_ibus_impl_set_context_engine_from_desc (ibus, context, new_engine_desc);
1966 * bus_ibus_impl_load_global_engine_name_from_config:
1968 * Retrieve the "global_engine" config from the config daemon. Return NULL if the daemon is not ready.
1971 bus_ibus_impl_load_global_engine_name_from_config (BusIBusImpl *ibus)
1973 g_assert (BUS_IS_IBUS_IMPL (ibus));
1974 if (ibus->config == NULL) {
1975 /* the config component is not started yet. */
1978 g_assert (IBUS_IS_CONFIG (ibus->config));
1980 GVariant *variant = ibus_config_get_value (ibus->config, "general", "global_engine");
1981 gchar *engine_name = NULL;
1982 if (variant != NULL) {
1983 g_variant_get (variant, "s", &engine_name);
1984 g_variant_unref (variant);
1990 * bus_ibus_impl_save_global_engine_name_to_config:
1992 * Save the "global_engine" config value on the config daemon. No-op if the daemon is not ready.
1995 bus_ibus_impl_save_global_engine_name_to_config (BusIBusImpl *ibus)
1997 g_assert (BUS_IS_IBUS_IMPL (ibus));
2000 ibus->use_global_engine &&
2001 ibus->global_engine_name) {
2002 ibus_config_set_value (ibus->config,
2003 "general", "global_engine",
2004 g_variant_new ("s", ibus->global_engine_name));
2009 * bus_ibus_impl_load_global_previous_engine_name_from_config:
2011 * Retrieve the "global_previous_engine" config from the config daemon. Return NULL if the daemon is not ready.
2014 bus_ibus_impl_load_global_previous_engine_name_from_config (BusIBusImpl *ibus)
2016 g_assert (BUS_IS_IBUS_IMPL (ibus));
2017 if (ibus->config == NULL) {
2018 /* the config component is not started yet. */
2021 g_assert (IBUS_IS_CONFIG (ibus->config));
2023 GVariant *value = ibus_config_get_value (ibus->config, "general", "global_previous_engine");
2026 gchar *engine_name = NULL;
2027 g_variant_get (value, "(s)", &engine_name);
2028 g_variant_unref (value);
2033 * bus_ibus_impl_save_global_previous_engine_name_to_config:
2035 * Save the "global_previous_engine" config value on the config daemon. No-op if the daemon is not ready.
2038 bus_ibus_impl_save_global_previous_engine_name_to_config (BusIBusImpl *ibus)
2040 g_assert (BUS_IS_IBUS_IMPL (ibus));
2043 ibus->use_global_engine &&
2044 ibus->global_previous_engine_name) {
2045 ibus_config_set_value (ibus->config,
2046 "general", "global_previous_engine",
2047 g_variant_new ("s", ibus->global_previous_engine_name));
2052 * _add_engine_hotkey:
2054 * Check the engine-specific hot key of the engine, and update ibus->engines_hotkey_profile.
2057 _add_engine_hotkey (IBusEngineDesc *engine, BusIBusImpl *ibus)
2059 const gchar *hotkeys;
2060 gchar **hotkey_list;
2073 hotkeys = ibus_engine_desc_get_hotkeys (engine);
2075 if (!hotkeys || !*hotkeys) {
2079 hotkey_list = g_strsplit_set (hotkeys, ";,", 0);
2081 for (p = hotkey_list; p && *p; ++p) {
2082 hotkey = g_strstrip (*p);
2083 if (!*hotkey || !ibus_key_event_from_string (hotkey, &keyval, &modifiers)) {
2087 /* If the hotkey already exists, we won't need to add it again. */
2088 event = ibus_hotkey_profile_lookup_hotkey (ibus->engines_hotkey_profile,
2091 event = g_quark_from_string (hotkey);
2092 ibus_hotkey_profile_add_hotkey (ibus->engines_hotkey_profile,
2093 keyval, modifiers, event);
2096 engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
2097 GUINT_TO_POINTER (event));
2099 /* As we will rebuild the engines hotkey map whenever an engine was
2100 * added or removed, we don't need to hold a reference of the engine
2102 engine_list = g_list_append (engine_list, engine);
2104 /* We need to steal the value before adding it back, otherwise it will
2106 g_hash_table_steal (ibus->hotkey_to_engines_map, GUINT_TO_POINTER (event));
2108 g_hash_table_insert (ibus->hotkey_to_engines_map,
2109 GUINT_TO_POINTER (event), engine_list);
2112 g_strfreev (hotkey_list);
2116 * bus_ibus_impl_update_engines_hotkey_profile:
2118 * Check engine-specific hot keys of all active engines, and update ibus->engines_hotkey_profile.
2121 bus_ibus_impl_update_engines_hotkey_profile (BusIBusImpl *ibus)
2123 if (ibus->engines_hotkey_profile) {
2124 g_object_unref (ibus->engines_hotkey_profile);
2127 if (ibus->hotkey_to_engines_map) {
2128 g_hash_table_unref (ibus->hotkey_to_engines_map);
2131 ibus->engines_hotkey_profile = ibus_hotkey_profile_new ();
2132 ibus->hotkey_to_engines_map =
2133 g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_list_free);
2135 g_list_foreach (ibus->register_engine_list, (GFunc) _add_engine_hotkey, ibus);
2136 g_list_foreach (ibus->engine_list, (GFunc) _add_engine_hotkey, ibus);
2140 bus_ibus_impl_is_use_sys_layout (BusIBusImpl *ibus)
2142 g_assert (BUS_IS_IBUS_IMPL (ibus));
2144 return ibus->use_sys_layout;
2148 bus_ibus_impl_is_embed_preedit_text (BusIBusImpl *ibus)
2150 g_assert (BUS_IS_IBUS_IMPL (ibus));
2152 return ibus->embed_preedit_text;
2156 bus_ibus_impl_get_focused_input_context (BusIBusImpl *ibus)
2158 g_assert (BUS_IS_IBUS_IMPL (ibus));
2160 return ibus->focused_context;