If the current engine is removed, then switch to another engine automatically.
[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_set_global_engine (BusIBusImpl        *ibus,
160                                                  BusEngineProxy     *engine);
161 static void     bus_ibus_impl_set_global_engine_by_name
162                                                 (BusIBusImpl        *ibus,
163                                                  const gchar        *name);
164 static void     bus_ibus_impl_engines_maybe_removed
165                                                 (BusIBusImpl        *ibus);
166 static void     bus_ibus_impl_registry_changed  (BusIBusImpl        *ibus);
167 static void     bus_ibus_impl_global_engine_changed
168                                                 (BusIBusImpl        *ibus);
169 static void     bus_ibus_impl_set_context_engine_from_desc
170                                                 (BusIBusImpl        *ibus,
171                                                  BusInputContext    *context,
172                                                  IBusEngineDesc     *desc);
173 static gchar   *bus_ibus_impl_load_global_engine_name_from_config
174                                                 (BusIBusImpl        *ibus);
175 static void     bus_ibus_impl_save_global_engine_name_to_config
176                                                 (BusIBusImpl        *ibus);
177
178 static gchar   *bus_ibus_impl_load_global_previous_engine_name_from_config
179                                                 (BusIBusImpl        *ibus);
180 static void     bus_ibus_impl_save_global_previous_engine_name_to_config
181                                                 (BusIBusImpl        *ibus);
182 static void     bus_ibus_impl_update_engines_hotkey_profile
183                                                 (BusIBusImpl        *ibus);
184 static BusInputContext
185                *bus_ibus_impl_create_input_context
186                                                 (BusIBusImpl        *ibus,
187                                                  BusConnection      *connection,
188                                                  const gchar        *client);
189 /* some callback functions */
190 static void     _context_engine_changed_cb      (BusInputContext    *context,
191                                                  BusIBusImpl        *ibus);
192
193 /* The interfaces available in this class, which consists of a list of methods this class implements and
194  * a list of signals this class may emit. Method calls to the interface that are not defined in this XML
195  * will be automatically rejected by the GDBus library (see src/ibusservice.c for details.) */
196 static const gchar introspection_xml[] =
197     "<node>\n"
198     "  <interface name='org.freedesktop.IBus'>\n"
199     "    <method name='GetAddress'>\n"
200     "      <arg direction='out' type='s' name='address' />\n"
201     "    </method>\n"
202     "    <method name='CreateInputContext'>\n"
203     "      <arg direction='in'  type='s' name='client_name' />\n"
204     "      <arg direction='out' type='o' name='object_path' />\n"
205     "    </method>\n"
206     "    <method name='CurrentInputContext'>\n"
207     "      <arg direction='out' type='o' name='object_path' />\n"
208     "    </method>\n"
209     "    <method name='RegisterComponent'>\n"
210     "      <arg direction='in'  type='v' name='component' />\n"
211     "    </method>\n"
212     "    <method name='ListEngines'>\n"
213     "      <arg direction='out' type='av' name='engines' />\n"
214     "    </method>\n"
215     "    <method name='ListActiveEngines'>\n"
216     "      <arg direction='out' type='av' name='engines' />\n"
217     "    </method>\n"
218     "    <method name='Exit'>\n"
219     "      <arg direction='in'  type='b' name='restart' />\n"
220     "    </method>\n"
221     "    <method name='Ping'>\n"
222     "      <arg direction='in'  type='v' name='data' />\n"
223     "      <arg direction='out' type='v' name='data' />\n"
224     "    </method>\n"
225     "    <method name='GetUseSysLayout'>\n"
226     "      <arg direction='out' type='b' name='enabled' />\n"
227     "    </method>\n"
228     "    <method name='GetUseGlobalEngine'>\n"
229     "      <arg direction='out' type='b' name='enabled' />\n"
230     "    </method>\n"
231     "    <method name='GetGlobalEngine'>\n"
232     "      <arg direction='out' type='v' name='desc' />\n"
233     "    </method>\n"
234     "    <method name='SetGlobalEngine'>\n"
235     "      <arg direction='in'  type='s' name='engine_name' />\n"
236     "    </method>\n"
237     "    <method name='IsGlobalEngineEnabled'>\n"
238     "      <arg direction='out' type='b' name='enabled' />\n"
239     "    </method>\n"
240     "    <signal name='RegistryChanged'>\n"
241     "    </signal>\n"
242     "    <signal name='GlobalEngineChanged'>\n"
243     "      <arg type='s' name='engine_name' />\n"
244     "    </signal>\n"
245     "  </interface>\n"
246     "</node>\n";
247
248
249 G_DEFINE_TYPE (BusIBusImpl, bus_ibus_impl, IBUS_TYPE_SERVICE)
250
251 static void
252 bus_ibus_impl_class_init (BusIBusImplClass *class)
253 {
254     IBUS_OBJECT_CLASS (class)->destroy = (IBusObjectDestroyFunc) bus_ibus_impl_destroy;
255
256     /* override the parent class's implementation. */
257     IBUS_SERVICE_CLASS (class)->service_method_call = bus_ibus_impl_service_method_call;
258     /* register the xml so that bus_ibus_impl_service_method_call will be called on a method call defined in the xml (e.g. 'GetAddress'.) */
259     ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml);
260 }
261
262 /**
263  * _panel_destroy_cb:
264  *
265  * A callback function which is called when (1) the connection to the panel process is terminated,
266  * or (2) ibus_proxy_destroy (ibus->panel); is called. See src/ibusproxy.c for details.
267  */
268 static void
269 _panel_destroy_cb (BusPanelProxy *panel,
270                    BusIBusImpl   *ibus)
271 {
272     g_assert (BUS_IS_PANEL_PROXY (panel));
273     g_assert (BUS_IS_IBUS_IMPL (ibus));
274
275     g_return_if_fail (ibus->panel == panel);
276
277     ibus->panel = NULL;
278     g_object_unref (panel);
279 }
280
281 static void
282 bus_ibus_impl_set_hotkey (BusIBusImpl *ibus,
283                           GQuark       hotkey,
284                           GVariant    *value)
285 {
286     g_assert (BUS_IS_IBUS_IMPL (ibus));
287
288     ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
289
290     if (value == NULL) {
291         return;
292     }
293
294     GVariantIter iter;
295     g_variant_iter_init (&iter, value);
296     const gchar *str = NULL;
297     while (g_variant_iter_loop (&iter,"&s", &str)) {
298        ibus_hotkey_profile_add_hotkey_from_string (ibus->hotkey_profile,
299                                                    str,
300                                                    hotkey);
301     }
302
303 }
304
305 /**
306  * bus_ibus_impl_set_trigger:
307  *
308  * A function to be called when "trigger" config is updated. If the value is NULL, the default trigger (Ctrl+space) is set.
309  */
310 static void
311 bus_ibus_impl_set_trigger (BusIBusImpl *ibus,
312                            GVariant    *value)
313 {
314     GQuark hotkey = g_quark_from_static_string ("trigger");
315     if (value != NULL) {
316         bus_ibus_impl_set_hotkey (ibus, hotkey, value);
317     }
318 #ifndef OS_CHROMEOS
319     else {
320         /* set default trigger */
321         ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
322         ibus_hotkey_profile_add_hotkey (ibus->hotkey_profile,
323                                         IBUS_space,
324                                         IBUS_CONTROL_MASK,
325                                         hotkey);
326     }
327 #endif
328 }
329
330 /**
331  * bus_ibus_impl_set_enable_unconditional:
332  *
333  * A function to be called when "enable_unconditional" config is updated.
334  */
335 static void
336 bus_ibus_impl_set_enable_unconditional (BusIBusImpl *ibus,
337                                         GVariant    *value)
338 {
339     GQuark hotkey = g_quark_from_static_string ("enable-unconditional");
340     bus_ibus_impl_set_hotkey (ibus, hotkey, value);
341 }
342
343 /**
344  * bus_ibus_impl_set_disable_unconditional:
345  *
346  * A function to be called when "disable_unconditional" config is updated.
347  */
348 static void
349 bus_ibus_impl_set_disable_unconditional (BusIBusImpl *ibus,
350                                          GVariant    *value)
351 {
352     GQuark hotkey = g_quark_from_static_string ("disable-unconditional");
353     bus_ibus_impl_set_hotkey (ibus, hotkey, value);
354 }
355
356 /**
357  * bus_ibus_impl_set_next_engine_in_menu:
358  *
359  * A function to be called when "next_engine_in_menu" config is updated.
360  */
361 static void
362 bus_ibus_impl_set_next_engine_in_menu (BusIBusImpl *ibus,
363                                        GVariant    *value)
364 {
365     GQuark hotkey = g_quark_from_static_string ("next-engine-in-menu");
366     bus_ibus_impl_set_hotkey (ibus, hotkey, value);
367 }
368
369 /**
370  * bus_ibus_impl_set_previous_engine:
371  *
372  * A function to be called when "previous_engine" config is updated.
373  */
374 static void
375 bus_ibus_impl_set_previous_engine (BusIBusImpl *ibus,
376                                    GVariant    *value)
377 {
378     GQuark hotkey = g_quark_from_static_string ("previous-engine");
379     bus_ibus_impl_set_hotkey (ibus, hotkey, value);
380 }
381
382 /**
383  * bus_ibus_impl_set_preload_engines:
384  *
385  * A function to be called when "preload_engines" config is updated.
386  */
387 static void
388 bus_ibus_impl_set_preload_engines (BusIBusImpl *ibus,
389                                    GVariant    *value)
390 {
391     GList *engine_list = NULL;
392
393     g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
394     g_list_free (ibus->engine_list);
395
396     if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_ARRAY) {
397         GVariantIter iter;
398         g_variant_iter_init (&iter, value);
399         const gchar *engine_name = NULL;
400         while (g_variant_iter_loop (&iter, "&s", &engine_name)) {
401             IBusEngineDesc *engine = bus_registry_find_engine_by_name (ibus->registry, engine_name);
402             if (engine == NULL || g_list_find (engine_list, engine) != NULL)
403                 continue;
404             engine_list = g_list_append (engine_list, engine);
405         }
406     }
407
408     g_list_foreach (engine_list, (GFunc) g_object_ref, NULL);
409     ibus->engine_list = engine_list;
410
411     if (ibus->engine_list) {
412         BusComponent *component = bus_component_from_engine_desc ((IBusEngineDesc *) ibus->engine_list->data);
413         if (component && !bus_component_is_running (component)) {
414             bus_component_start (component, g_verbose);
415         }
416     }
417
418     bus_ibus_impl_engines_maybe_removed (ibus);
419     bus_ibus_impl_update_engines_hotkey_profile (ibus);
420 }
421
422 /**
423  * bus_ibus_impl_set_use_sys_layout:
424  *
425  * A function to be called when "use_system_keyboard_layout" config is updated.
426  */
427 static void
428 bus_ibus_impl_set_use_sys_layout (BusIBusImpl *ibus,
429                                   GVariant    *value)
430 {
431     if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
432         ibus->use_sys_layout = g_variant_get_boolean (value);
433     }
434 }
435
436 /**
437  * bus_ibus_impl_set_embed_preedit_text:
438  *
439  * A function to be called when "use_embed_preedit_text" config is updated.
440  */
441 static void
442 bus_ibus_impl_set_embed_preedit_text (BusIBusImpl *ibus,
443                                       GVariant    *value)
444 {
445     if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
446         ibus->embed_preedit_text = g_variant_get_boolean (value);
447     }
448 }
449
450 /**
451  * bus_ibus_impl_set_enable_by_default:
452  *
453  * A function to be called when "enable_by_default" config is updated.
454  */
455 static void
456 bus_ibus_impl_set_enable_by_default (BusIBusImpl *ibus,
457                                      GVariant    *value)
458 {
459     if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
460         ibus->enable_by_default = g_variant_get_boolean (value);
461     }
462 }
463
464 /**
465  * bus_ibus_impl_set_use_global_engine:
466  *
467  * A function to be called when "use_global_engine" config is updated.
468  */
469 static void
470 bus_ibus_impl_set_use_global_engine (BusIBusImpl *ibus,
471                                      GVariant    *value)
472 {
473     if (value == NULL || g_variant_classify (value) != G_VARIANT_CLASS_BOOLEAN)
474         return;
475
476     gboolean new_value = g_variant_get_boolean (value);
477     if (ibus->use_global_engine == new_value)
478         return;
479
480     if (new_value) {
481         /* turn on use_global_engine option */
482         ibus->use_global_engine = TRUE;
483         if (ibus->panel && ibus->focused_context == NULL) {
484             bus_panel_proxy_focus_in (ibus->panel, ibus->fake_context);
485         }
486     }
487     else {
488         /* turn off use_global_engine option */
489         ibus->use_global_engine = FALSE;
490
491         /* if fake context has the focus, we should focus out it */
492         if (ibus->panel && ibus->focused_context == NULL) {
493             bus_panel_proxy_focus_out (ibus->panel, ibus->fake_context);
494         }
495         /* remove engine in fake context */
496         bus_input_context_set_engine (ibus->fake_context, NULL);
497     }
498 }
499
500 #ifndef OS_CHROMEOS
501 static gint
502 _engine_desc_cmp (IBusEngineDesc *desc1,
503                   IBusEngineDesc *desc2)
504 {
505     return - ((gint) ibus_engine_desc_get_rank (desc1)) +
506               ((gint) ibus_engine_desc_get_rank (desc2));
507 }
508 #endif
509
510 /**
511  * bus_ibus_impl_set_default_preload_engines:
512  *
513  * If the "preload_engines" config variable is not set yet, set the default value which is determined based on a current locale.
514  */
515 static void
516 bus_ibus_impl_set_default_preload_engines (BusIBusImpl *ibus)
517 {
518 #ifndef OS_CHROMEOS
519     g_assert (BUS_IS_IBUS_IMPL (ibus));
520
521     static gboolean done = FALSE;
522
523     if (done || ibus->config == NULL) {
524         return;
525     }
526
527     GVariant *variant = ibus_config_get_value (ibus->config, "general", "preload_engines");
528     if (variant != NULL) {
529         done = TRUE;
530         g_variant_unref (variant);
531         return;
532     }
533
534     done = TRUE;
535
536     /* The setlocale call first checks LC_ALL. If it's not available, checks
537      * LC_CTYPE. If it's also not available, checks LANG. */
538     gchar *lang = g_strdup (setlocale (LC_CTYPE, NULL));
539     if (lang == NULL) {
540         return;
541     }
542
543     gchar *p = index (lang, '.');
544     if (p) {
545         *p = '\0';
546     }
547
548     GList *engines = bus_registry_get_engines_by_language (ibus->registry, lang);
549     if (engines == NULL) {
550         p = index (lang, '_');
551         if (p) {
552             *p = '\0';
553             engines = bus_registry_get_engines_by_language (ibus->registry, lang);
554         }
555     }
556     g_free (lang);
557
558     /* sort engines by rank */
559     engines = g_list_sort (engines, (GCompareFunc) _engine_desc_cmp);
560
561     GVariantBuilder builder;
562     g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
563     GList *list;
564     for (list = engines; list != NULL; list = list->next) {
565         IBusEngineDesc *desc = (IBusEngineDesc *) list->data;
566         /* ignore engines with rank <= 0 */
567         if (ibus_engine_desc_get_rank (desc) > 0)
568             g_variant_builder_add (&builder, "s", ibus_engine_desc_get_name (desc));
569     }
570
571     GVariant *value = g_variant_builder_end (&builder);
572     if (value != NULL) {
573         if (g_variant_n_children (value) > 0) {
574             ibus_config_set_value (ibus->config,
575                                    "general", "preload_engines", value);
576         } else {
577             /* We don't update preload_engines with an empty string for safety.
578              * Just unref the floating value. */
579             g_variant_unref (value);
580         }
581     }
582     g_list_free (engines);
583 #endif
584 }
585
586 /* The list of config entries that are related to ibus-daemon. */
587 const static struct {
588     gchar *section;
589     gchar *key;
590     void (*func) (BusIBusImpl *, GVariant *);
591 } bus_ibus_impl_config_items [] = {
592     { "general/hotkey", "trigger",               bus_ibus_impl_set_trigger },
593     { "general/hotkey", "enable_unconditional",  bus_ibus_impl_set_enable_unconditional },
594     { "general/hotkey", "disable_unconditional", bus_ibus_impl_set_disable_unconditional },
595     { "general/hotkey", "next_engine_in_menu",   bus_ibus_impl_set_next_engine_in_menu },
596     { "general/hotkey", "previous_engine",       bus_ibus_impl_set_previous_engine },
597     { "general", "preload_engines",              bus_ibus_impl_set_preload_engines },
598     { "general", "use_system_keyboard_layout",   bus_ibus_impl_set_use_sys_layout },
599     { "general", "use_global_engine",            bus_ibus_impl_set_use_global_engine },
600     { "general", "embed_preedit_text",           bus_ibus_impl_set_embed_preedit_text },
601     { "general", "enable_by_default",            bus_ibus_impl_set_enable_by_default },
602 };
603
604 /**
605  * bus_ibus_impl_reload_config
606  *
607  * Read config entries (e.g. preload_engines) from the config daemon.
608  */
609 static void
610 bus_ibus_impl_reload_config (BusIBusImpl *ibus)
611 {
612     g_assert (BUS_IS_IBUS_IMPL (ibus));
613
614     gint i;
615     for (i = 0; i < G_N_ELEMENTS (bus_ibus_impl_config_items); i++) {
616         GVariant *variant = NULL;
617         if (ibus->config != NULL)
618             variant = ibus_config_get_value (ibus->config,
619                             bus_ibus_impl_config_items[i].section,
620                             bus_ibus_impl_config_items[i].key);
621         bus_ibus_impl_config_items[i].func (ibus, variant); /* variant could be NULL if the deamon is not ready yet. */
622         if (variant) g_variant_unref (variant);
623     }
624 }
625
626 /**
627  * _config_value_changed_cb:
628  *
629  * A callback function to be called when the "ValueChanged" D-Bus signal is sent from the config daemon.
630  */
631 static void
632 _config_value_changed_cb (IBusConfig  *config,
633                           gchar       *section,
634                           gchar       *key,
635                           GVariant    *value,
636                           BusIBusImpl *ibus)
637 {
638     g_assert (IBUS_IS_CONFIG (config));
639     g_assert (section);
640     g_assert (key);
641     g_assert (value);
642     g_assert (BUS_IS_IBUS_IMPL (ibus));
643
644     gint i;
645     for (i = 0; i < G_N_ELEMENTS (bus_ibus_impl_config_items); i++) {
646         if (g_strcmp0 (bus_ibus_impl_config_items[i].section, section) == 0 &&
647             g_strcmp0 (bus_ibus_impl_config_items[i].key, key) == 0) {
648             bus_ibus_impl_config_items[i].func (ibus, value);
649             break;
650         }
651     }
652 }
653
654 /**
655  * _config_destroy_cb:
656  *
657  * A callback function which is called when (1) the connection to the config process is terminated,
658  * or (2) ibus_proxy_destroy (ibus->config); is called. See src/ibusproxy.c for details.
659  */
660 static void
661 _config_destroy_cb (IBusConfig  *config,
662                     BusIBusImpl *ibus)
663 {
664     g_assert (IBUS_IS_CONFIG (config));
665     g_assert (BUS_IS_IBUS_IMPL (ibus));
666
667     g_assert (ibus->config == config);
668
669     g_object_unref (ibus->config);
670     ibus->config = NULL;
671 }
672
673 static void
674 _registry_changed_cb (BusRegistry *registry,
675                       BusIBusImpl *ibus)
676 {
677     bus_ibus_impl_registry_changed (ibus);
678 }
679
680 /*
681  * _dbus_name_owner_changed_cb:
682  *
683  * A callback function to be called when the name-owner-changed signal is sent to the dbus object.
684  * This usually means a client (e.g. a panel/config/engine process or an application) is connected/disconnected to/from the bus.
685  */
686 static void
687 _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
688                              const gchar *name,
689                              const gchar *old_name,
690                              const gchar *new_name,
691                              BusIBusImpl *ibus)
692 {
693     g_assert (BUS_IS_DBUS_IMPL (dbus));
694     g_assert (name != NULL);
695     g_assert (old_name != NULL);
696     g_assert (new_name != NULL);
697     g_assert (BUS_IS_IBUS_IMPL (ibus));
698
699     if (g_strcmp0 (name, IBUS_SERVICE_PANEL) == 0) {
700         if (g_strcmp0 (new_name, "") != 0) {
701             /* a Panel process is started. */
702             BusConnection *connection;
703
704             if (ibus->panel != NULL) {
705                 ibus_proxy_destroy ((IBusProxy *) ibus->panel);
706                 /* panel should be NULL after destroy. See _panel_destroy_cb for details. */
707                 g_assert (ibus->panel == NULL);
708             }
709
710             connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
711             g_return_if_fail (connection != NULL);
712
713             ibus->panel = bus_panel_proxy_new (connection);
714
715             g_signal_connect (ibus->panel,
716                               "destroy",
717                               G_CALLBACK (_panel_destroy_cb),
718                               ibus);
719
720             if (ibus->focused_context != NULL) {
721                 bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context);
722             }
723             else if (ibus->use_global_engine) {
724                 bus_panel_proxy_focus_in (ibus->panel, ibus->fake_context);
725             }
726         }
727     }
728     else if (g_strcmp0 (name, IBUS_SERVICE_CONFIG) == 0) {
729         if (g_strcmp0 (new_name, "") != 0) {
730             /* a config process is started. */
731             BusConnection *connection;
732
733             if (ibus->config != NULL) {
734                 ibus_proxy_destroy ((IBusProxy *) ibus->config);
735                 /* config should be NULL after destroy. See _config_destroy_cb for details. */
736                 g_assert (ibus->config == NULL);
737             }
738
739             /* get a connection between ibus-daemon and the config daemon. */
740             connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
741             g_return_if_fail (connection != NULL);
742
743             ibus->config = g_initable_new (IBUS_TYPE_CONFIG,
744                                            NULL,
745                                            NULL,
746                                            /* The following properties are necessary to initialize GDBusProxy object
747                                             * which is a parent of the config object. */
748                                            "g-connection",      bus_connection_get_dbus_connection (connection),
749                                            "g-flags",           G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
750                                            "g-interface-name",  IBUS_INTERFACE_CONFIG,
751                                            "g-object-path",     IBUS_PATH_CONFIG,
752                                            "g-default-timeout", g_gdbus_timeout,
753                                            NULL);
754
755             g_signal_connect (ibus->config,
756                               "value-changed",
757                               G_CALLBACK (_config_value_changed_cb),
758                               ibus);
759
760             g_signal_connect (ibus->config,
761                               "destroy",
762                               G_CALLBACK (_config_destroy_cb),
763                               ibus);
764
765             bus_ibus_impl_set_default_preload_engines (ibus);
766             bus_ibus_impl_reload_config (ibus);
767         }
768     }
769
770     bus_registry_name_owner_changed (ibus->registry, name, old_name, new_name);
771 }
772
773 /**
774  * bus_ibus_impl_init:
775  *
776  * The constructor of BusIBusImpl. Initialize all member variables of a BusIBusImpl object.
777  */
778 static void
779 bus_ibus_impl_init (BusIBusImpl *ibus)
780 {
781     ibus->factory_dict = g_hash_table_new_full (
782                             g_str_hash,
783                             g_str_equal,
784                             NULL,
785                             (GDestroyNotify) g_object_unref);
786
787     ibus->fake_context = bus_input_context_new (NULL, "fake");
788     g_object_ref_sink (ibus->fake_context);
789     bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
790                                    (IBusService *) ibus->fake_context);
791     bus_input_context_set_capabilities (ibus->fake_context,
792                                         IBUS_CAP_PREEDIT_TEXT |
793                                         IBUS_CAP_FOCUS |
794                                         IBUS_CAP_SURROUNDING_TEXT);
795     g_signal_connect (ibus->fake_context,
796                       "engine-changed",
797                       G_CALLBACK (_context_engine_changed_cb),
798                       ibus);
799     bus_input_context_focus_in (ibus->fake_context);
800
801     ibus->engine_list = NULL;
802     ibus->register_engine_list = NULL;
803     ibus->contexts = NULL;
804     ibus->focused_context = NULL;
805     ibus->panel = NULL;
806     ibus->config = NULL;
807
808     ibus->registry = bus_registry_new ();
809
810     g_signal_connect (ibus->registry,
811                       "changed",
812                       G_CALLBACK (_registry_changed_cb),
813                       ibus);
814 #ifdef G_THREADS_ENABLED
815     extern gint g_monitor_timeout;
816     if (g_monitor_timeout != 0) {
817         /* Start the monitor of registry changes. */
818         bus_registry_start_monitor_changes (ibus->registry);
819     }
820 #endif
821
822     ibus->hotkey_profile = ibus_hotkey_profile_new ();
823     ibus->keymap = ibus_keymap_get ("us");
824
825     ibus->use_sys_layout = FALSE;
826     ibus->embed_preedit_text = TRUE;
827     ibus->enable_by_default = FALSE;
828     ibus->use_global_engine = FALSE;
829     ibus->global_engine_name = NULL;
830     ibus->global_previous_engine_name = NULL;
831
832     ibus->engines_hotkey_profile = NULL;
833     ibus->hotkey_to_engines_map = NULL;
834
835     bus_ibus_impl_reload_config (ibus);
836
837     g_signal_connect (BUS_DEFAULT_DBUS,
838                       "name-owner-changed",
839                       G_CALLBACK (_dbus_name_owner_changed_cb),
840                       ibus);
841 }
842
843 /**
844  * bus_ibus_impl_destroy:
845  *
846  * The destructor of BusIBusImpl.
847  */
848 static void
849 bus_ibus_impl_destroy (BusIBusImpl *ibus)
850 {
851     pid_t pid;
852     glong timeout;
853     gint status;
854     gboolean flag;
855
856     bus_registry_stop_all_components (ibus->registry);
857
858     pid = 0;
859     timeout = 0;
860     flag = FALSE;
861     while (1) {
862         while ((pid = waitpid (0, &status, WNOHANG)) > 0);
863
864         if (pid == -1) { /* all children finished */
865             break;
866         }
867         if (pid == 0) { /* no child status changed */
868             g_usleep (1000);
869             timeout += 1000;
870             if (timeout >= G_USEC_PER_SEC) {
871                 if (flag == FALSE) {
872                     gpointer old;
873                     old = signal (SIGTERM, SIG_IGN);
874                     /* send TERM signal to the whole process group (i.e. engines, panel, and config daemon.) */
875                     kill (-getpid (), SIGTERM);
876                     signal (SIGTERM, old);
877                     flag = TRUE;
878                 }
879                 else {
880                     g_warning ("Not every child processes exited!");
881                     break;
882                 }
883             }
884         }
885     }
886
887     g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
888     g_list_free (ibus->engine_list);
889     ibus->engine_list = NULL;
890
891     g_list_foreach (ibus->register_engine_list, (GFunc) g_object_unref, NULL);
892     g_list_free (ibus->register_engine_list);
893     ibus->register_engine_list = NULL;
894
895     if (ibus->factory_dict != NULL) {
896         g_hash_table_destroy (ibus->factory_dict);
897         ibus->factory_dict = NULL;
898     }
899
900     if (ibus->hotkey_profile != NULL) {
901         g_object_unref (ibus->hotkey_profile);
902         ibus->hotkey_profile = NULL;
903     }
904
905     if (ibus->keymap != NULL) {
906         g_object_unref (ibus->keymap);
907         ibus->keymap = NULL;
908     }
909
910     g_free (ibus->global_engine_name);
911     ibus->global_engine_name = NULL;
912
913     g_free (ibus->global_previous_engine_name);
914     ibus->global_previous_engine_name = NULL;
915
916     if (ibus->engines_hotkey_profile != NULL) {
917         g_object_unref (ibus->engines_hotkey_profile);
918         ibus->engines_hotkey_profile = NULL;
919     }
920
921     if (ibus->hotkey_to_engines_map) {
922         g_hash_table_unref (ibus->hotkey_to_engines_map);
923         ibus->hotkey_to_engines_map = NULL;
924     }
925
926     if (ibus->fake_context) {
927         g_object_unref (ibus->fake_context);
928         ibus->fake_context = NULL;
929     }
930
931     bus_server_quit ();
932     IBUS_OBJECT_CLASS (bus_ibus_impl_parent_class)->destroy (IBUS_OBJECT (ibus));
933 }
934
935 /**
936  * _ibus_get_address:
937  *
938  * Implement the "GetAddress" method call of the org.freedesktop.IBus interface.
939  */
940 static void
941 _ibus_get_address (BusIBusImpl           *ibus,
942                    GVariant              *parameters,
943                    GDBusMethodInvocation *invocation)
944 {
945     g_dbus_method_invocation_return_value (invocation,
946                                            g_variant_new ("(s)", bus_server_get_address ()));
947 }
948
949 static IBusEngineDesc *
950 _find_engine_desc_by_name (BusIBusImpl *ibus,
951                            const gchar *engine_name)
952 {
953     IBusEngineDesc *desc = NULL;
954     GList *p;
955
956     /* find engine in registered engine list */
957     for (p = ibus->register_engine_list; p != NULL; p = p->next) {
958         desc = (IBusEngineDesc *) p->data;
959         if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
960             return desc;
961     }
962
963     /* find engine in preload engine list */
964     for (p = ibus->engine_list; p != NULL; p = p->next) {
965         desc = (IBusEngineDesc *) p->data;
966         if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
967             return desc;
968     }
969
970     return NULL;
971 }
972
973 /**
974  * _context_request_engine_cb:
975  *
976  * A callback function to be called when the "request-engine" signal is sent to the context.
977  */
978 static void
979 _context_request_engine_cb (BusInputContext *context,
980                             const gchar     *engine_name,
981                             BusIBusImpl     *ibus)
982 {
983     IBusEngineDesc *desc = NULL;
984
985     /* context should has focus before request an engine */
986     g_return_if_fail (bus_input_context_has_focus (context) ||
987                       context == ibus->focused_context);
988
989     if (engine_name != NULL && engine_name[0] != '\0') {
990         /* request engine by name */
991         desc = _find_engine_desc_by_name (ibus, engine_name);
992         g_return_if_fail (desc != NULL);
993     }
994     else {
995         /* Use global engine if possible. */
996         if (ibus->use_global_engine) {
997             gchar *name = g_strdup (ibus->global_engine_name);
998             if (name == NULL) {
999                 name = bus_ibus_impl_load_global_engine_name_from_config (ibus);
1000             }
1001             if (name) {
1002                 desc = _find_engine_desc_by_name (ibus, name);
1003                 g_free (name);
1004             }
1005         }
1006         /* request default engine */
1007         if (!desc) {
1008             if (ibus->register_engine_list) {
1009                 desc = (IBusEngineDesc *) ibus->register_engine_list->data;
1010             }
1011             else if (ibus->engine_list) {
1012                 desc = (IBusEngineDesc *) ibus->engine_list->data;
1013             }
1014         }
1015         if (!desc) {
1016             /* no engine is available. the user hasn't ran ibus-setup yet and
1017              * the bus_ibus_impl_set_default_preload_engines() function could
1018              * not find any default engines. another possiblity is that the
1019              * user hasn't installed an engine yet? just give up. */
1020             g_warning ("No engine is available. Run ibus-setup first.");
1021             return;
1022         }
1023     }
1024
1025     bus_ibus_impl_set_context_engine_from_desc (ibus, context, desc);
1026 }
1027
1028 /**
1029  * bus_ibus_impl_context_request_next_engine_in_menu:
1030  *
1031  * Process the "next_engine_in_menu" hotkey.
1032  */
1033 static void
1034 bus_ibus_impl_context_request_next_engine_in_menu (BusIBusImpl     *ibus,
1035                                                    BusInputContext *context)
1036 {
1037     BusEngineProxy *engine;
1038     IBusEngineDesc *desc;
1039     IBusEngineDesc *next_desc = NULL;
1040     GList *p;
1041
1042     engine = bus_input_context_get_engine (context);
1043     if (engine == NULL) {
1044         _context_request_engine_cb (context, NULL, ibus);
1045         return;
1046     }
1047
1048     desc = bus_engine_proxy_get_desc (engine);
1049
1050     p = g_list_find (ibus->register_engine_list, desc);
1051     if (p != NULL) {
1052         p = p->next;
1053     }
1054     if (p == NULL) {
1055         p = g_list_find (ibus->engine_list, desc);
1056         if (p != NULL) {
1057             p = p->next;
1058         }
1059     }
1060
1061     if (p != NULL) {
1062         next_desc = (IBusEngineDesc*) p->data;
1063     }
1064     else {
1065         if (ibus->register_engine_list) {
1066             next_desc = (IBusEngineDesc *) ibus->register_engine_list->data;
1067         }
1068         else if (ibus->engine_list) {
1069             next_desc = (IBusEngineDesc *) ibus->engine_list->data;
1070         }
1071     }
1072
1073     bus_ibus_impl_set_context_engine_from_desc (ibus, context, next_desc);
1074 }
1075
1076 /**
1077  * bus_ibus_impl_context_request_previous_engine:
1078  *
1079  * Process the "previous_engine" hotkey.
1080  */
1081 static void
1082 bus_ibus_impl_context_request_previous_engine (BusIBusImpl     *ibus,
1083                                                BusInputContext *context)
1084 {
1085     gchar *engine_name = NULL;
1086     if (!ibus->use_global_engine) {
1087         engine_name = (gchar *) g_object_get_data (G_OBJECT (context), "previous-engine-name");
1088     }
1089     else {
1090         if (!ibus->global_previous_engine_name) {
1091             ibus->global_previous_engine_name = bus_ibus_impl_load_global_previous_engine_name_from_config (ibus);
1092         }
1093         engine_name = ibus->global_previous_engine_name;
1094     }
1095
1096     /*
1097      * If the previous engine name is not found, switch to the next engine
1098      * in the menu. This behavior is better than doing nothing.
1099      */
1100     if (!engine_name) {
1101         bus_ibus_impl_context_request_next_engine_in_menu (ibus, context);
1102         return;
1103     }
1104     _context_request_engine_cb (context, engine_name, ibus);
1105 }
1106
1107 static void
1108 bus_ibus_impl_set_context_engine_from_desc (BusIBusImpl     *ibus,
1109                                             BusInputContext *context,
1110                                             IBusEngineDesc  *desc)
1111 {
1112     bus_input_context_set_engine_by_desc (context,
1113                                           desc,
1114                                           g_gdbus_timeout, /* timeout in msec. */
1115                                           NULL, /* we do not cancel the call. */
1116                                           NULL, /* use the default callback function. */
1117                                           NULL);
1118 }
1119
1120 /**
1121  * bus_ibus_impl_set_focused_context:
1122  *
1123  * Set the current focused context.
1124  */
1125 static void
1126 bus_ibus_impl_set_focused_context (BusIBusImpl     *ibus,
1127                                    BusInputContext *context)
1128 {
1129     g_assert (BUS_IS_IBUS_IMPL (ibus));
1130     g_assert (context == NULL || BUS_IS_INPUT_CONTEXT (context));
1131     g_assert (context == NULL || bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS);
1132
1133     /* Do noting if it is not focused context. */
1134     if (ibus->focused_context == context) {
1135         return;
1136     }
1137
1138     BusEngineProxy *engine = NULL;
1139
1140     if (ibus->focused_context) {
1141         if (ibus->use_global_engine) {
1142             /* dettach engine from the focused context */
1143             engine = bus_input_context_get_engine (ibus->focused_context);
1144             if (engine) {
1145                 g_object_ref (engine);
1146                 bus_input_context_set_engine (ibus->focused_context, NULL);
1147             }
1148         }
1149
1150         if (ibus->panel != NULL)
1151             bus_panel_proxy_focus_out (ibus->panel, ibus->focused_context);
1152
1153         g_object_unref (ibus->focused_context);
1154         ibus->focused_context = NULL;
1155     }
1156
1157     if (context == NULL && ibus->use_global_engine) {
1158         context = ibus->fake_context;
1159     }
1160
1161     if (context) {
1162         ibus->focused_context = (BusInputContext *) g_object_ref (context);
1163         /* attach engine to the focused context */
1164         if (engine != NULL) {
1165             bus_input_context_set_engine (context, engine);
1166             if (bus_engine_proxy_is_enabled (engine))
1167                 bus_input_context_enable (context);
1168             g_object_unref (engine);
1169         }
1170
1171         if (ibus->panel != NULL)
1172             bus_panel_proxy_focus_in (ibus->panel, context);
1173     }
1174 }
1175
1176 static void
1177 bus_ibus_impl_set_global_engine (BusIBusImpl    *ibus,
1178                                  BusEngineProxy *engine)
1179 {
1180     BusInputContext *context = NULL;
1181
1182     if (!ibus->use_global_engine)
1183         return;
1184
1185     if (ibus->focused_context) {
1186         bus_input_context_set_engine (ibus->focused_context, engine);
1187     } else if (ibus->fake_context) {
1188         bus_input_context_set_engine (ibus->fake_context, engine);
1189     }
1190 }
1191
1192 static void
1193 bus_ibus_impl_set_global_engine_by_name (BusIBusImpl *ibus,
1194                                          const gchar *name)
1195 {
1196     gchar *old_engine_name = NULL;
1197
1198     if (!ibus->use_global_engine)
1199         return;
1200
1201     if (g_strcmp0 (name, ibus->global_engine_name) == 0) {
1202         /* If the user requested the same global engine, then we just enable the
1203          * original one. */
1204         if (ibus->focused_context) {
1205             bus_input_context_enable (ibus->focused_context);
1206         }
1207         else if (ibus->fake_context) {
1208             bus_input_context_enable (ibus->fake_context);
1209         }
1210         return;
1211     }
1212
1213     /* If there is a focused input context, then we just change the engine of
1214      * the focused context, which will then change the global engine
1215      * automatically. Otherwise, we need to change the global engine directly.
1216      */
1217     if (ibus->focused_context) {
1218         _context_request_engine_cb (ibus->focused_context, name, ibus);
1219     }
1220     else if (ibus->fake_context) {
1221         _context_request_engine_cb (ibus->fake_context, name, ibus);
1222     }
1223 }
1224
1225 static void
1226 bus_ibus_impl_engines_maybe_removed (BusIBusImpl *ibus)
1227 {
1228     const gchar *old_engine_name = NULL;
1229     GList *engine_list = NULL;
1230
1231     if (!ibus->use_global_engine || ibus->global_engine_name == NULL)
1232         return;
1233
1234     /* The current global engine is not removed, so do nothing. */
1235     if (_find_engine_desc_by_name (ibus, ibus->global_engine_name))
1236         return;
1237
1238     /* If the previous engine is available, then just switch to it. */
1239     if (ibus->global_previous_engine_name &&
1240         _find_engine_desc_by_name (ibus, ibus->global_previous_engine_name)) {
1241         bus_ibus_impl_set_global_engine_by_name (
1242             ibus, ibus->global_previous_engine_name);
1243         return;
1244     }
1245
1246     /* Just choose one in the list. */
1247     engine_list = ibus->register_engine_list;
1248     if (!engine_list)
1249         engine_list = ibus->engine_list;
1250
1251     if (engine_list) {
1252         IBusEngineDesc *engine_desc = (IBusEngineDesc *)engine_list->data;
1253         bus_ibus_impl_set_global_engine_by_name (ibus,
1254                         ibus_engine_desc_get_name (engine_desc));
1255         return;
1256     }
1257
1258     /* No engine available? Just disable global engine. */
1259     bus_ibus_impl_set_global_engine (ibus, NULL);
1260 }
1261
1262 /**
1263  * _context_engine_changed_cb:
1264  *
1265  * A callback function to be called when the "engine-changed" signal is sent to the context.
1266  * Update global engine as well if necessary.
1267  */
1268 static void
1269 _context_engine_changed_cb (BusInputContext *context,
1270                             BusIBusImpl     *ibus)
1271 {
1272     if (!ibus->use_global_engine)
1273         return;
1274
1275     if ((context == ibus->focused_context) ||
1276         (ibus->focused_context == NULL && context == ibus->fake_context)) {
1277         BusEngineProxy *engine = bus_input_context_get_engine (context);
1278         if (engine != NULL) {
1279             /* only set global engine if engine is not NULL */
1280             const gchar *name = ibus_engine_desc_get_name (bus_engine_proxy_get_desc (engine));
1281             if (g_strcmp0 (name, ibus->global_engine_name) == 0)
1282                 return;
1283             g_free (ibus->global_previous_engine_name);
1284             ibus->global_previous_engine_name = ibus->global_engine_name;
1285             ibus->global_engine_name = g_strdup (name);
1286             /* save changes */
1287             bus_ibus_impl_save_global_engine_name_to_config (ibus);
1288             bus_ibus_impl_save_global_previous_engine_name_to_config (ibus);
1289             bus_ibus_impl_global_engine_changed (ibus);
1290         }
1291     }
1292 }
1293
1294 /**
1295  * _context_focus_in_cb:
1296  *
1297  * A callback function to be called when the "focus-in" signal is sent to the context.
1298  * If necessary, enables the global engine on the context and update ibus->focused_context.
1299  */
1300 static void
1301 _context_focus_in_cb (BusInputContext *context,
1302                       BusIBusImpl     *ibus)
1303 {
1304     g_assert (BUS_IS_IBUS_IMPL (ibus));
1305     g_assert (BUS_IS_INPUT_CONTEXT (context));
1306
1307     /* Do nothing if context does not support focus.
1308      * The global engine shoule be detached from the focused context. */
1309     if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
1310         return;
1311     }
1312
1313     bus_ibus_impl_set_focused_context (ibus, context);
1314 }
1315
1316 /**
1317  * _context_focus_out_cb:
1318  *
1319  * A callback function to be called when the "focus-out" signal is sent to the context.
1320  */
1321 static void
1322 _context_focus_out_cb (BusInputContext    *context,
1323                        BusIBusImpl        *ibus)
1324 {
1325     g_assert (BUS_IS_IBUS_IMPL (ibus));
1326     g_assert (BUS_IS_INPUT_CONTEXT (context));
1327
1328     /* Do noting if context does not support focus.
1329      * Actually, the context should emit focus signals, if it does not support focus */
1330     if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
1331         return;
1332     }
1333
1334     /* Do noting if it is not focused context. */
1335     if (ibus->focused_context != context) {
1336         return;
1337     }
1338
1339
1340     if (ibus->use_global_engine == FALSE) {
1341         /* Do not change the focused context, if use_global_engine option is enabled.
1342          * If focused context swith to NULL, users can not swith engine in panel anymore.
1343          **/
1344         bus_ibus_impl_set_focused_context (ibus, NULL);
1345     }
1346 }
1347
1348 /**
1349  * _context_destroy_cb:
1350  *
1351  * A callback function to be called when the "destroy" signal is sent to the context.
1352  */
1353 static void
1354 _context_destroy_cb (BusInputContext    *context,
1355                      BusIBusImpl        *ibus)
1356 {
1357     g_assert (BUS_IS_IBUS_IMPL (ibus));
1358     g_assert (BUS_IS_INPUT_CONTEXT (context));
1359
1360     if (context == ibus->focused_context) {
1361         bus_ibus_impl_set_focused_context (ibus, NULL);
1362     }
1363
1364     ibus->contexts = g_list_remove (ibus->contexts, context);
1365     g_object_unref (context);
1366 }
1367
1368 /**
1369  * _context_enabled_cb:
1370  *
1371  * A callback function to be called when the "enabled" signal is sent to the context.
1372  */
1373 static void
1374 _context_enabled_cb (BusInputContext    *context,
1375                      BusIBusImpl        *ibus)
1376 {
1377     /* FIXME implement this. */
1378 }
1379
1380 /**
1381  * _context_disabled_cb:
1382  *
1383  * A callback function to be called when the "disabled" signal is sent to the context.
1384  */
1385 static void
1386 _context_disabled_cb (BusInputContext    *context,
1387                       BusIBusImpl        *ibus)
1388 {
1389     /* FIXME implement this. */
1390 }
1391
1392 /**
1393  * bus_ibus_impl_create_input_context:
1394  * @client: A name of a client. e.g. "gtk-im"
1395  * @returns: A BusInputContext object.
1396  *
1397  * Create a new BusInputContext object for the client.
1398  */
1399 static BusInputContext *
1400 bus_ibus_impl_create_input_context (BusIBusImpl   *ibus,
1401                                     BusConnection *connection,
1402                                     const gchar   *client)
1403 {
1404     BusInputContext *context = bus_input_context_new (connection, client);
1405     g_object_ref_sink (context);
1406     ibus->contexts = g_list_append (ibus->contexts, context);
1407
1408     /* Installs glib signal handlers so that the ibus object could be notified when e.g. an IBus.InputContext D-Bus method is called. */
1409     static const struct {
1410         gchar *name;
1411         GCallback callback;
1412     } signals [] = {
1413         { "request-engine", G_CALLBACK (_context_request_engine_cb) },
1414         { "engine-changed", G_CALLBACK (_context_engine_changed_cb) },
1415         { "focus-in",       G_CALLBACK (_context_focus_in_cb) },
1416         { "focus-out",      G_CALLBACK (_context_focus_out_cb) },
1417         { "destroy",        G_CALLBACK (_context_destroy_cb) },
1418         { "enabled",        G_CALLBACK (_context_enabled_cb) },
1419         { "disabled",       G_CALLBACK (_context_disabled_cb) },
1420     };
1421
1422     gint i;
1423     for (i = 0; i < G_N_ELEMENTS (signals); i++) {
1424         g_signal_connect (context,
1425                           signals[i].name,
1426                           signals[i].callback,
1427                           ibus);
1428     }
1429
1430     if (ibus->enable_by_default) {
1431         bus_input_context_enable (context);
1432     }
1433
1434     /* register the context object so that the object could handle IBus.InputContext method calls. */
1435     bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
1436                                    (IBusService *) context);
1437     g_object_ref (context);
1438     return context;
1439 }
1440
1441 /**
1442  * _ibus_create_input_context:
1443  *
1444  * Implement the "CreateInputContext" method call of the org.freedesktop.IBus interface.
1445  */
1446 static void
1447 _ibus_create_input_context (BusIBusImpl           *ibus,
1448                             GVariant              *parameters,
1449                             GDBusMethodInvocation *invocation)
1450 {
1451     const gchar *client_name = NULL;  // e.g. "gtk-im"
1452     g_variant_get (parameters, "(&s)", &client_name);
1453
1454     BusConnection *connection =
1455             bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
1456     BusInputContext *context =
1457             bus_ibus_impl_create_input_context (ibus,
1458                                                 connection,
1459                                                 client_name);
1460     if (context) {
1461         const gchar *path = ibus_service_get_object_path ((IBusService *) context);
1462         /* the format-string 'o' is for a D-Bus object path. */
1463         g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
1464         g_object_unref (context);
1465     }
1466     else {
1467         g_dbus_method_invocation_return_error (invocation,
1468                                                G_DBUS_ERROR,
1469                                                G_DBUS_ERROR_FAILED,
1470                                                "Create input context failed!");
1471     }
1472 }
1473
1474 /**
1475  * _ibus_current_input_context:
1476  *
1477  * Implement the "CurrentInputContext" method call of the org.freedesktop.IBus interface.
1478  */
1479 static void
1480 _ibus_current_input_context (BusIBusImpl           *ibus,
1481                              GVariant              *parameters,
1482                              GDBusMethodInvocation *invocation)
1483 {
1484     if (!ibus->focused_context)
1485     {
1486         g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1487                         "No focused input context");
1488     }
1489     else {
1490         const gchar *path = ibus_service_get_object_path ((IBusService *) ibus->focused_context);
1491         /* the format-string 'o' is for a D-Bus object path. */
1492         g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
1493     }
1494 }
1495
1496 static void
1497 _component_destroy_cb (BusComponent *component,
1498                        BusIBusImpl  *ibus)
1499 {
1500     g_assert (BUS_IS_IBUS_IMPL (ibus));
1501     g_assert (BUS_IS_COMPONENT (component));
1502
1503     ibus->registered_components = g_list_remove (ibus->registered_components, component);
1504
1505     /* remove engines from engine_list */
1506     GList *engines = bus_component_get_engines (component);
1507     GList *p;
1508     for (p = engines; p != NULL; p = p->next) {
1509         if (g_list_find (ibus->register_engine_list, p->data)) {
1510             ibus->register_engine_list = g_list_remove (ibus->register_engine_list, p->data);
1511             g_object_unref (p->data);
1512         }
1513     }
1514     g_list_free (engines);
1515
1516     g_object_unref (component);
1517
1518     bus_ibus_impl_engines_maybe_removed (ibus);
1519     bus_ibus_impl_update_engines_hotkey_profile (ibus);
1520 }
1521
1522 /**
1523  * _ibus_register_component:
1524  *
1525  * Implement the "RegisterComponent" method call of the org.freedesktop.IBus interface.
1526  */
1527 static void
1528 _ibus_register_component (BusIBusImpl           *ibus,
1529                           GVariant              *parameters,
1530                           GDBusMethodInvocation *invocation)
1531 {
1532     GVariant *variant = g_variant_get_child_value (parameters, 0);
1533     IBusComponent *component = (IBusComponent *) ibus_serializable_deserialize (variant);
1534
1535     if (!IBUS_IS_COMPONENT (component)) {
1536         if (component)
1537             g_object_unref (component);
1538         g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1539                         "The first argument should be an IBusComponent.");
1540         return;
1541     }
1542
1543     BusConnection *connection = bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
1544     BusFactoryProxy *factory = bus_factory_proxy_new (connection);
1545
1546     if (factory == NULL) {
1547         g_object_unref (component);
1548         g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1549                         "Create factory failed.");
1550         return;
1551     }
1552
1553     g_object_ref_sink (component);
1554
1555     BusComponent *buscomp = bus_component_new (component, factory);
1556     bus_component_set_destroy_with_factory (buscomp, TRUE);
1557     g_object_unref (component);
1558     g_object_unref (factory);
1559
1560     ibus->registered_components = g_list_append (ibus->registered_components,
1561                                                 g_object_ref_sink (buscomp));
1562     GList *engines = bus_component_get_engines (buscomp);
1563     g_list_foreach (engines, (GFunc) g_object_ref, NULL);
1564     ibus->register_engine_list = g_list_concat (ibus->register_engine_list,
1565                                                engines);
1566
1567     g_signal_connect (buscomp, "destroy", G_CALLBACK (_component_destroy_cb), ibus);
1568
1569     bus_ibus_impl_update_engines_hotkey_profile (ibus);
1570
1571     g_dbus_method_invocation_return_value (invocation, NULL);
1572 }
1573
1574 /**
1575  * _ibus_list_engines:
1576  *
1577  * Implement the "ListEngines" method call of the org.freedesktop.IBus interface.
1578  */
1579 static void
1580 _ibus_list_engines (BusIBusImpl           *ibus,
1581                     GVariant              *parameters,
1582                     GDBusMethodInvocation *invocation)
1583 {
1584     GVariantBuilder builder;
1585     g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1586
1587     GList *engines = bus_registry_get_engines (ibus->registry);
1588     GList *p;
1589     for (p = engines; p != NULL; p = p->next) {
1590         g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1591     }
1592     g_list_free (engines);
1593     g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1594 }
1595
1596 /**
1597  * _ibus_list_active_engines:
1598  *
1599  * Implement the "ListActiveEngines" method call of the org.freedesktop.IBus interface.
1600  */
1601 static void
1602 _ibus_list_active_engines (BusIBusImpl           *ibus,
1603                            GVariant              *parameters,
1604                            GDBusMethodInvocation *invocation)
1605 {
1606     GVariantBuilder builder;
1607     g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1608
1609     GList *p;
1610     for (p = ibus->engine_list; p != NULL; p = p->next) {
1611         g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1612     }
1613     for (p = ibus->register_engine_list; p != NULL; p = p->next) {
1614         g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *) p->data));
1615     }
1616     g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1617 }
1618
1619 /**
1620  * _ibus_exit:
1621  *
1622  * Implement the "Exit" method call of the org.freedesktop.IBus interface.
1623  */
1624 static void
1625 _ibus_exit (BusIBusImpl           *ibus,
1626             GVariant              *parameters,
1627             GDBusMethodInvocation *invocation)
1628 {
1629     gboolean restart = FALSE;
1630     g_variant_get (parameters, "(b)", &restart);
1631
1632     g_dbus_method_invocation_return_value (invocation, NULL);
1633
1634     /* Make sure the reply has been sent out before exit */
1635     g_dbus_connection_flush_sync (g_dbus_method_invocation_get_connection (invocation),
1636                                   NULL,
1637                                   NULL);
1638     bus_server_quit ();
1639
1640     if (!restart) {
1641         exit (0);
1642     }
1643     else {
1644         extern gchar **g_argv;
1645         gchar *exe;
1646         gint fd;
1647
1648         exe = g_strdup_printf ("/proc/%d/exe", getpid ());
1649         exe = g_file_read_link (exe, NULL);
1650
1651         if (exe == NULL)
1652             exe = BINDIR "/ibus-daemon";
1653
1654         /* close all fds except stdin, stdout, stderr */
1655         for (fd = 3; fd <= sysconf (_SC_OPEN_MAX); fd ++) {
1656             close (fd);
1657         }
1658
1659         execv (exe, g_argv);
1660
1661         /* If the server binary is replaced while the server is running,
1662          * "readlink /proc/[pid]/exe" might return a path with " (deleted)"
1663          * suffix. */
1664         const gchar suffix[] = " (deleted)";
1665         if (g_str_has_suffix (exe, suffix)) {
1666             exe [strlen (exe) - sizeof (suffix) + 1] = '\0';
1667             execv (exe, g_argv);
1668         }
1669         g_warning ("execv %s failed!", g_argv[0]);
1670         exit (-1);
1671     }
1672
1673     /* should not reach here */
1674     g_assert_not_reached ();
1675 }
1676
1677 /**
1678  * _ibus_ping:
1679  *
1680  * Implement the "Ping" method call of the org.freedesktop.IBus interface.
1681  */
1682 static void
1683 _ibus_ping (BusIBusImpl           *ibus,
1684             GVariant              *parameters,
1685             GDBusMethodInvocation *invocation)
1686 {
1687     g_dbus_method_invocation_return_value (invocation, parameters);
1688 }
1689
1690 /**
1691  * _ibus_get_use_sys_layout:
1692  *
1693  * Implement the "GetUseSysLayout" method call of the org.freedesktop.IBus interface.
1694  */
1695 static void
1696 _ibus_get_use_sys_layout (BusIBusImpl           *ibus,
1697                           GVariant              *parameters,
1698                           GDBusMethodInvocation *invocation)
1699 {
1700     g_dbus_method_invocation_return_value (invocation,
1701                     g_variant_new ("(b)", ibus->use_sys_layout));
1702 }
1703
1704 /**
1705  * _ibus_get_use_global_engine:
1706  *
1707  * Implement the "GetUseGlobalEngine" method call of the org.freedesktop.IBus interface.
1708  */
1709 static void
1710 _ibus_get_use_global_engine (BusIBusImpl           *ibus,
1711                              GVariant              *parameters,
1712                              GDBusMethodInvocation *invocation)
1713 {
1714     g_dbus_method_invocation_return_value (invocation,
1715                     g_variant_new ("(b)", ibus->use_global_engine));
1716 }
1717
1718 /**
1719  * _ibus_get_global_engine:
1720  *
1721  * Implement the "GetGlobalEngine" method call of the org.freedesktop.IBus interface.
1722  */
1723 static void
1724 _ibus_get_global_engine (BusIBusImpl           *ibus,
1725                          GVariant              *parameters,
1726                          GDBusMethodInvocation *invocation)
1727 {
1728     IBusEngineDesc *desc = NULL;
1729
1730     do {
1731         if (!ibus->use_global_engine)
1732             break;
1733         BusInputContext *context = ibus->focused_context;
1734         if (context == NULL)
1735             context = ibus->fake_context;
1736
1737         desc = bus_input_context_get_engine_desc (context);
1738
1739         if (desc == NULL)
1740             break;
1741
1742         GVariant *variant = ibus_serializable_serialize ((IBusSerializable *) desc);
1743         g_dbus_method_invocation_return_value (invocation,
1744                                                g_variant_new ("(v)", variant));
1745         return;
1746     } while (0);
1747
1748     g_dbus_method_invocation_return_error (invocation,
1749                     G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1750                     "No global engine.");
1751 }
1752
1753 struct _SetGlobalEngineData {
1754     BusIBusImpl *ibus;
1755     GDBusMethodInvocation *invocation;
1756 };
1757 typedef struct _SetGlobalEngineData SetGlobalEngineData;
1758
1759 static void
1760 _ibus_set_global_engine_ready_cb (BusInputContext       *context,
1761                                   GAsyncResult          *res,
1762                                   SetGlobalEngineData   *data)
1763 {
1764     BusIBusImpl *ibus = data->ibus;
1765
1766     GError *error = NULL;
1767     if (!bus_input_context_set_engine_by_desc_finish (context, res, &error)) {
1768         g_error_free (error);
1769         g_dbus_method_invocation_return_error (data->invocation,
1770                                                G_DBUS_ERROR,
1771                                                G_DBUS_ERROR_FAILED,
1772                                                "Set global engine failed.");
1773
1774     }
1775     else {
1776         g_dbus_method_invocation_return_value (data->invocation, NULL);
1777
1778         if (ibus->use_global_engine && (context != ibus->focused_context)) {
1779             /* context and ibus->focused_context don't match. This means that
1780              * the focus is moved before _ibus_set_global_engine() asynchronous
1781              * call finishes. In this case, the engine for the context currently
1782              * being focused hasn't been updated. Update the engine here so that
1783              * subsequent _ibus_get_global_engine() call could return a
1784              * consistent engine name. */
1785             BusEngineProxy *engine = bus_input_context_get_engine (context);
1786             if (engine && ibus->focused_context != NULL) {
1787                 g_object_ref (engine);
1788                 bus_input_context_set_engine (context, NULL);
1789                 bus_input_context_set_engine (ibus->focused_context, engine);
1790                 g_object_unref (engine);
1791             }
1792         }
1793     }
1794
1795     g_object_unref (ibus);
1796     g_slice_free (SetGlobalEngineData, data);
1797 }
1798
1799 /**
1800  * _ibus_set_global_engine:
1801  *
1802  * Implement the "SetGlobalEngine" method call of the org.freedesktop.IBus interface.
1803  */
1804 static void
1805 _ibus_set_global_engine (BusIBusImpl           *ibus,
1806                          GVariant              *parameters,
1807                          GDBusMethodInvocation *invocation)
1808 {
1809     if (!ibus->use_global_engine) {
1810         g_dbus_method_invocation_return_error (invocation,
1811                         G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1812                         "Global engine feature is disabled.");
1813         return;
1814     }
1815
1816     BusInputContext *context = ibus->focused_context;
1817     if (context == NULL)
1818         context = ibus->fake_context;
1819
1820     const gchar *engine_name = NULL;
1821     g_variant_get (parameters, "(&s)", &engine_name);
1822
1823     IBusEngineDesc *desc = _find_engine_desc_by_name (ibus, engine_name);
1824     if (desc == NULL) {
1825         g_dbus_method_invocation_return_error (invocation,
1826                                                G_DBUS_ERROR,
1827                                                G_DBUS_ERROR_FAILED,
1828                                                "Can not find engine %s.",
1829                                                engine_name);
1830         return;
1831     }
1832
1833     SetGlobalEngineData *data = g_slice_new0 (SetGlobalEngineData);
1834     data->ibus = g_object_ref (ibus);
1835     data->invocation = invocation;
1836     bus_input_context_set_engine_by_desc (context,
1837                                           desc,
1838                                           g_gdbus_timeout, /* timeout in msec. */
1839                                           NULL, /* we do not cancel the call. */
1840                                           (GAsyncReadyCallback) _ibus_set_global_engine_ready_cb,
1841                                           data);
1842 }
1843
1844 /**
1845  * _ibus_is_global_engine_enabled:
1846  *
1847  * Implement the "IsGlobalEngineEnabled" method call of the org.freedesktop.IBus interface.
1848  */
1849 static void
1850 _ibus_is_global_engine_enabled (BusIBusImpl           *ibus,
1851                                 GVariant              *parameters,
1852                                 GDBusMethodInvocation *invocation)
1853 {
1854     gboolean enabled = FALSE;
1855
1856     do {
1857         if (!ibus->use_global_engine)
1858             break;
1859
1860         BusInputContext *context = ibus->focused_context;
1861         if (context == NULL)
1862             context = ibus->fake_context;
1863         if (context == NULL)
1864             break;
1865
1866         enabled = bus_input_context_is_enabled (context);
1867     } while (0);
1868
1869     g_dbus_method_invocation_return_value (invocation,
1870                     g_variant_new ("(b)", enabled));
1871 }
1872
1873 /**
1874  * bus_ibus_impl_service_method_call:
1875  *
1876  * Handle a D-Bus method call whose destination and interface name are both "org.freedesktop.IBus"
1877  */
1878 static void
1879 bus_ibus_impl_service_method_call (IBusService           *service,
1880                                    GDBusConnection       *connection,
1881                                    const gchar           *sender,
1882                                    const gchar           *object_path,
1883                                    const gchar           *interface_name,
1884                                    const gchar           *method_name,
1885                                    GVariant              *parameters,
1886                                    GDBusMethodInvocation *invocation)
1887 {
1888     if (g_strcmp0 (interface_name, "org.freedesktop.IBus") != 0) {
1889         IBUS_SERVICE_CLASS (bus_ibus_impl_parent_class)->service_method_call (
1890                         service, connection, sender, object_path, interface_name, method_name,
1891                         parameters, invocation);
1892         return;
1893     }
1894
1895     /* all methods in the xml definition above should be listed here. */
1896     static const struct {
1897         const gchar *method_name;
1898         void (* method_callback) (BusIBusImpl *, GVariant *, GDBusMethodInvocation *);
1899     } methods [] =  {
1900         /* IBus interface */
1901         { "GetAddress",            _ibus_get_address },
1902         { "CreateInputContext",    _ibus_create_input_context },
1903         { "CurrentInputContext",   _ibus_current_input_context },
1904         { "RegisterComponent",     _ibus_register_component },
1905         { "ListEngines",           _ibus_list_engines },
1906         { "ListActiveEngines",     _ibus_list_active_engines },
1907         { "Exit",                  _ibus_exit },
1908         { "Ping",                  _ibus_ping },
1909         { "GetUseSysLayout",       _ibus_get_use_sys_layout },
1910         { "GetUseGlobalEngine",    _ibus_get_use_global_engine },
1911         { "GetGlobalEngine",       _ibus_get_global_engine },
1912         { "SetGlobalEngine",       _ibus_set_global_engine },
1913         { "IsGlobalEngineEnabled", _ibus_is_global_engine_enabled },
1914     };
1915
1916     gint i;
1917     for (i = 0; i < G_N_ELEMENTS (methods); i++) {
1918         if (g_strcmp0 (methods[i].method_name, method_name) == 0) {
1919             methods[i].method_callback ((BusIBusImpl *) service, parameters, invocation);
1920             return;
1921         }
1922     }
1923
1924     /* notreached - unknown method calls that are not in the introspection_xml should be handled by the GDBus library. */
1925     g_return_if_reached ();
1926 }
1927
1928 BusIBusImpl *
1929 bus_ibus_impl_get_default (void)
1930 {
1931     static BusIBusImpl *ibus = NULL;
1932
1933     if (ibus == NULL) {
1934         ibus = (BusIBusImpl *) g_object_new (BUS_TYPE_IBUS_IMPL,
1935                                              "object-path", IBUS_PATH_IBUS,
1936                                              NULL);
1937     }
1938     return ibus;
1939 }
1940
1941 BusFactoryProxy *
1942 bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
1943                               const gchar *path)
1944 {
1945     g_assert (BUS_IS_IBUS_IMPL (ibus));
1946
1947     BusFactoryProxy *factory;
1948
1949     factory = (BusFactoryProxy *) g_hash_table_lookup (ibus->factory_dict, path);
1950
1951     return factory;
1952 }
1953
1954 IBusHotkeyProfile *
1955 bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus)
1956 {
1957     g_assert (BUS_IS_IBUS_IMPL (ibus));
1958
1959     return ibus->hotkey_profile;
1960 }
1961
1962 IBusKeymap *
1963 bus_ibus_impl_get_keymap (BusIBusImpl *ibus)
1964 {
1965
1966     g_assert (BUS_IS_IBUS_IMPL (ibus));
1967
1968     return ibus->keymap;
1969 }
1970
1971 BusRegistry *
1972 bus_ibus_impl_get_registry (BusIBusImpl *ibus)
1973 {
1974
1975     g_assert (BUS_IS_IBUS_IMPL (ibus));
1976
1977     return ibus->registry;
1978 }
1979
1980 /**
1981  * bus_ibus_impl_emit_signal:
1982  *
1983  * Send a D-Bus signal to buses (connections) that are listening to the signal.
1984  */
1985 static void
1986 bus_ibus_impl_emit_signal (BusIBusImpl *ibus,
1987                            const gchar *signal_name,
1988                            GVariant    *parameters)
1989 {
1990     static guint32 serial = 0;
1991     GDBusMessage *message = g_dbus_message_new_signal ("/org/freedesktop/IBus",
1992                                                        "org.freedesktop.IBus",
1993                                                        signal_name);
1994     /* set a non-zero serial to make libdbus happy */
1995     g_dbus_message_set_serial (message, ++serial);
1996     g_dbus_message_set_sender (message, "org.freedesktop.IBus");
1997     if (parameters)
1998         g_dbus_message_set_body (message, parameters);
1999     bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
2000     g_object_unref (message);
2001 }
2002
2003 static void
2004 bus_ibus_impl_registry_changed (BusIBusImpl *ibus)
2005 {
2006     bus_ibus_impl_emit_signal (ibus, "RegistryChanged", NULL);
2007 }
2008
2009 static void
2010 bus_ibus_impl_global_engine_changed (BusIBusImpl *ibus)
2011 {
2012     const gchar *name = ibus->global_engine_name ? ibus->global_engine_name : "";
2013     bus_ibus_impl_emit_signal (ibus, "GlobalEngineChanged",
2014                                g_variant_new ("(s)", name));
2015 }
2016
2017 gboolean
2018 bus_ibus_impl_filter_keyboard_shortcuts (BusIBusImpl     *ibus,
2019                                          BusInputContext *context,
2020                                          guint           keyval,
2021                                          guint           modifiers,
2022                                          guint           prev_keyval,
2023                                          guint           prev_modifiers)
2024 {
2025     static GQuark trigger = 0;
2026     static GQuark enable_unconditional = 0;
2027     static GQuark disable_unconditional = 0;
2028     static GQuark next = 0;
2029     static GQuark previous = 0;
2030
2031     GQuark event;
2032     GList *engine_list;
2033
2034     if (trigger == 0) {
2035         trigger = g_quark_from_static_string ("trigger");
2036         enable_unconditional = g_quark_from_static_string ("enable-unconditional");
2037         disable_unconditional = g_quark_from_static_string ("disable-unconditional");
2038         next = g_quark_from_static_string ("next-engine-in-menu");
2039         previous = g_quark_from_static_string ("previous-engine");
2040     }
2041
2042     /* Try global hotkeys first. */
2043     event = ibus_hotkey_profile_filter_key_event (ibus->hotkey_profile,
2044                                                   keyval,
2045                                                   modifiers,
2046                                                   prev_keyval,
2047                                                   prev_modifiers,
2048                                                   0);
2049
2050     if (event == trigger) {
2051         gboolean enabled = bus_input_context_is_enabled (context);
2052         if (enabled) {
2053             bus_input_context_disable (context);
2054         }
2055         else {
2056             bus_input_context_enable (context);
2057         }
2058         return (enabled != bus_input_context_is_enabled (context));
2059     }
2060     if (event == enable_unconditional) {
2061         gboolean enabled = bus_input_context_is_enabled (context);
2062         if (!enabled) {
2063             bus_input_context_enable (context);
2064         }
2065         return bus_input_context_is_enabled (context);
2066     }
2067     if (event == disable_unconditional) {
2068         gboolean enabled = bus_input_context_is_enabled (context);
2069         if (enabled) {
2070             bus_input_context_disable (context);
2071         }
2072         return !bus_input_context_is_enabled (context);
2073     }
2074     if (event == next) {
2075         if (bus_input_context_is_enabled (context)) {
2076             bus_ibus_impl_context_request_next_engine_in_menu (ibus, context);
2077         }
2078         else {
2079             bus_input_context_enable (context);
2080         }
2081         return TRUE;
2082     }
2083     if (event == previous) {
2084         if (bus_input_context_is_enabled (context)) {
2085             bus_ibus_impl_context_request_previous_engine (ibus, context);
2086         }
2087         else {
2088             bus_input_context_enable (context);
2089         }
2090         return TRUE;
2091     }
2092
2093     if (!ibus->engines_hotkey_profile || !ibus->hotkey_to_engines_map) {
2094         return FALSE;
2095     }
2096
2097     /* Then try engines hotkeys. */
2098     event = ibus_hotkey_profile_filter_key_event (ibus->engines_hotkey_profile,
2099                                                   keyval,
2100                                                   modifiers,
2101                                                   prev_keyval,
2102                                                   prev_modifiers,
2103                                                   0);
2104     if (event == 0) {
2105         return FALSE;
2106     }
2107
2108     engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
2109                                        GUINT_TO_POINTER (event));
2110     if (engine_list) {
2111         BusEngineProxy *current_engine = bus_input_context_get_engine (context);
2112         IBusEngineDesc *current_engine_desc =
2113             (current_engine ? bus_engine_proxy_get_desc (current_engine) : NULL);
2114         IBusEngineDesc *new_engine_desc = (IBusEngineDesc *) engine_list->data;
2115
2116         g_assert (new_engine_desc);
2117
2118         /* Find out what engine we should switch to. If the current engine has
2119          * the same hotkey, then we should switch to the next engine with the
2120          * same hotkey in the list. Otherwise, we just switch to the first
2121          * engine in the list. */
2122         GList *p = engine_list;
2123         for (; p->next != NULL; p = p->next) {
2124             if (current_engine_desc == (IBusEngineDesc *) p->data) {
2125                 new_engine_desc = (IBusEngineDesc *) p->next->data;
2126                 break;
2127             }
2128         }
2129
2130         if (current_engine_desc != new_engine_desc) {
2131             bus_ibus_impl_set_context_engine_from_desc (ibus, context, new_engine_desc);
2132         }
2133
2134         return TRUE;
2135     }
2136
2137     return FALSE;
2138 }
2139
2140 /**
2141  * bus_ibus_impl_load_global_engine_name_from_config:
2142  *
2143  * Retrieve the "global_engine" config from the config daemon. Return NULL if the daemon is not ready.
2144  */
2145 static gchar*
2146 bus_ibus_impl_load_global_engine_name_from_config (BusIBusImpl *ibus)
2147 {
2148     g_assert (BUS_IS_IBUS_IMPL (ibus));
2149     if (ibus->config == NULL) {
2150         /* the config component is not started yet. */
2151         return NULL;
2152     }
2153     g_assert (IBUS_IS_CONFIG (ibus->config));
2154
2155     GVariant *variant = ibus_config_get_value (ibus->config, "general", "global_engine");
2156     gchar *engine_name = NULL;
2157     if (variant != NULL) {
2158         g_variant_get (variant, "s", &engine_name);
2159         g_variant_unref (variant);
2160     }
2161     return engine_name;
2162 }
2163
2164 /**
2165  * bus_ibus_impl_save_global_engine_name_to_config:
2166  *
2167  * Save the "global_engine" config value on the config daemon. No-op if the daemon is not ready.
2168  */
2169 static void
2170 bus_ibus_impl_save_global_engine_name_to_config (BusIBusImpl *ibus)
2171 {
2172     g_assert (BUS_IS_IBUS_IMPL (ibus));
2173
2174     if (ibus->config &&
2175         ibus->use_global_engine &&
2176         ibus->global_engine_name) {
2177         ibus_config_set_value (ibus->config,
2178                         "general", "global_engine",
2179                         g_variant_new ("s", ibus->global_engine_name));
2180     }
2181 }
2182
2183 /**
2184  * bus_ibus_impl_load_global_previous_engine_name_from_config:
2185  *
2186  * Retrieve the "global_previous_engine" config from the config daemon. Return NULL if the daemon is not ready.
2187  */
2188 static gchar*
2189 bus_ibus_impl_load_global_previous_engine_name_from_config (BusIBusImpl *ibus)
2190 {
2191     g_assert (BUS_IS_IBUS_IMPL (ibus));
2192     if (ibus->config == NULL) {
2193         /* the config component is not started yet. */
2194         return NULL;
2195     }
2196     g_assert (IBUS_IS_CONFIG (ibus->config));
2197
2198     GVariant *value = ibus_config_get_value (ibus->config, "general", "global_previous_engine");
2199     if (value == NULL)
2200         return NULL;
2201     gchar *engine_name = NULL;
2202     g_variant_get (value, "(s)", &engine_name);
2203     g_variant_unref (value);
2204     return engine_name;
2205 }
2206
2207 /**
2208  * bus_ibus_impl_save_global_previous_engine_name_to_config:
2209  *
2210  * Save the "global_previous_engine" config value on the config daemon. No-op if the daemon is not ready.
2211  */
2212 static void
2213 bus_ibus_impl_save_global_previous_engine_name_to_config (BusIBusImpl *ibus)
2214 {
2215     g_assert (BUS_IS_IBUS_IMPL (ibus));
2216
2217     if (ibus->config &&
2218         ibus->use_global_engine &&
2219         ibus->global_previous_engine_name) {
2220         ibus_config_set_value (ibus->config,
2221                         "general", "global_previous_engine",
2222                         g_variant_new ("s", ibus->global_previous_engine_name));
2223     }
2224 }
2225
2226 /**
2227  * _add_engine_hotkey:
2228  *
2229  * Check the engine-specific hot key of the engine, and update ibus->engines_hotkey_profile.
2230  */
2231 static void
2232 _add_engine_hotkey (IBusEngineDesc *engine, BusIBusImpl *ibus)
2233 {
2234     const gchar *hotkeys;
2235     gchar **hotkey_list;
2236     gchar **p;
2237     gchar *hotkey;
2238     GList *engine_list;
2239
2240     GQuark event;
2241     guint keyval;
2242     guint modifiers;
2243
2244     if (!engine) {
2245         return;
2246     }
2247
2248     hotkeys = ibus_engine_desc_get_hotkeys (engine);
2249
2250     if (!hotkeys || !*hotkeys) {
2251         return;
2252     }
2253
2254     hotkey_list = g_strsplit_set (hotkeys, ";,", 0);
2255
2256     for (p = hotkey_list; p && *p; ++p) {
2257         hotkey = g_strstrip (*p);
2258         if (!*hotkey || !ibus_key_event_from_string (hotkey, &keyval, &modifiers)) {
2259             continue;
2260         }
2261
2262         /* If the hotkey already exists, we won't need to add it again. */
2263         event = ibus_hotkey_profile_lookup_hotkey (ibus->engines_hotkey_profile,
2264                                                    keyval, modifiers);
2265         if (event == 0) {
2266             event = g_quark_from_string (hotkey);
2267             ibus_hotkey_profile_add_hotkey (ibus->engines_hotkey_profile,
2268                                             keyval, modifiers, event);
2269         }
2270
2271         engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
2272                                            GUINT_TO_POINTER (event));
2273
2274         /* As we will rebuild the engines hotkey map whenever an engine was
2275          * added or removed, we don't need to hold a reference of the engine
2276          * here. */
2277         engine_list = g_list_append (engine_list, engine);
2278
2279         /* We need to steal the value before adding it back, otherwise it will
2280          * be destroyed. */
2281         g_hash_table_steal (ibus->hotkey_to_engines_map, GUINT_TO_POINTER (event));
2282
2283         g_hash_table_insert (ibus->hotkey_to_engines_map,
2284                              GUINT_TO_POINTER (event), engine_list);
2285     }
2286
2287     g_strfreev (hotkey_list);
2288 }
2289
2290 /**
2291  * bus_ibus_impl_update_engines_hotkey_profile:
2292  *
2293  * Check engine-specific hot keys of all active engines, and update ibus->engines_hotkey_profile.
2294  */
2295 static void
2296 bus_ibus_impl_update_engines_hotkey_profile (BusIBusImpl *ibus)
2297 {
2298     if (ibus->engines_hotkey_profile) {
2299         g_object_unref (ibus->engines_hotkey_profile);
2300     }
2301
2302     if (ibus->hotkey_to_engines_map) {
2303         g_hash_table_unref (ibus->hotkey_to_engines_map);
2304     }
2305
2306     ibus->engines_hotkey_profile = ibus_hotkey_profile_new ();
2307     ibus->hotkey_to_engines_map =
2308         g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_list_free);
2309
2310     g_list_foreach (ibus->register_engine_list, (GFunc) _add_engine_hotkey, ibus);
2311     g_list_foreach (ibus->engine_list, (GFunc) _add_engine_hotkey, ibus);
2312 }
2313
2314 gboolean
2315 bus_ibus_impl_is_use_sys_layout (BusIBusImpl *ibus)
2316 {
2317     g_assert (BUS_IS_IBUS_IMPL (ibus));
2318
2319     return ibus->use_sys_layout;
2320 }
2321
2322 gboolean
2323 bus_ibus_impl_is_embed_preedit_text (BusIBusImpl *ibus)
2324 {
2325     g_assert (BUS_IS_IBUS_IMPL (ibus));
2326
2327     return ibus->embed_preedit_text;
2328 }
2329
2330 BusInputContext *
2331 bus_ibus_impl_get_focused_input_context (BusIBusImpl *ibus)
2332 {
2333     g_assert (BUS_IS_IBUS_IMPL (ibus));
2334
2335     return ibus->focused_context;
2336 }