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