Set nonzero serial number for RegistryChanged / EngineChanged signals.
[platform/upstream/ibus.git] / bus / ibusimpl.c
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.
6  *
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.
11  *
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.
16  *
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.
21  */
22
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/wait.h>
26 #include <signal.h>
27 #include <stdlib.h>
28 #include <locale.h>
29 #include <string.h>
30 #include <strings.h>
31 #include "types.h"
32 #include "ibusimpl.h"
33 #include "dbusimpl.h"
34 #include "server.h"
35 #include "connection.h"
36 #include "registry.h"
37 #include "factoryproxy.h"
38 #include "panelproxy.h"
39 #include "inputcontext.h"
40 #include "option.h"
41
42 struct _BusIBusImpl {
43     IBusService parent;
44     /* instance members */
45     GHashTable *factory_dict;
46
47     /* registered components */
48     GList *registered_components;
49     GList *contexts;
50
51     /* a fake input context for global engine support */
52     BusInputContext *fake_context;
53
54     /* a list of engines that are preloaded. */
55     GList *engine_list;
56     /* a list of engines that are started by a user (without the --ibus command line flag.) */
57     GList *register_engine_list;
58
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;
62
63     gboolean embed_preedit_text;
64     gboolean enable_by_default;
65
66     BusRegistry     *registry;
67
68     BusInputContext *focused_context;
69     BusPanelProxy   *panel;
70     IBusConfig      *config;
71
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. */
75     IBusKeymap      *keymap;
76
77     gboolean use_global_engine;
78     gchar *global_engine_name;
79     gchar *global_previous_engine_name;
80
81     /* engine-specific hotkeys */
82     IBusHotkeyProfile *engines_hotkey_profile;
83     GHashTable      *hotkey_to_engines_map;
84 };
85
86 struct _BusIBusImplClass {
87     IBusServiceClass parent;
88
89     /* class members */
90 };
91
92 enum {
93     LAST_SIGNAL,
94 };
95
96 enum {
97     PROP_0,
98 };
99
100 /*
101 static guint            _signals[LAST_SIGNAL] = { 0 };
102 */
103
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,
109                                                   const gchar        *sender,
110                                                   const gchar        *object_path,
111                                                   const gchar        *interface_name,
112                                                   const gchar        *method_name,
113                                                   GVariant           *parameters,
114                                                   GDBusMethodInvocation
115                                                                      *invocation);
116 /* TODO use property to replace some getter and setter in future */
117 #if 0
118 static GVariant *ibus_ibus_impl_service_get_property
119                                               (IBusService        *service,
120                                                GDBusConnection    *connection,
121                                                const gchar        *sender,
122                                                const gchar        *object_path,
123                                                const gchar        *interface_name,
124                                                const gchar        *property_name,
125                                                GError            **error);
126 static gboolean  ibus_ibus_impl_service_set_property
127                                               (IBusService        *service,
128                                                GDBusConnection    *connection,
129                                                const gchar        *sender,
130                                                const gchar        *object_path,
131                                                const gchar        *interface_name,
132                                                const gchar        *property_name,
133                                                GVariant           *value,
134                                                GError            **error);
135 #endif
136 static void     bus_ibus_impl_set_trigger       (BusIBusImpl        *ibus,
137                                                  GVariant           *value);
138 static void     bus_ibus_impl_set_next_engine_in_menu
139                                                 (BusIBusImpl        *ibus,
140                                                  GVariant           *value);
141 static void     bus_ibus_impl_set_previous_engine
142                                                 (BusIBusImpl        *ibus,
143                                                  GVariant           *value);
144 static void     bus_ibus_impl_set_preload_engines
145                                                 (BusIBusImpl        *ibus,
146                                                  GVariant           *value);
147 static void     bus_ibus_impl_set_use_sys_layout
148                                                 (BusIBusImpl        *ibus,
149                                                  GVariant           *value);
150 static void     bus_ibus_impl_set_embed_preedit_text
151                                                 (BusIBusImpl        *ibus,
152                                                  GVariant           *value);
153 static void     bus_ibus_impl_set_enable_by_default
154                                                 (BusIBusImpl        *ibus,
155                                                  GVariant           *value);
156 static void     bus_ibus_impl_set_use_global_engine
157                                                 (BusIBusImpl        *ibus,
158                                                  GVariant           *value);
159 static void     bus_ibus_impl_registry_changed  (BusIBusImpl        *ibus);
160 static void     bus_ibus_impl_global_engine_changed
161                                                 (BusIBusImpl        *ibus);
162 static void     bus_ibus_impl_set_context_engine_from_desc
163                                                 (BusIBusImpl        *ibus,
164                                                  BusInputContext    *context,
165                                                  IBusEngineDesc     *desc);
166 static gchar   *bus_ibus_impl_load_global_engine_name_from_config
167                                                 (BusIBusImpl        *ibus);
168 static void     bus_ibus_impl_save_global_engine_name_to_config
169                                                 (BusIBusImpl        *ibus);
170
171 static gchar   *bus_ibus_impl_load_global_previous_engine_name_from_config
172                                                 (BusIBusImpl        *ibus);
173 static void     bus_ibus_impl_save_global_previous_engine_name_to_config
174                                                 (BusIBusImpl        *ibus);
175 static void     bus_ibus_impl_update_engines_hotkey_profile
176                                                 (BusIBusImpl        *ibus);
177 static BusInputContext
178                *bus_ibus_impl_create_input_context
179                                                 (BusIBusImpl        *ibus,
180                                                  BusConnection      *connection,
181                                                  const gchar        *client);
182 /* some callback functions */
183 static void     _context_engine_changed_cb      (BusInputContext    *context,
184                                                  BusIBusImpl        *ibus);
185
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[] =
190     "<node>\n"
191     "  <interface name='org.freedesktop.IBus'>\n"
192     "    <method name='GetAddress'>\n"
193     "      <arg direction='out' type='s' name='address' />\n"
194     "    </method>\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"
198     "    </method>\n"
199     "    <method name='CurrentInputContext'>\n"
200     "      <arg direction='out' type='o' name='object_path' />\n"
201     "    </method>\n"
202     "    <method name='RegisterComponent'>\n"
203     "      <arg direction='in'  type='v' name='component' />\n"
204     "    </method>\n"
205     "    <method name='ListEngines'>\n"
206     "      <arg direction='out' type='av' name='engines' />\n"
207     "    </method>\n"
208     "    <method name='ListActiveEngines'>\n"
209     "      <arg direction='out' type='av' name='engines' />\n"
210     "    </method>\n"
211     "    <method name='Exit'>\n"
212     "      <arg direction='in'  type='b' name='restart' />\n"
213     "    </method>\n"
214     "    <method name='Ping'>\n"
215     "      <arg direction='in'  type='v' name='data' />\n"
216     "      <arg direction='out' type='v' name='data' />\n"
217     "    </method>\n"
218     "    <method name='GetUseSysLayout'>\n"
219     "      <arg direction='out' type='b' name='enabled' />\n"
220     "    </method>\n"
221     "    <method name='GetUseGlobalEngine'>\n"
222     "      <arg direction='out' type='b' name='enabled' />\n"
223     "    </method>\n"
224     "    <method name='GetGlobalEngine'>\n"
225     "      <arg direction='out' type='v' name='desc' />\n"
226     "    </method>\n"
227     "    <method name='SetGlobalEngine'>\n"
228     "      <arg direction='in'  type='s' name='engine_name' />\n"
229     "    </method>\n"
230     "    <method name='IsGlobalEngineEnabled'>\n"
231     "      <arg direction='out' type='b' name='enabled' />\n"
232     "    </method>\n"
233     "    <signal name='RegistryChanged'>\n"
234     "    </signal>\n"
235     "    <signal name='GlobalEngineChanged'>\n"
236     "    </signal>\n"
237     "  </interface>\n"
238     "</node>\n";
239
240
241 G_DEFINE_TYPE (BusIBusImpl, bus_ibus_impl, IBUS_TYPE_SERVICE)
242
243 static void
244 bus_ibus_impl_class_init (BusIBusImplClass *class)
245 {
246     IBUS_OBJECT_CLASS (class)->destroy = (IBusObjectDestroyFunc) bus_ibus_impl_destroy;
247
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);
252 }
253
254 /**
255  * _panel_destroy_cb:
256  *
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.
259  */
260 static void
261 _panel_destroy_cb (BusPanelProxy *panel,
262                    BusIBusImpl   *ibus)
263 {
264     g_assert (BUS_IS_PANEL_PROXY (panel));
265     g_assert (BUS_IS_IBUS_IMPL (ibus));
266
267     g_return_if_fail (ibus->panel == panel);
268
269     ibus->panel = NULL;
270     g_object_unref (panel);
271 }
272
273 static void
274 bus_ibus_impl_set_hotkey (BusIBusImpl *ibus,
275                           GQuark       hotkey,
276                           GVariant    *value)
277 {
278     g_assert (BUS_IS_IBUS_IMPL (ibus));
279
280     ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
281
282     if (value == NULL) {
283         return;
284     }
285
286     GVariantIter iter;
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,
291                                                    str,
292                                                    hotkey);
293     }
294
295 }
296
297 /**
298  * bus_ibus_impl_set_trigger:
299  *
300  * A function to be called when "trigger" config is updated. If the value is NULL, the default trigger (Ctrl+space) is set.
301  */
302 static void
303 bus_ibus_impl_set_trigger (BusIBusImpl *ibus,
304                            GVariant    *value)
305 {
306     GQuark hotkey = g_quark_from_static_string ("trigger");
307     if (value != NULL) {
308         bus_ibus_impl_set_hotkey (ibus, hotkey, value);
309     }
310 #ifndef OS_CHROMEOS
311     else {
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,
315                                         IBUS_space,
316                                         IBUS_CONTROL_MASK,
317                                         hotkey);
318     }
319 #endif
320 }
321
322 /**
323  * bus_ibus_impl_set_next_engine_in_menu:
324  *
325  * A function to be called when "next_engine_in_menu" config is updated.
326  */
327 static void
328 bus_ibus_impl_set_next_engine_in_menu (BusIBusImpl *ibus,
329                                        GVariant    *value)
330 {
331     GQuark hotkey = g_quark_from_static_string ("next-engine-in-menu");
332     bus_ibus_impl_set_hotkey (ibus, hotkey, value);
333 }
334
335 /**
336  * bus_ibus_impl_set_previous_engine:
337  *
338  * A function to be called when "previous_engine" config is updated.
339  */
340 static void
341 bus_ibus_impl_set_previous_engine (BusIBusImpl *ibus,
342                                    GVariant    *value)
343 {
344     GQuark hotkey = g_quark_from_static_string ("previous-engine");
345     bus_ibus_impl_set_hotkey (ibus, hotkey, value);
346 }
347
348 /**
349  * bus_ibus_impl_set_preload_engines:
350  *
351  * A function to be called when "preload_engines" config is updated.
352  */
353 static void
354 bus_ibus_impl_set_preload_engines (BusIBusImpl *ibus,
355                                    GVariant    *value)
356 {
357     GList *engine_list = NULL;
358
359     g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
360     g_list_free (ibus->engine_list);
361
362     if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_ARRAY) {
363         GVariantIter iter;
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)
369                 continue;
370             engine_list = g_list_append (engine_list, engine);
371         }
372     }
373
374     g_list_foreach (engine_list, (GFunc) g_object_ref, NULL);
375     ibus->engine_list = engine_list;
376
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);
381         }
382     }
383
384     bus_ibus_impl_update_engines_hotkey_profile (ibus);
385 }
386
387 /**
388  * bus_ibus_impl_set_use_sys_layout:
389  *
390  * A function to be called when "use_system_keyboard_layout" config is updated.
391  */
392 static void
393 bus_ibus_impl_set_use_sys_layout (BusIBusImpl *ibus,
394                                   GVariant    *value)
395 {
396     if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
397         ibus->use_sys_layout = g_variant_get_boolean (value);
398     }
399 }
400
401 /**
402  * bus_ibus_impl_set_embed_preedit_text:
403  *
404  * A function to be called when "use_embed_preedit_text" config is updated.
405  */
406 static void
407 bus_ibus_impl_set_embed_preedit_text (BusIBusImpl *ibus,
408                                       GVariant    *value)
409 {
410     if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
411         ibus->embed_preedit_text = g_variant_get_boolean (value);
412     }
413 }
414
415 /**
416  * bus_ibus_impl_set_enable_by_default:
417  *
418  * A function to be called when "enable_by_default" config is updated.
419  */
420 static void
421 bus_ibus_impl_set_enable_by_default (BusIBusImpl *ibus,
422                                      GVariant    *value)
423 {
424     if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
425         ibus->enable_by_default = g_variant_get_boolean (value);
426     }
427 }
428
429 /**
430  * bus_ibus_impl_set_use_global_engine:
431  *
432  * A function to be called when "use_global_engine" config is updated.
433  */
434 static void
435 bus_ibus_impl_set_use_global_engine (BusIBusImpl *ibus,
436                                      GVariant    *value)
437 {
438     if (value == NULL || g_variant_classify (value) != G_VARIANT_CLASS_BOOLEAN)
439         return;
440
441     gboolean new_value = g_variant_get_boolean (value);
442     if (ibus->use_global_engine == new_value)
443         return;
444
445     if (new_value) {
446         /* turn on use_global_engine option */
447         ibus->use_global_engine = TRUE;
448     }
449     else {
450         /* turn off use_global_engine option */
451         ibus->use_global_engine = FALSE;
452
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);
456         }
457         /* remove engine in fake context */
458         bus_input_context_set_engine (ibus->fake_context, NULL);
459     }
460 }
461
462 static gint
463 _engine_desc_cmp (IBusEngineDesc *desc1,
464                   IBusEngineDesc *desc2)
465 {
466     return - ((gint) ibus_engine_desc_get_rank (desc1)) +
467               ((gint) ibus_engine_desc_get_rank (desc2));
468 }
469
470 /**
471  * bus_ibus_impl_set_default_preload_engines:
472  *
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).
474  */
475 static void
476 bus_ibus_impl_set_default_preload_engines (BusIBusImpl *ibus)
477 {
478     g_assert (BUS_IS_IBUS_IMPL (ibus));
479
480     static gboolean done = FALSE;
481
482     if (done || ibus->config == NULL) {
483         return;
484     }
485
486     GVariant *variant = ibus_config_get_value (ibus->config, "general", "preload_engines");
487     if (variant != NULL) {
488         done = TRUE;
489         g_variant_unref (variant);
490         return;
491     }
492
493     done = TRUE;
494     gchar *lang = g_strdup (setlocale (LC_ALL, NULL));
495     gchar *p = index (lang, '.');
496     if (p) {
497         *p = '\0';
498     }
499
500     GList *engines = bus_registry_get_engines_by_language (ibus->registry, lang);
501     if (engines == NULL) {
502         p = index (lang, '_');
503         if (p) {
504             *p = '\0';
505             engines = bus_registry_get_engines_by_language (ibus->registry, lang);
506         }
507     }
508     g_free (lang);
509
510     /* sort engines by rank */
511     engines = g_list_sort (engines, (GCompareFunc) _engine_desc_cmp);
512
513     GVariantBuilder builder;
514     g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
515     GList *list;
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));
521     }
522
523     GVariant *value = g_variant_builder_end (&builder);
524     if (value != NULL) {
525         if (g_variant_n_children (value) > 0) {
526             ibus_config_set_value (ibus->config,
527                                    "general", "preload_engines", value);
528         } else {
529             /* We don't update preload_engines with an empty string for safety.
530              * Just unref the floating value. */
531             g_variant_unref (value);
532         }
533     }
534     g_list_free (engines);
535 }
536
537 /* The list of config entries that are related to ibus-daemon. */
538 const static struct {
539     gchar *section;
540     gchar *key;
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 },
551 };
552
553 /**
554  * bus_ibus_impl_reload_config
555  *
556  * Read config entries (e.g. preload_engines) from the config daemon.
557  */
558 static void
559 bus_ibus_impl_reload_config (BusIBusImpl *ibus)
560 {
561     g_assert (BUS_IS_IBUS_IMPL (ibus));
562
563     gint i;
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);
572     }
573 }
574
575 /**
576  * _config_value_changed_cb:
577  *
578  * A callback function to be called when the "ValueChanged" D-Bus signal is sent from the config daemon.
579  */
580 static void
581 _config_value_changed_cb (IBusConfig  *config,
582                           gchar       *section,
583                           gchar       *key,
584                           GVariant    *value,
585                           BusIBusImpl *ibus)
586 {
587     g_assert (IBUS_IS_CONFIG (config));
588     g_assert (section);
589     g_assert (key);
590     g_assert (value);
591     g_assert (BUS_IS_IBUS_IMPL (ibus));
592
593     gint i;
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);
598             break;
599         }
600     }
601 }
602
603 /**
604  * _config_destroy_cb:
605  *
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.
608  */
609 static void
610 _config_destroy_cb (IBusConfig  *config,
611                     BusIBusImpl *ibus)
612 {
613     g_assert (IBUS_IS_CONFIG (config));
614     g_assert (BUS_IS_IBUS_IMPL (ibus));
615
616     g_assert (ibus->config == config);
617
618     g_object_unref (ibus->config);
619     ibus->config = NULL;
620 }
621
622 static void
623 _registry_changed_cb (BusRegistry *registry,
624                       BusIBusImpl *ibus)
625 {
626     bus_ibus_impl_registry_changed (ibus);
627 }
628
629 /*
630  * _dbus_name_owner_changed_cb:
631  *
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.
634  */
635 static void
636 _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
637                              const gchar *name,
638                              const gchar *old_name,
639                              const gchar *new_name,
640                              BusIBusImpl *ibus)
641 {
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));
647
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;
652
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);
657             }
658
659             connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
660             g_return_if_fail (connection != NULL);
661
662             ibus->panel = bus_panel_proxy_new (connection);
663
664             g_signal_connect (ibus->panel,
665                               "destroy",
666                               G_CALLBACK (_panel_destroy_cb),
667                               ibus);
668
669             if (ibus->focused_context != NULL) {
670                 bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context);
671             }
672         }
673     }
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;
678
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);
683             }
684
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);
688
689             ibus->config = g_initable_new (IBUS_TYPE_CONFIG,
690                                            NULL,
691                                            NULL,
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,
699                                            NULL);
700
701             g_signal_connect (ibus->config,
702                               "value-changed",
703                               G_CALLBACK (_config_value_changed_cb),
704                               ibus);
705
706             g_signal_connect (ibus->config,
707                               "destroy",
708                               G_CALLBACK (_config_destroy_cb),
709                               ibus);
710
711             bus_ibus_impl_set_default_preload_engines (ibus);
712             bus_ibus_impl_reload_config (ibus);
713         }
714     }
715
716     bus_registry_name_owner_changed (ibus->registry, name, old_name, new_name);
717 }
718
719 /**
720  * bus_ibus_impl_init:
721  *
722  * The constructor of BusIBusImpl. Initialize all member variables of a BusIBusImpl object.
723  */
724 static void
725 bus_ibus_impl_init (BusIBusImpl *ibus)
726 {
727     ibus->factory_dict = g_hash_table_new_full (
728                             g_str_hash,
729                             g_str_equal,
730                             NULL,
731                             (GDestroyNotify) g_object_unref);
732
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 |
739                                         IBUS_CAP_FOCUS |
740                                         IBUS_CAP_SURROUNDING_TEXT);
741     g_signal_connect (ibus->fake_context,
742                       "engine-changed",
743                       G_CALLBACK (_context_engine_changed_cb),
744                       ibus);
745     bus_input_context_focus_in (ibus->fake_context);
746
747     ibus->engine_list = NULL;
748     ibus->register_engine_list = NULL;
749     ibus->contexts = NULL;
750     ibus->focused_context = NULL;
751     ibus->panel = NULL;
752     ibus->config = NULL;
753
754     ibus->registry = bus_registry_new ();
755
756     g_signal_connect (ibus->registry,
757                       "changed",
758                       G_CALLBACK (_registry_changed_cb),
759                       ibus);
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);
765     }
766 #endif
767
768     ibus->hotkey_profile = ibus_hotkey_profile_new ();
769     ibus->keymap = ibus_keymap_get ("us");
770
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;
777
778     ibus->engines_hotkey_profile = NULL;
779     ibus->hotkey_to_engines_map = NULL;
780
781     bus_ibus_impl_reload_config (ibus);
782
783     g_signal_connect (BUS_DEFAULT_DBUS,
784                       "name-owner-changed",
785                       G_CALLBACK (_dbus_name_owner_changed_cb),
786                       ibus);
787 }
788
789 /**
790  * bus_ibus_impl_destroy:
791  *
792  * The destructor of BusIBusImpl.
793  */
794 static void
795 bus_ibus_impl_destroy (BusIBusImpl *ibus)
796 {
797     pid_t pid;
798     glong timeout;
799     gint status;
800     gboolean flag;
801
802     bus_registry_stop_all_components (ibus->registry);
803
804     pid = 0;
805     timeout = 0;
806     flag = FALSE;
807     while (1) {
808         while ((pid = waitpid (0, &status, WNOHANG)) > 0);
809
810         if (pid == -1) { /* all children finished */
811             break;
812         }
813         if (pid == 0) { /* no child status changed */
814             g_usleep (1000);
815             timeout += 1000;
816             if (timeout >= G_USEC_PER_SEC) {
817                 if (flag == FALSE) {
818                     gpointer old;
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);
823                     flag = TRUE;
824                 }
825                 else {
826                     g_warning ("Not every child processes exited!");
827                     break;
828                 }
829             }
830         }
831     }
832
833     g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
834     g_list_free (ibus->engine_list);
835     ibus->engine_list = NULL;
836
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;
840
841     if (ibus->factory_dict != NULL) {
842         g_hash_table_destroy (ibus->factory_dict);
843         ibus->factory_dict = NULL;
844     }
845
846     if (ibus->hotkey_profile != NULL) {
847         g_object_unref (ibus->hotkey_profile);
848         ibus->hotkey_profile = NULL;
849     }
850
851     if (ibus->keymap != NULL) {
852         g_object_unref (ibus->keymap);
853         ibus->keymap = NULL;
854     }
855
856     g_free (ibus->global_engine_name);
857     ibus->global_engine_name = NULL;
858
859     g_free (ibus->global_previous_engine_name);
860     ibus->global_previous_engine_name = NULL;
861
862     if (ibus->engines_hotkey_profile != NULL) {
863         g_object_unref (ibus->engines_hotkey_profile);
864         ibus->engines_hotkey_profile = NULL;
865     }
866
867     if (ibus->hotkey_to_engines_map) {
868         g_hash_table_unref (ibus->hotkey_to_engines_map);
869         ibus->hotkey_to_engines_map = NULL;
870     }
871
872     if (ibus->fake_context) {
873         g_object_unref (ibus->fake_context);
874         ibus->fake_context = NULL;
875     }
876
877     bus_server_quit ();
878     IBUS_OBJECT_CLASS (bus_ibus_impl_parent_class)->destroy (IBUS_OBJECT (ibus));
879 }
880
881 /**
882  * _ibus_get_address:
883  *
884  * Implement the "GetAddress" method call of the org.freedesktop.IBus interface.
885  */
886 static void
887 _ibus_get_address (BusIBusImpl           *ibus,
888                    GVariant              *parameters,
889                    GDBusMethodInvocation *invocation)
890 {
891     g_dbus_method_invocation_return_value (invocation,
892                                            g_variant_new ("(s)", bus_server_get_address ()));
893 }
894
895 static IBusEngineDesc *
896 _find_engine_desc_by_name (BusIBusImpl *ibus,
897                            const gchar *engine_name)
898 {
899     IBusEngineDesc *desc = NULL;
900     GList *p;
901
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)
906             return desc;
907     }
908
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)
913             return desc;
914     }
915
916     return NULL;
917 }
918
919 /**
920  * _context_request_engine_cb:
921  *
922  * A callback function to be called when the "request-engine" signal is sent to the context.
923  */
924 static void
925 _context_request_engine_cb (BusInputContext *context,
926                             const gchar     *engine_name,
927                             BusIBusImpl     *ibus)
928 {
929     IBusEngineDesc *desc = NULL;
930
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);
934
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);
939     }
940     else {
941         /* Use global engine if possible. */
942         if (ibus->use_global_engine) {
943             gchar *name = g_strdup (ibus->global_engine_name);
944             if (name == NULL) {
945                 name = bus_ibus_impl_load_global_engine_name_from_config (ibus);
946             }
947             if (name) {
948                 desc = _find_engine_desc_by_name (ibus, name);
949                 g_free (name);
950             }
951         }
952         /* request default engine */
953         if (!desc) {
954             if (ibus->register_engine_list) {
955                 desc = (IBusEngineDesc *) ibus->register_engine_list->data;
956             }
957             else if (ibus->engine_list) {
958                 desc = (IBusEngineDesc *) ibus->engine_list->data;
959             }
960         }
961         if (!desc) {
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.");
967             return;
968         }
969     }
970
971     bus_ibus_impl_set_context_engine_from_desc (ibus, context, desc);
972 }
973
974 /**
975  * bus_ibus_impl_context_request_next_engine_in_menu:
976  *
977  * Process the "next_engine_in_menu" hotkey.
978  */
979 static void
980 bus_ibus_impl_context_request_next_engine_in_menu (BusIBusImpl     *ibus,
981                                                    BusInputContext *context)
982 {
983     BusEngineProxy *engine;
984     IBusEngineDesc *desc;
985     IBusEngineDesc *next_desc = NULL;
986     GList *p;
987
988     engine = bus_input_context_get_engine (context);
989     if (engine == NULL) {
990         _context_request_engine_cb (context, NULL, ibus);
991         return;
992     }
993
994     desc = bus_engine_proxy_get_desc (engine);
995
996     p = g_list_find (ibus->register_engine_list, desc);
997     if (p != NULL) {
998         p = p->next;
999     }
1000     if (p == NULL) {
1001         p = g_list_find (ibus->engine_list, desc);
1002         if (p != NULL) {
1003             p = p->next;
1004         }
1005     }
1006
1007     if (p != NULL) {
1008         next_desc = (IBusEngineDesc*) p->data;
1009     }
1010     else {
1011         if (ibus->register_engine_list) {
1012             next_desc = (IBusEngineDesc *) ibus->register_engine_list->data;
1013         }
1014         else if (ibus->engine_list) {
1015             next_desc = (IBusEngineDesc *) ibus->engine_list->data;
1016         }
1017     }
1018
1019     bus_ibus_impl_set_context_engine_from_desc (ibus, context, next_desc);
1020 }
1021
1022 /**
1023  * bus_ibus_impl_context_request_previous_engine:
1024  *
1025  * Process the "previous_engine" hotkey.
1026  */
1027 static void
1028 bus_ibus_impl_context_request_previous_engine (BusIBusImpl     *ibus,
1029                                                BusInputContext *context)
1030 {
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");
1034     }
1035     else {
1036         if (!ibus->global_previous_engine_name) {
1037             ibus->global_previous_engine_name = bus_ibus_impl_load_global_previous_engine_name_from_config (ibus);
1038         }
1039         engine_name = ibus->global_previous_engine_name;
1040     }
1041
1042     /*
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.
1045      */
1046     if (!engine_name) {
1047         bus_ibus_impl_context_request_next_engine_in_menu (ibus, context);
1048         return;
1049     }
1050     _context_request_engine_cb (context, engine_name, ibus);
1051 }
1052
1053 static void
1054 bus_ibus_impl_set_context_engine_from_desc (BusIBusImpl     *ibus,
1055                                             BusInputContext *context,
1056                                             IBusEngineDesc  *desc)
1057 {
1058     bus_input_context_set_engine_by_desc (context,
1059                                           desc,
1060                                           g_gdbus_timeout, /* timeout in msec. */
1061                                           NULL, /* we do not cancel the call. */
1062                                           NULL, /* use the default callback function. */
1063                                           NULL);
1064 }
1065
1066 /**
1067  * bus_ibus_impl_set_focused_context:
1068  *
1069  * Set the current focused context.
1070  */
1071 static void
1072 bus_ibus_impl_set_focused_context (BusIBusImpl     *ibus,
1073                                    BusInputContext *context)
1074 {
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);
1078
1079     /* Do noting if it is not focused context. */
1080     if (ibus->focused_context == context) {
1081         return;
1082     }
1083
1084     BusEngineProxy *engine = NULL;
1085
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);
1090             if (engine) {
1091                 g_object_ref (engine);
1092                 bus_input_context_set_engine (ibus->focused_context, NULL);
1093             }
1094         }
1095
1096         if (ibus->panel != NULL)
1097             bus_panel_proxy_focus_out (ibus->panel, ibus->focused_context);
1098
1099         g_object_unref (ibus->focused_context);
1100         ibus->focused_context = NULL;
1101     }
1102
1103     if (context == NULL && ibus->use_global_engine) {
1104         context = ibus->fake_context;
1105     }
1106
1107     if (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);
1115         }
1116
1117         if (ibus->panel != NULL)
1118             bus_panel_proxy_focus_in (ibus->panel, context);
1119     }
1120 }
1121
1122
1123 /**
1124  * _context_engine_changed_cb:
1125  *
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.
1128  */
1129 static void
1130 _context_engine_changed_cb (BusInputContext *context,
1131                             BusIBusImpl     *ibus)
1132 {
1133     if (!ibus->use_global_engine)
1134         return;
1135
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)
1143                 return;
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);
1147             /* save changes */
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);
1151         }
1152     }
1153 }
1154
1155 /**
1156  * _context_focus_in_cb:
1157  *
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.
1160  */
1161 static void
1162 _context_focus_in_cb (BusInputContext *context,
1163                       BusIBusImpl     *ibus)
1164 {
1165     g_assert (BUS_IS_IBUS_IMPL (ibus));
1166     g_assert (BUS_IS_INPUT_CONTEXT (context));
1167
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) {
1171         return;
1172     }
1173
1174     bus_ibus_impl_set_focused_context (ibus, context);
1175 }
1176
1177 /**
1178  * _context_focus_out_cb:
1179  *
1180  * A callback function to be called when the "focus-out" signal is sent to the context.
1181  */
1182 static void
1183 _context_focus_out_cb (BusInputContext    *context,
1184                        BusIBusImpl        *ibus)
1185 {
1186     g_assert (BUS_IS_IBUS_IMPL (ibus));
1187     g_assert (BUS_IS_INPUT_CONTEXT (context));
1188
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) {
1192         return;
1193     }
1194
1195     /* Do noting if it is not focused context. */
1196     if (ibus->focused_context != context) {
1197         return;
1198     }
1199
1200
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.
1204          **/
1205         bus_ibus_impl_set_focused_context (ibus, NULL);
1206     }
1207 }
1208
1209 /**
1210  * _context_destroy_cb:
1211  *
1212  * A callback function to be called when the "destroy" signal is sent to the context.
1213  */
1214 static void
1215 _context_destroy_cb (BusInputContext    *context,
1216                      BusIBusImpl        *ibus)
1217 {
1218     g_assert (BUS_IS_IBUS_IMPL (ibus));
1219     g_assert (BUS_IS_INPUT_CONTEXT (context));
1220
1221     if (context == ibus->focused_context) {
1222         bus_ibus_impl_set_focused_context (ibus, NULL);
1223     }
1224
1225     ibus->contexts = g_list_remove (ibus->contexts, context);
1226     g_object_unref (context);
1227 }
1228
1229 /**
1230  * _context_enabled_cb:
1231  *
1232  * A callback function to be called when the "enabled" signal is sent to the context.
1233  */
1234 static void
1235 _context_enabled_cb (BusInputContext    *context,
1236                      BusIBusImpl        *ibus)
1237 {
1238     /* FIXME implement this. */
1239 }
1240
1241 /**
1242  * _context_disabled_cb:
1243  *
1244  * A callback function to be called when the "disabled" signal is sent to the context.
1245  */
1246 static void
1247 _context_disabled_cb (BusInputContext    *context,
1248                       BusIBusImpl        *ibus)
1249 {
1250     /* FIXME implement this. */
1251 }
1252
1253 /**
1254  * bus_ibus_impl_create_input_context:
1255  * @client: A name of a client. e.g. "gtk-im"
1256  * @returns: A BusInputContext object.
1257  *
1258  * Create a new BusInputContext object for the client.
1259  */
1260 static BusInputContext *
1261 bus_ibus_impl_create_input_context (BusIBusImpl   *ibus,
1262                                     BusConnection *connection,
1263                                     const gchar   *client)
1264 {
1265     BusInputContext *context = bus_input_context_new (connection, client);
1266     g_object_ref_sink (context);
1267     ibus->contexts = g_list_append (ibus->contexts, context);
1268
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 {
1271         gchar *name;
1272         GCallback callback;
1273     } signals [] = {
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) },
1281     };
1282
1283     gint i;
1284     for (i = 0; i < G_N_ELEMENTS (signals); i++) {
1285         g_signal_connect (context,
1286                           signals[i].name,
1287                           signals[i].callback,
1288                           ibus);
1289     }
1290
1291     if (ibus->enable_by_default) {
1292         bus_input_context_enable (context);
1293     }
1294
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);
1299     return context;
1300 }
1301
1302 /**
1303  * _ibus_create_input_context:
1304  *
1305  * Implement the "CreateInputContext" method call of the org.freedesktop.IBus interface.
1306  */
1307 static void
1308 _ibus_create_input_context (BusIBusImpl           *ibus,
1309                             GVariant              *parameters,
1310                             GDBusMethodInvocation *invocation)
1311 {
1312     const gchar *client_name = NULL;  // e.g. "gtk-im"
1313     g_variant_get (parameters, "(&s)", &client_name);
1314
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,
1319                                                 connection,
1320                                                 client_name);
1321     if (context) {
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);
1326     }
1327     else {
1328         g_dbus_method_invocation_return_error (invocation,
1329                                                G_DBUS_ERROR,
1330                                                G_DBUS_ERROR_FAILED,
1331                                                "Create input context failed!");
1332     }
1333 }
1334
1335 /**
1336  * _ibus_current_input_context:
1337  *
1338  * Implement the "CurrentInputContext" method call of the org.freedesktop.IBus interface.
1339  */
1340 static void
1341 _ibus_current_input_context (BusIBusImpl           *ibus,
1342                              GVariant              *parameters,
1343                              GDBusMethodInvocation *invocation)
1344 {
1345     if (!ibus->focused_context)
1346     {
1347         g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1348                         "No focused input context");
1349     }
1350     else {
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));
1354     }
1355 }
1356
1357 static void
1358 _component_destroy_cb (BusComponent *component,
1359                        BusIBusImpl  *ibus)
1360 {
1361     g_assert (BUS_IS_IBUS_IMPL (ibus));
1362     g_assert (BUS_IS_COMPONENT (component));
1363
1364     ibus->registered_components = g_list_remove (ibus->registered_components, component);
1365
1366     /* remove engines from engine_list */
1367     GList *engines = bus_component_get_engines (component);
1368     GList *p;
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);
1373         }
1374     }
1375     g_list_free (engines);
1376
1377     g_object_unref (component);
1378
1379     bus_ibus_impl_update_engines_hotkey_profile (ibus);
1380 }
1381
1382 /**
1383  * _ibus_register_component:
1384  *
1385  * Implement the "RegisterComponent" method call of the org.freedesktop.IBus interface.
1386  */
1387 static void
1388 _ibus_register_component (BusIBusImpl           *ibus,
1389                           GVariant              *parameters,
1390                           GDBusMethodInvocation *invocation)
1391 {
1392     GVariant *variant = g_variant_get_child_value (parameters, 0);
1393     IBusComponent *component = (IBusComponent *) ibus_serializable_deserialize (variant);
1394
1395     if (!IBUS_IS_COMPONENT (component)) {
1396         if (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.");
1400         return;
1401     }
1402
1403     BusConnection *connection = bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
1404     BusFactoryProxy *factory = bus_factory_proxy_new (connection);
1405
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.");
1410         return;
1411     }
1412
1413     g_object_ref_sink (component);
1414
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);
1419
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,
1425                                                engines);
1426
1427     g_signal_connect (buscomp, "destroy", G_CALLBACK (_component_destroy_cb), ibus);
1428
1429     bus_ibus_impl_update_engines_hotkey_profile (ibus);
1430
1431     g_dbus_method_invocation_return_value (invocation, NULL);
1432 }
1433
1434 /**
1435  * _ibus_list_engines:
1436  *
1437  * Implement the "ListEngines" method call of the org.freedesktop.IBus interface.
1438  */
1439 static void
1440 _ibus_list_engines (BusIBusImpl           *ibus,
1441                     GVariant              *parameters,
1442                     GDBusMethodInvocation *invocation)
1443 {
1444     GVariantBuilder builder;
1445     g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1446
1447     GList *engines = bus_registry_get_engines (ibus->registry);
1448     GList *p;
1449     for (p = engines; p != NULL; p = p->next) {
1450         g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1451     }
1452     g_list_free (engines);
1453     g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1454 }
1455
1456 /**
1457  * _ibus_list_active_engines:
1458  *
1459  * Implement the "ListActiveEngines" method call of the org.freedesktop.IBus interface.
1460  */
1461 static void
1462 _ibus_list_active_engines (BusIBusImpl           *ibus,
1463                            GVariant              *parameters,
1464                            GDBusMethodInvocation *invocation)
1465 {
1466     GVariantBuilder builder;
1467     g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1468
1469     GList *p;
1470     for (p = ibus->engine_list; p != NULL; p = p->next) {
1471         g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1472     }
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));
1475     }
1476     g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1477 }
1478
1479 /**
1480  * _ibus_exit:
1481  *
1482  * Implement the "Exit" method call of the org.freedesktop.IBus interface.
1483  */
1484 static void
1485 _ibus_exit (BusIBusImpl           *ibus,
1486             GVariant              *parameters,
1487             GDBusMethodInvocation *invocation)
1488 {
1489     gboolean restart = FALSE;
1490     g_variant_get (parameters, "(b)", &restart);
1491
1492     g_dbus_method_invocation_return_value (invocation, NULL);
1493
1494     /* Make sure the reply has been sent out before exit */
1495     g_dbus_connection_flush_sync (g_dbus_method_invocation_get_connection (invocation),
1496                                   NULL,
1497                                   NULL);
1498     bus_server_quit ();
1499
1500     if (!restart) {
1501         exit (0);
1502     }
1503     else {
1504         extern gchar **g_argv;
1505         gchar *exe;
1506         gint fd;
1507
1508         exe = g_strdup_printf ("/proc/%d/exe", getpid ());
1509         exe = g_file_read_link (exe, NULL);
1510
1511         if (exe == NULL)
1512             exe = BINDIR "/ibus-daemon";
1513
1514         /* close all fds except stdin, stdout, stderr */
1515         for (fd = 3; fd <= sysconf (_SC_OPEN_MAX); fd ++) {
1516             close (fd);
1517         }
1518
1519         execv (exe, g_argv);
1520
1521         /* If the server binary is replaced while the server is running,
1522          * "readlink /proc/[pid]/exe" might return a path with " (deleted)"
1523          * suffix. */
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);
1528         }
1529         g_warning ("execv %s failed!", g_argv[0]);
1530         exit (-1);
1531     }
1532
1533     /* should not reach here */
1534     g_assert_not_reached ();
1535 }
1536
1537 /**
1538  * _ibus_ping:
1539  *
1540  * Implement the "Ping" method call of the org.freedesktop.IBus interface.
1541  */
1542 static void
1543 _ibus_ping (BusIBusImpl           *ibus,
1544             GVariant              *parameters,
1545             GDBusMethodInvocation *invocation)
1546 {
1547     g_dbus_method_invocation_return_value (invocation, parameters);
1548 }
1549
1550 /**
1551  * _ibus_get_use_sys_layout:
1552  *
1553  * Implement the "GetUseSysLayout" method call of the org.freedesktop.IBus interface.
1554  */
1555 static void
1556 _ibus_get_use_sys_layout (BusIBusImpl           *ibus,
1557                           GVariant              *parameters,
1558                           GDBusMethodInvocation *invocation)
1559 {
1560     g_dbus_method_invocation_return_value (invocation,
1561                     g_variant_new ("(b)", ibus->use_sys_layout));
1562 }
1563
1564 /**
1565  * _ibus_get_use_global_engine:
1566  *
1567  * Implement the "GetUseGlobalEngine" method call of the org.freedesktop.IBus interface.
1568  */
1569 static void
1570 _ibus_get_use_global_engine (BusIBusImpl           *ibus,
1571                              GVariant              *parameters,
1572                              GDBusMethodInvocation *invocation)
1573 {
1574     g_dbus_method_invocation_return_value (invocation,
1575                     g_variant_new ("(b)", ibus->use_global_engine));
1576 }
1577
1578 /**
1579  * _ibus_get_global_engine:
1580  *
1581  * Implement the "GetGlobalEngine" method call of the org.freedesktop.IBus interface.
1582  */
1583 static void
1584 _ibus_get_global_engine (BusIBusImpl           *ibus,
1585                          GVariant              *parameters,
1586                          GDBusMethodInvocation *invocation)
1587 {
1588     IBusEngineDesc *desc = NULL;
1589
1590     do {
1591         if (!ibus->use_global_engine)
1592             break;
1593         BusInputContext *context = ibus->focused_context;
1594         if (context == NULL)
1595             context = ibus->fake_context;
1596
1597         desc = bus_input_context_get_engine_desc (context);
1598
1599         if (desc == NULL)
1600             break;
1601
1602         GVariant *variant = ibus_serializable_serialize ((IBusSerializable *) desc);
1603         g_dbus_method_invocation_return_value (invocation,
1604                                                g_variant_new ("(v)", variant));
1605         return;
1606     } while (0);
1607
1608     g_dbus_method_invocation_return_error (invocation,
1609                     G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1610                     "No global engine.");
1611 }
1612
1613 static void
1614 _ibus_set_global_engine_ready_cb (BusInputContext       *context,
1615                                   GAsyncResult          *res,
1616                                   GDBusMethodInvocation *invocation)
1617 {
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,
1622                                                G_DBUS_ERROR,
1623                                                G_DBUS_ERROR_FAILED,
1624                                                "Set global engine failed.");
1625
1626     }
1627     else {
1628         g_dbus_method_invocation_return_value (invocation, NULL);
1629     }
1630 }
1631
1632 /**
1633  * _ibus_set_global_engine:
1634  *
1635  * Implement the "SetGlobalEngine" method call of the org.freedesktop.IBus interface.
1636  */
1637 static void
1638 _ibus_set_global_engine (BusIBusImpl           *ibus,
1639                          GVariant              *parameters,
1640                          GDBusMethodInvocation *invocation)
1641 {
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.");
1646         return;
1647     }
1648
1649     BusInputContext *context = ibus->focused_context;
1650     if (context == NULL)
1651         context = ibus->fake_context;
1652
1653     const gchar *new_engine_name = NULL;
1654     g_variant_get (parameters, "(&s)", &new_engine_name);
1655     const gchar *old_engine_name = NULL;
1656
1657     BusEngineProxy *engine = bus_input_context_get_engine (context);
1658     if (engine) {
1659         old_engine_name =
1660                 ibus_engine_desc_get_name (bus_engine_proxy_get_desc (engine));
1661     }
1662
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
1665          * original one. */
1666         bus_input_context_enable (context);
1667         g_dbus_method_invocation_return_value (invocation, NULL);
1668         return;
1669     }
1670
1671     IBusEngineDesc *desc = _find_engine_desc_by_name (ibus, new_engine_name);
1672     if (desc == NULL) {
1673         g_dbus_method_invocation_return_error (invocation,
1674                                                G_DBUS_ERROR,
1675                                                G_DBUS_ERROR_FAILED,
1676                                                "Can not find engine %s.",
1677                                                new_engine_name);
1678         return;
1679     }
1680
1681     bus_input_context_set_engine_by_desc (context,
1682                                           desc,
1683                                           g_gdbus_timeout, /* timeout in msec. */
1684                                           NULL, /* we do not cancel the call. */
1685                                           (GAsyncReadyCallback) _ibus_set_global_engine_ready_cb,
1686                                           invocation);
1687 }
1688
1689 /**
1690  * _ibus_is_global_engine_enabled:
1691  *
1692  * Implement the "IsGlobalEngineEnabled" method call of the org.freedesktop.IBus interface.
1693  */
1694 static void
1695 _ibus_is_global_engine_enabled (BusIBusImpl           *ibus,
1696                                 GVariant              *parameters,
1697                                 GDBusMethodInvocation *invocation)
1698 {
1699     gboolean enabled = FALSE;
1700
1701     do {
1702         if (!ibus->use_global_engine)
1703             break;
1704
1705         BusInputContext *context = ibus->focused_context;
1706         if (context == NULL)
1707             context = ibus->fake_context;
1708         if (context == NULL)
1709             break;
1710
1711         enabled = bus_input_context_is_enabled (context);
1712     } while (0);
1713
1714     g_dbus_method_invocation_return_value (invocation,
1715                     g_variant_new ("(b)", enabled));
1716 }
1717
1718 /**
1719  * bus_ibus_impl_service_method_call:
1720  *
1721  * Handle a D-Bus method call whose destination and interface name are both "org.freedesktop.IBus"
1722  */
1723 static void
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)
1732 {
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);
1737         return;
1738     }
1739
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 *);
1744     } methods [] =  {
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 },
1759     };
1760
1761     gint i;
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);
1765             return;
1766         }
1767     }
1768
1769     /* notreached - unknown method calls that are not in the introspection_xml should be handled by the GDBus library. */
1770     g_return_if_reached ();
1771 }
1772
1773 BusIBusImpl *
1774 bus_ibus_impl_get_default (void)
1775 {
1776     static BusIBusImpl *ibus = NULL;
1777
1778     if (ibus == NULL) {
1779         ibus = (BusIBusImpl *) g_object_new (BUS_TYPE_IBUS_IMPL,
1780                                              "object-path", IBUS_PATH_IBUS,
1781                                              NULL);
1782     }
1783     return ibus;
1784 }
1785
1786 BusFactoryProxy *
1787 bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
1788                               const gchar *path)
1789 {
1790     g_assert (BUS_IS_IBUS_IMPL (ibus));
1791
1792     BusFactoryProxy *factory;
1793
1794     factory = (BusFactoryProxy *) g_hash_table_lookup (ibus->factory_dict, path);
1795
1796     return factory;
1797 }
1798
1799 IBusHotkeyProfile *
1800 bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus)
1801 {
1802     g_assert (BUS_IS_IBUS_IMPL (ibus));
1803
1804     return ibus->hotkey_profile;
1805 }
1806
1807 IBusKeymap *
1808 bus_ibus_impl_get_keymap (BusIBusImpl *ibus)
1809 {
1810
1811     g_assert (BUS_IS_IBUS_IMPL (ibus));
1812
1813     return ibus->keymap;
1814 }
1815
1816 BusRegistry *
1817 bus_ibus_impl_get_registry (BusIBusImpl *ibus)
1818 {
1819
1820     g_assert (BUS_IS_IBUS_IMPL (ibus));
1821
1822     return ibus->registry;
1823 }
1824
1825 /**
1826  * bus_ibus_impl_emit_signal:
1827  *
1828  * Send a D-Bus signal to buses (connections) that are listening to the signal.
1829  */
1830 static void
1831 bus_ibus_impl_emit_signal (BusIBusImpl *ibus,
1832                            const gchar *signal_name,
1833                            GVariant    *parameters)
1834 {
1835     static guint32 serial = 0;
1836     GDBusMessage *message = g_dbus_message_new_signal ("/org/freedesktop/IBus",
1837                                                        "org.freedesktop.IBus",
1838                                                        signal_name);
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");
1842     if (parameters)
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);
1846 }
1847
1848 static void
1849 bus_ibus_impl_registry_changed (BusIBusImpl *ibus)
1850 {
1851     bus_ibus_impl_emit_signal (ibus, "RegistryChanged", NULL);
1852 }
1853
1854 static void
1855 bus_ibus_impl_global_engine_changed (BusIBusImpl *ibus)
1856 {
1857     bus_ibus_impl_emit_signal (ibus, "GlobalEngineChanged", NULL);
1858 }
1859
1860 gboolean
1861 bus_ibus_impl_filter_keyboard_shortcuts (BusIBusImpl     *ibus,
1862                                          BusInputContext *context,
1863                                          guint           keyval,
1864                                          guint           modifiers,
1865                                          guint           prev_keyval,
1866                                          guint           prev_modifiers)
1867 {
1868     static GQuark trigger = 0;
1869     static GQuark next = 0;
1870     static GQuark previous = 0;
1871
1872     GQuark event;
1873     GList *engine_list;
1874
1875     if (trigger == 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");
1879     }
1880
1881     /* Try global hotkeys first. */
1882     event = ibus_hotkey_profile_filter_key_event (ibus->hotkey_profile,
1883                                                   keyval,
1884                                                   modifiers,
1885                                                   prev_keyval,
1886                                                   prev_modifiers,
1887                                                   0);
1888
1889     if (event == trigger) {
1890         gboolean enabled = bus_input_context_is_enabled (context);
1891         if (enabled) {
1892             bus_input_context_disable (context);
1893         }
1894         else {
1895             bus_input_context_enable (context);
1896         }
1897         return (enabled != bus_input_context_is_enabled (context));
1898     }
1899     if (event == next) {
1900         if (bus_input_context_is_enabled (context)) {
1901             bus_ibus_impl_context_request_next_engine_in_menu (ibus, context);
1902         }
1903         else {
1904             bus_input_context_enable (context);
1905         }
1906         return TRUE;
1907     }
1908     if (event == previous) {
1909         if (bus_input_context_is_enabled (context)) {
1910             bus_ibus_impl_context_request_previous_engine (ibus, context);
1911         }
1912         else {
1913             bus_input_context_enable (context);
1914         }
1915         return TRUE;
1916     }
1917
1918     if (!ibus->engines_hotkey_profile || !ibus->hotkey_to_engines_map) {
1919         return FALSE;
1920     }
1921
1922     /* Then try engines hotkeys. */
1923     event = ibus_hotkey_profile_filter_key_event (ibus->engines_hotkey_profile,
1924                                                   keyval,
1925                                                   modifiers,
1926                                                   prev_keyval,
1927                                                   prev_modifiers,
1928                                                   0);
1929     if (event == 0) {
1930         return FALSE;
1931     }
1932
1933     engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
1934                                        GUINT_TO_POINTER (event));
1935     if (engine_list) {
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;
1940
1941         g_assert (new_engine_desc);
1942
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;
1951                 break;
1952             }
1953         }
1954
1955         if (current_engine_desc != new_engine_desc) {
1956             bus_ibus_impl_set_context_engine_from_desc (ibus, context, new_engine_desc);
1957         }
1958
1959         return TRUE;
1960     }
1961
1962     return FALSE;
1963 }
1964
1965 /**
1966  * bus_ibus_impl_load_global_engine_name_from_config:
1967  *
1968  * Retrieve the "global_engine" config from the config daemon. Return NULL if the daemon is not ready.
1969  */
1970 static gchar*
1971 bus_ibus_impl_load_global_engine_name_from_config (BusIBusImpl *ibus)
1972 {
1973     g_assert (BUS_IS_IBUS_IMPL (ibus));
1974     if (ibus->config == NULL) {
1975         /* the config component is not started yet. */
1976         return NULL;
1977     }
1978     g_assert (IBUS_IS_CONFIG (ibus->config));
1979
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);
1985     }
1986     return engine_name;
1987 }
1988
1989 /**
1990  * bus_ibus_impl_save_global_engine_name_to_config:
1991  *
1992  * Save the "global_engine" config value on the config daemon. No-op if the daemon is not ready.
1993  */
1994 static void
1995 bus_ibus_impl_save_global_engine_name_to_config (BusIBusImpl *ibus)
1996 {
1997     g_assert (BUS_IS_IBUS_IMPL (ibus));
1998
1999     if (ibus->config &&
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));
2005     }
2006 }
2007
2008 /**
2009  * bus_ibus_impl_load_global_previous_engine_name_from_config:
2010  *
2011  * Retrieve the "global_previous_engine" config from the config daemon. Return NULL if the daemon is not ready.
2012  */
2013 static gchar*
2014 bus_ibus_impl_load_global_previous_engine_name_from_config (BusIBusImpl *ibus)
2015 {
2016     g_assert (BUS_IS_IBUS_IMPL (ibus));
2017     if (ibus->config == NULL) {
2018         /* the config component is not started yet. */
2019         return NULL;
2020     }
2021     g_assert (IBUS_IS_CONFIG (ibus->config));
2022
2023     GVariant *value = ibus_config_get_value (ibus->config, "general", "global_previous_engine");
2024     if (value == NULL)
2025         return NULL;
2026     gchar *engine_name = NULL;
2027     g_variant_get (value, "(s)", &engine_name);
2028     g_variant_unref (value);
2029     return engine_name;
2030 }
2031
2032 /**
2033  * bus_ibus_impl_save_global_previous_engine_name_to_config:
2034  *
2035  * Save the "global_previous_engine" config value on the config daemon. No-op if the daemon is not ready.
2036  */
2037 static void
2038 bus_ibus_impl_save_global_previous_engine_name_to_config (BusIBusImpl *ibus)
2039 {
2040     g_assert (BUS_IS_IBUS_IMPL (ibus));
2041
2042     if (ibus->config &&
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));
2048     }
2049 }
2050
2051 /**
2052  * _add_engine_hotkey:
2053  *
2054  * Check the engine-specific hot key of the engine, and update ibus->engines_hotkey_profile.
2055  */
2056 static void
2057 _add_engine_hotkey (IBusEngineDesc *engine, BusIBusImpl *ibus)
2058 {
2059     const gchar *hotkeys;
2060     gchar **hotkey_list;
2061     gchar **p;
2062     gchar *hotkey;
2063     GList *engine_list;
2064
2065     GQuark event;
2066     guint keyval;
2067     guint modifiers;
2068
2069     if (!engine) {
2070         return;
2071     }
2072
2073     hotkeys = ibus_engine_desc_get_hotkeys (engine);
2074
2075     if (!hotkeys || !*hotkeys) {
2076         return;
2077     }
2078
2079     hotkey_list = g_strsplit_set (hotkeys, ";,", 0);
2080
2081     for (p = hotkey_list; p && *p; ++p) {
2082         hotkey = g_strstrip (*p);
2083         if (!*hotkey || !ibus_key_event_from_string (hotkey, &keyval, &modifiers)) {
2084             continue;
2085         }
2086
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,
2089                                                    keyval, modifiers);
2090         if (event == 0) {
2091             event = g_quark_from_string (hotkey);
2092             ibus_hotkey_profile_add_hotkey (ibus->engines_hotkey_profile,
2093                                             keyval, modifiers, event);
2094         }
2095
2096         engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
2097                                            GUINT_TO_POINTER (event));
2098
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
2101          * here. */
2102         engine_list = g_list_append (engine_list, engine);
2103
2104         /* We need to steal the value before adding it back, otherwise it will
2105          * be destroyed. */
2106         g_hash_table_steal (ibus->hotkey_to_engines_map, GUINT_TO_POINTER (event));
2107
2108         g_hash_table_insert (ibus->hotkey_to_engines_map,
2109                              GUINT_TO_POINTER (event), engine_list);
2110     }
2111
2112     g_strfreev (hotkey_list);
2113 }
2114
2115 /**
2116  * bus_ibus_impl_update_engines_hotkey_profile:
2117  *
2118  * Check engine-specific hot keys of all active engines, and update ibus->engines_hotkey_profile.
2119  */
2120 static void
2121 bus_ibus_impl_update_engines_hotkey_profile (BusIBusImpl *ibus)
2122 {
2123     if (ibus->engines_hotkey_profile) {
2124         g_object_unref (ibus->engines_hotkey_profile);
2125     }
2126
2127     if (ibus->hotkey_to_engines_map) {
2128         g_hash_table_unref (ibus->hotkey_to_engines_map);
2129     }
2130
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);
2134
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);
2137 }
2138
2139 gboolean
2140 bus_ibus_impl_is_use_sys_layout (BusIBusImpl *ibus)
2141 {
2142     g_assert (BUS_IS_IBUS_IMPL (ibus));
2143
2144     return ibus->use_sys_layout;
2145 }
2146
2147 gboolean
2148 bus_ibus_impl_is_embed_preedit_text (BusIBusImpl *ibus)
2149 {
2150     g_assert (BUS_IS_IBUS_IMPL (ibus));
2151
2152     return ibus->embed_preedit_text;
2153 }
2154
2155 BusInputContext *
2156 bus_ibus_impl_get_focused_input_context (BusIBusImpl *ibus)
2157 {
2158     g_assert (BUS_IS_IBUS_IMPL (ibus));
2159
2160     return ibus->focused_context;
2161 }