Refine some code and remove some dead code.
[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     GList *factory_list;
47     GList *contexts;
48
49     GList *engine_list;
50     GList *register_engine_list;
51     GList *component_list;
52
53     gboolean use_sys_layout;
54     gboolean embed_preedit_text;
55     gboolean enable_by_default;
56
57     BusRegistry     *registry;
58
59     BusInputContext *focused_context;
60     BusPanelProxy   *panel;
61     IBusConfig      *config;
62     IBusHotkeyProfile *hotkey_profile;
63     IBusKeymap      *keymap;
64
65     gboolean use_global_engine;
66     BusEngineProxy  *global_engine;
67     gchar           *global_previous_engine_name;
68
69     IBusHotkeyProfile *engines_hotkey_profile;
70     GHashTable      *hotkey_to_engines_map;
71 };
72
73 struct _BusIBusImplClass {
74     IBusServiceClass parent;
75
76     /* class members */
77 };
78
79 enum {
80     LAST_SIGNAL,
81 };
82
83 enum {
84     PROP_0,
85 };
86
87 /*
88 static guint            _signals[LAST_SIGNAL] = { 0 };
89 */
90
91 /* functions prototype */
92 static void      bus_ibus_impl_destroy           (BusIBusImpl        *ibus);
93 static void      bus_ibus_impl_service_method_call
94                                               (IBusService        *service,
95                                                GDBusConnection    *connection,
96                                                const gchar        *sender,
97                                                const gchar        *object_path,
98                                                const gchar        *interface_name,
99                                                const gchar        *method_name,
100                                                GVariant           *parameters,
101                                                GDBusMethodInvocation
102                                                                   *invocation);
103 /* FIXME */
104 #if 0
105 static GVariant *ibus_ibus_impl_service_get_property
106                                              (IBusService        *service,
107                                               GDBusConnection    *connection,
108                                               const gchar        *sender,
109                                               const gchar        *object_path,
110                                               const gchar        *interface_name,
111                                               const gchar        *property_name,
112                                               GError            **error);
113 static gboolean  ibus_ibus_impl_service_set_property
114                                              (IBusService        *service,
115                                               GDBusConnection    *connection,
116                                               const gchar        *sender,
117                                               const gchar        *object_path,
118                                               const gchar        *interface_name,
119                                               const gchar        *property_name,
120                                               GVariant           *value,
121                                               GError            **error);
122 #endif
123 static void     bus_ibus_impl_add_factory       (BusIBusImpl        *ibus,
124                                                  BusFactoryProxy    *factory);
125 static void     bus_ibus_impl_set_trigger       (BusIBusImpl        *ibus,
126                                                  GVariant           *value);
127 static void     bus_ibus_impl_set_next_engine_in_menu
128                                                 (BusIBusImpl        *ibus,
129                                                  GVariant           *value);
130 static void     bus_ibus_impl_set_previous_engine
131                                                 (BusIBusImpl        *ibus,
132                                                  GVariant           *value);
133 static void     bus_ibus_impl_set_preload_engines
134                                                 (BusIBusImpl        *ibus,
135                                                  GVariant           *value);
136 static void     bus_ibus_impl_set_use_sys_layout
137                                                 (BusIBusImpl        *ibus,
138                                                  GVariant           *value);
139 static void     bus_ibus_impl_set_embed_preedit_text
140                                                 (BusIBusImpl        *ibus,
141                                                  GVariant           *value);
142 static void     bus_ibus_impl_set_enable_by_default
143                                                 (BusIBusImpl        *ibus,
144                                                  GVariant           *value);
145 static void     bus_ibus_impl_set_use_global_engine
146                                                 (BusIBusImpl        *ibus,
147                                                  GVariant           *value);
148 static void     bus_ibus_impl_set_global_engine (BusIBusImpl        *ibus,
149                                                  BusEngineProxy     *engine);
150
151 static void     bus_ibus_impl_registry_changed  (BusIBusImpl        *ibus);
152 static void     bus_ibus_impl_global_engine_changed
153                                                 (BusIBusImpl        *ibus);
154
155 static void     _factory_destroy_cb             (BusFactoryProxy    *factory,
156                                                  BusIBusImpl        *ibus);
157
158 static void     bus_ibus_impl_set_context_engine_from_desc
159                                                 (BusIBusImpl        *ibus,
160                                                  BusInputContext    *context,
161                                                  IBusEngineDesc     *engine_desc);
162 static void     bus_ibus_impl_set_context_engine(BusIBusImpl        *ibus,
163                                                  BusInputContext    *context,
164                                                  BusEngineProxy     *engine);
165
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
178 static const gchar introspection_xml[] =
179     "<node>"
180     "  <interface name='org.freedesktop.IBus'>"
181     "    <method name='GetAddress'>"
182     "      <arg direction='out' type='s' name='address' />"
183     "    </method>"
184     "    <method name='CreateInputContext'>"
185     "      <arg direction='in'  type='s' name='client_name' />"
186     "      <arg direction='out' type='o' name='object_path' />"
187     "    </method>"
188     "    <method name='CurrentInputContext'>"
189     "      <arg direction='out' type='o' name='object_path' />"
190     "    </method>"
191     "    <method name='RegisterComponent'>"
192     "      <arg direction='in'  type='v' name='component' />"
193     "    </method>"
194     "    <method name='ListEngines'>"
195     "      <arg direction='out' type='av' name='engines' />"
196     "    </method>"
197     "    <method name='ListActiveEngines'>"
198     "      <arg direction='out' type='av' name='engines' />"
199     "    </method>"
200     "    <method name='Exit'>"
201     "      <arg direction='in'  type='b' name='restart' />"
202     "    </method>"
203     "    <method name='Ping'>"
204     "      <arg direction='in'  type='v' name='data' />"
205     "      <arg direction='out' type='v' name='data' />"
206     "    </method>"
207     "    <method name='GetUseSysLayout'>"
208     "      <arg direction='out' type='b' name='enabled' />"
209     "    </method>"
210     "    <method name='GetUseGlobalEngine'>"
211     "      <arg direction='out' type='b' name='enabled' />"
212     "    </method>"
213     "    <method name='GetGlobalEngine'>"
214     "      <arg direction='out' type='v' name='desc' />"
215     "    </method>"
216     "    <method name='SetGlobalEngine'>"
217     "      <arg direction='in'  type='s' name='engine_name' />"
218     "    </method>"
219     "    <method name='IsGlobalEngineEnabled'>"
220     "      <arg direction='out' type='b' name='enabled' />"
221     "    </method>"
222     "    <signal name='RegistryChanged'>"
223     "    </signal>"
224     "    <signal name='GlobalEngineChanged'>"
225     "    </signal>"
226     "  </interface>"
227     "</node>";
228
229
230 G_DEFINE_TYPE(BusIBusImpl, bus_ibus_impl, IBUS_TYPE_SERVICE)
231
232 static void
233 bus_ibus_impl_class_init (BusIBusImplClass *class)
234 {
235     IBUS_OBJECT_CLASS(class)->destroy = (IBusObjectDestroyFunc) bus_ibus_impl_destroy;
236
237     IBUS_SERVICE_CLASS (class)->service_method_call = bus_ibus_impl_service_method_call;
238     ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml);
239 }
240
241 static void
242 _panel_destroy_cb (BusPanelProxy *panel,
243                    BusIBusImpl   *ibus)
244 {
245     g_assert (BUS_IS_PANEL_PROXY (panel));
246     g_assert (BUS_IS_IBUS_IMPL (ibus));
247
248     g_return_if_fail (ibus->panel == panel);
249
250     ibus->panel = NULL;
251     g_object_unref (panel);
252 }
253
254 static void
255 bus_ibus_impl_set_hotkey (BusIBusImpl *ibus,
256                           GQuark       hotkey,
257                           GVariant     *value)
258 {
259     g_assert (BUS_IS_IBUS_IMPL (ibus));
260
261     ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
262
263     if (value == NULL) {
264         return;
265     }
266
267     GVariantIter iter;
268     g_variant_iter_init (&iter, value);
269     const gchar *str = NULL;
270     while (g_variant_iter_loop (&iter,"&s", &str)) {
271        ibus_hotkey_profile_add_hotkey_from_string (ibus->hotkey_profile,
272                                                    str,
273                                                    hotkey);
274     }
275
276 }
277
278 static void
279 bus_ibus_impl_set_trigger (BusIBusImpl *ibus,
280                            GVariant    *value)
281 {
282     GQuark hotkey = g_quark_from_static_string ("trigger");
283     if (value != NULL) {
284         bus_ibus_impl_set_hotkey (ibus, hotkey, value);
285     }
286     else {
287         /* set default trigger */
288         ibus_hotkey_profile_add_hotkey (ibus->hotkey_profile,
289                                         IBUS_space,
290                                         IBUS_CONTROL_MASK,
291                                         hotkey);
292     }
293 }
294
295 static void
296 bus_ibus_impl_set_next_engine_in_menu (BusIBusImpl *ibus,
297                                        GVariant     *value)
298 {
299     GQuark hotkey = g_quark_from_static_string ("next-engine-in-menu");
300     bus_ibus_impl_set_hotkey (ibus, hotkey, value);
301 }
302
303 static void
304 bus_ibus_impl_set_previous_engine (BusIBusImpl *ibus,
305                                    GVariant    *value)
306 {
307     GQuark hotkey = g_quark_from_static_string ("previous-engine");
308     bus_ibus_impl_set_hotkey (ibus, hotkey, value);
309 }
310
311 static void
312 bus_ibus_impl_set_preload_engines (BusIBusImpl *ibus,
313                                    GVariant    *value)
314 {
315     GList *engine_list = NULL;
316
317     g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
318     g_list_free (ibus->engine_list);
319
320     if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_ARRAY) {
321         GVariantIter iter;
322         g_variant_iter_init (&iter, value);
323         const gchar *engine_name = NULL;
324         while (g_variant_iter_loop (&iter, "&s", &engine_name)) {
325             IBusEngineDesc *engine = bus_registry_find_engine_by_name (ibus->registry, engine_name);
326             if (engine == NULL || g_list_find (engine_list, engine) != NULL)
327                 continue;
328             engine_list = g_list_append (engine_list, engine);
329         }
330     }
331
332     g_list_foreach (engine_list, (GFunc) g_object_ref, NULL);
333     ibus->engine_list = engine_list;
334
335     if (ibus->engine_list) {
336         IBusComponent *component = ibus_component_get_from_engine ((IBusEngineDesc *) ibus->engine_list->data);
337         if (component && !ibus_component_is_running (component)) {
338             ibus_component_start (component, g_verbose);
339         }
340     }
341
342     bus_ibus_impl_update_engines_hotkey_profile (ibus);
343 }
344
345 static void
346 bus_ibus_impl_set_use_sys_layout (BusIBusImpl *ibus,
347                                   GVariant    *value)
348 {
349     if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
350         ibus->use_sys_layout = g_variant_get_boolean (value);
351     }
352 }
353
354 static void
355 bus_ibus_impl_set_embed_preedit_text (BusIBusImpl *ibus,
356                                       GVariant    *value)
357 {
358     if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
359         ibus->embed_preedit_text = g_variant_get_boolean (value);
360     }
361 }
362
363 static void
364 bus_ibus_impl_set_enable_by_default (BusIBusImpl *ibus,
365                                      GVariant    *value)
366 {
367     if (value != NULL && g_variant_classify (value) == G_VARIANT_CLASS_BOOLEAN) {
368         ibus->enable_by_default = g_variant_get_boolean (value);
369     }
370 }
371
372 static void
373 bus_ibus_impl_set_use_global_engine (BusIBusImpl *ibus,
374                                      GVariant    *value)
375 {
376     if (value == NULL || g_variant_classify (value) != G_VARIANT_CLASS_BOOLEAN)
377         return;
378
379     gboolean new_value = g_variant_get_boolean (value);
380     if (ibus->use_global_engine == new_value)
381         return;
382
383     if (new_value) {
384         /* turn on use_global_engine option */
385         ibus->use_global_engine = TRUE;
386         BusEngineProxy *engine = ibus->focused_context != NULL ?
387                     bus_input_context_get_engine (ibus->focused_context) : NULL;
388         if (engine != NULL) {
389             bus_ibus_impl_set_global_engine (ibus, engine);
390         }
391     }
392     else {
393         /* turn off use_global_engine option */
394         bus_ibus_impl_set_global_engine (ibus, NULL);
395         ibus->use_global_engine = FALSE;
396         g_free (ibus->global_previous_engine_name);
397     }
398 }
399
400 static gint
401 _engine_desc_cmp (IBusEngineDesc *desc1,
402                   IBusEngineDesc *desc2)
403 {
404     return - ((gint) ibus_engine_desc_get_rank (desc1)) +
405               ((gint) ibus_engine_desc_get_rank (desc2));
406 }
407
408 static void
409 bus_ibus_impl_set_default_preload_engines (BusIBusImpl *ibus)
410 {
411     g_assert (BUS_IS_IBUS_IMPL (ibus));
412
413     static gboolean done = FALSE;
414
415     if (done || ibus->config == NULL) {
416         return;
417     }
418
419     GVariant *variant = ibus_config_get_value (ibus->config, "general", "preload_engines");
420     if (variant != NULL) {
421         done = TRUE;
422         g_variant_unref (variant);
423         return;
424     }
425
426     done = TRUE;
427     gchar *lang = g_strdup (setlocale (LC_ALL, NULL));
428     gchar *p = index (lang, '.');
429     if (p) {
430         *p = '\0';
431     }
432
433     GList *engines = bus_registry_get_engines_by_language (ibus->registry, lang);
434     if (engines == NULL) {
435         p = index (lang, '_');
436         if (p) {
437             *p = '\0';
438             engines = bus_registry_get_engines_by_language (ibus->registry, lang);
439         }
440     }
441     g_free (lang);
442
443     /* sort engines by rank */
444     engines = g_list_sort (engines, (GCompareFunc) _engine_desc_cmp);
445
446     GVariantBuilder builder;
447     g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
448     GList *list;
449     for (list = engines; list != NULL; list = list->next) {
450         IBusEngineDesc *desc = (IBusEngineDesc *)list->data;
451         /* ignore engines with rank <== 0 */
452         if (ibus_engine_desc_get_rank (desc) > 0)
453             g_variant_builder_add (&builder, "s", ibus_engine_desc_get_name (desc));
454     }
455     ibus_config_set_value (ibus->config,
456                     "general", "preload_engines", g_variant_builder_end (&builder));
457     g_list_free (engines);
458 }
459
460 const static struct {
461     gchar *section;
462     gchar *key;
463     void ( *func) (BusIBusImpl *, GVariant *);
464 } bus_ibus_impl_config_items [] = {
465     { "general/hotkey", "trigger",              bus_ibus_impl_set_trigger },
466     { "general/hotkey", "next_engine_in_menu",  bus_ibus_impl_set_next_engine_in_menu },
467     { "general/hotkey", "previous_engine",      bus_ibus_impl_set_previous_engine },
468     { "general", "preload_engines",             bus_ibus_impl_set_preload_engines },
469     { "general", "use_system_keyboard_layout",  bus_ibus_impl_set_use_sys_layout },
470     { "general", "use_global_engine",           bus_ibus_impl_set_use_global_engine },
471     { "general", "embed_preedit_text",          bus_ibus_impl_set_embed_preedit_text },
472     { "general", "enable_by_default",           bus_ibus_impl_set_enable_by_default },
473 };
474
475 static void
476 bus_ibus_impl_reload_config (BusIBusImpl *ibus)
477 {
478     g_assert (BUS_IS_IBUS_IMPL (ibus));
479
480     gint i;
481     for (i = 0; i < G_N_ELEMENTS (bus_ibus_impl_config_items); i++) {
482         GVariant *variant = NULL;
483         if (ibus->config != NULL)
484             variant = ibus_config_get_value (ibus->config,
485                             bus_ibus_impl_config_items[i].section,
486                             bus_ibus_impl_config_items[i].key);
487         bus_ibus_impl_config_items[i].func (ibus, variant);
488         if (variant) g_variant_unref (variant);
489     }
490 }
491
492 static void
493 _config_value_changed_cb (IBusConfig  *config,
494                           gchar       *section,
495                           gchar       *key,
496                           GVariant    *value,
497                           BusIBusImpl *ibus)
498 {
499     g_assert (IBUS_IS_CONFIG (config));
500     g_assert (section);
501     g_assert (key);
502     g_assert (value);
503     g_assert (BUS_IS_IBUS_IMPL (ibus));
504
505     gint i;
506     for (i = 0; i < G_N_ELEMENTS (bus_ibus_impl_config_items); i++) {
507         if (g_strcmp0 (bus_ibus_impl_config_items[i].section, section) == 0 &&
508             g_strcmp0 (bus_ibus_impl_config_items[i].key, key) == 0) {
509             bus_ibus_impl_config_items[i].func (ibus, value);
510             break;
511         }
512     }
513 }
514
515 static void
516 _config_destroy_cb (IBusConfig  *config,
517                     BusIBusImpl *ibus)
518 {
519     g_assert (IBUS_IS_CONFIG (config));
520     g_assert (BUS_IS_IBUS_IMPL (ibus));
521
522     g_assert (ibus->config == config);
523
524     g_object_unref (ibus->config);
525     ibus->config = NULL;
526 }
527
528 static void
529 _registry_changed_cb (BusRegistry *registry,
530                       BusIBusImpl *ibus)
531 {
532     bus_ibus_impl_registry_changed (ibus);
533 }
534
535 static void
536 _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
537                              const gchar *name,
538                              const gchar *old_name,
539                              const gchar *new_name,
540                              BusIBusImpl *ibus)
541 {
542     g_assert (BUS_IS_DBUS_IMPL (dbus));
543     g_assert (name != NULL);
544     g_assert (old_name != NULL);
545     g_assert (new_name != NULL);
546     g_assert (BUS_IS_IBUS_IMPL (ibus));
547
548     if (g_strcmp0 (name, IBUS_SERVICE_PANEL) == 0) {
549         if (g_strcmp0 (new_name, "") != 0) {
550             BusConnection *connection;
551
552             if (ibus->panel != NULL) {
553                 ibus_proxy_destroy ((IBusProxy *)ibus->panel);
554                 /* panel should be NULL after destroy */
555                 g_assert (ibus->panel == NULL);
556             }
557
558             connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
559             g_return_if_fail (connection != NULL);
560
561             ibus->panel = bus_panel_proxy_new (connection);
562             g_object_ref_sink (ibus->panel);
563
564             g_signal_connect (ibus->panel,
565                               "destroy",
566                               G_CALLBACK (_panel_destroy_cb),
567                               ibus);
568
569             if (ibus->focused_context != NULL) {
570                 bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context);
571             }
572         }
573     }
574     else if (g_strcmp0 (name, IBUS_SERVICE_CONFIG) == 0) {
575         if (g_strcmp0 (new_name, "") != 0) {
576             BusConnection *connection;
577
578             if (ibus->config != NULL) {
579                 ibus_proxy_destroy ((IBusProxy *)ibus->config);
580                 /* config should be NULL */
581                 g_assert (ibus->config == NULL);
582             }
583
584             connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
585             g_return_if_fail (connection != NULL);
586
587             ibus->config = g_initable_new (IBUS_TYPE_CONFIG,
588                                            NULL,
589                                            NULL,
590                                            "g-object-path", IBUS_PATH_CONFIG,
591                                            "g-interface-name", IBUS_INTERFACE_CONFIG,
592                                            "g-connection", bus_connection_get_dbus_connection (connection),
593                                            NULL);
594             g_object_ref_sink (ibus->config);
595
596             g_signal_connect (ibus->config,
597                               "value-changed",
598                               G_CALLBACK (_config_value_changed_cb),
599                               ibus);
600
601             g_signal_connect (ibus->config,
602                               "destroy",
603                               G_CALLBACK (_config_destroy_cb),
604                               ibus);
605
606             bus_ibus_impl_set_default_preload_engines (ibus);
607             bus_ibus_impl_reload_config (ibus);
608         }
609     }
610
611     BusFactoryProxy *factory = bus_registry_name_owner_changed (ibus->registry,
612                                                 name, old_name, new_name);
613
614     if (factory != NULL) {
615         bus_ibus_impl_add_factory (ibus, factory);
616     }
617 }
618
619 static void
620 bus_ibus_impl_init (BusIBusImpl *ibus)
621 {
622     ibus->factory_dict = g_hash_table_new_full (
623                             g_str_hash,
624                             g_str_equal,
625                             NULL,
626                             (GDestroyNotify) g_object_unref);
627
628     ibus->engine_list = NULL;
629     ibus->register_engine_list = NULL;
630     ibus->contexts = NULL;
631     ibus->focused_context = NULL;
632     ibus->panel = NULL;
633     ibus->config = NULL;
634
635     ibus->registry = bus_registry_new ();
636
637     g_signal_connect (ibus->registry,
638                       "changed",
639                       G_CALLBACK (_registry_changed_cb),
640                       ibus);
641 #ifdef G_THREADS_ENABLED
642     extern gint g_monitor_timeout;
643     if (g_monitor_timeout != 0) {
644         /* Start the monitor of registry changes. */
645         bus_registry_start_monitor_changes (ibus->registry);
646     }
647 #endif
648
649     ibus->hotkey_profile = ibus_hotkey_profile_new ();
650     ibus->keymap = ibus_keymap_get ("us");
651
652     ibus->use_sys_layout = FALSE;
653     ibus->embed_preedit_text = TRUE;
654     ibus->enable_by_default = FALSE;
655     ibus->use_global_engine = FALSE;
656     ibus->global_engine = NULL;
657     ibus->global_previous_engine_name = NULL;
658
659     ibus->engines_hotkey_profile = NULL;
660     ibus->hotkey_to_engines_map = NULL;
661
662     bus_ibus_impl_reload_config (ibus);
663
664     g_signal_connect (BUS_DEFAULT_DBUS,
665                       "name-owner-changed",
666                       G_CALLBACK (_dbus_name_owner_changed_cb),
667                       ibus);
668 }
669
670 static void
671 bus_ibus_impl_destroy (BusIBusImpl *ibus)
672 {
673     pid_t pid;
674     glong timeout;
675     gint status;
676     gboolean flag;
677
678     bus_registry_stop_all_components (ibus->registry);
679
680     pid = 0;
681     timeout = 0;
682     flag = FALSE;
683     while (1) {
684         while ((pid = waitpid (0, &status, WNOHANG)) > 0);
685
686         if (pid == -1) { /* all children finished */
687             break;
688         }
689         if (pid == 0) { /* no child status changed */
690             g_usleep (1000);
691             timeout += 1000;
692             if (timeout >= G_USEC_PER_SEC) {
693                 if (flag == FALSE) {
694                     gpointer old;
695                     old = signal (SIGTERM, SIG_IGN);
696                     kill (-getpid (), SIGTERM);
697                     signal (SIGTERM, old);
698                     flag = TRUE;
699                 }
700                 else {
701                     g_warning ("Not every child processes exited!");
702                     break;
703                 }
704             }
705         }
706     };
707
708     g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
709     g_list_free (ibus->engine_list);
710     ibus->engine_list = NULL;
711
712     g_list_foreach (ibus->register_engine_list, (GFunc) g_object_unref, NULL);
713     g_list_free (ibus->register_engine_list);
714     ibus->register_engine_list = NULL;
715
716     if (ibus->factory_dict != NULL) {
717         g_hash_table_destroy (ibus->factory_dict);
718         ibus->factory_dict = NULL;
719     }
720
721     if (ibus->hotkey_profile != NULL) {
722         g_object_unref (ibus->hotkey_profile);
723         ibus->hotkey_profile = NULL;
724     }
725
726     if (ibus->keymap != NULL) {
727         g_object_unref (ibus->keymap);
728         ibus->keymap = NULL;
729     }
730
731     if (ibus->global_engine) {
732         g_object_unref (ibus->global_engine);
733         ibus->global_engine = NULL;
734     }
735
736     g_free (ibus->global_previous_engine_name);
737
738     if (ibus->engines_hotkey_profile != NULL) {
739         g_object_unref (ibus->engines_hotkey_profile);
740         ibus->engines_hotkey_profile = NULL;
741     }
742
743     if (ibus->hotkey_to_engines_map) {
744         g_hash_table_unref (ibus->hotkey_to_engines_map);
745         ibus->hotkey_to_engines_map = NULL;
746     }
747
748     bus_server_quit ();
749     IBUS_OBJECT_CLASS(bus_ibus_impl_parent_class)->destroy (IBUS_OBJECT (ibus));
750 }
751
752 static void
753 _ibus_get_address (BusIBusImpl           *ibus,
754                    GVariant              *parameters,
755                    GDBusMethodInvocation *invocation)
756 {
757     g_dbus_method_invocation_return_value (invocation,
758                                            g_variant_new ("(s)", bus_server_get_address ()));
759 }
760
761
762 static gboolean
763 _timeout_cb (gpointer data)
764 {
765     return TRUE;
766 }
767
768 static BusFactoryProxy *
769 _get_factory_proxy(IBusEngineDesc *engine_desc)
770 {
771     BusFactoryProxy *factory = NULL;
772
773     /* Add a timeout to wake up g_main_context_iteration in every 0.5 second,
774      * and then to check the factory assocated with the engine_desc */
775     guint timeout_id = g_timeout_add (500, _timeout_cb, NULL);
776
777     GTimer *timer = g_timer_new ();
778
779     /* Leave the loop, if it spends more than 5 seconds */
780     while (g_timer_elapsed (timer, NULL) <= 5.0) {
781         if (g_main_context_iteration (NULL, TRUE)) {
782             factory = bus_factory_proxy_get_from_engine (engine_desc);
783             if (factory != NULL) {
784                 break;
785             }
786         }
787     }
788
789     g_source_remove (timeout_id);
790     g_timer_destroy (timer);
791
792     return factory;
793 }
794
795 static BusEngineProxy *
796 bus_ibus_impl_create_engine (IBusEngineDesc *engine_desc)
797 {
798     IBusComponent *comp;
799     BusFactoryProxy *factory;
800     BusEngineProxy *engine;
801
802     factory = bus_factory_proxy_get_from_engine (engine_desc);
803
804     if (factory == NULL) {
805         /* try to execute the engine */
806         comp = ibus_component_get_from_engine (engine_desc);
807         g_assert (comp);
808
809         if (!ibus_component_is_running (comp)) {
810             ibus_component_start (comp, g_verbose);
811         }
812         factory = _get_factory_proxy (engine_desc);
813     }
814
815     if (factory == NULL) {
816         return NULL;
817     }
818
819     g_object_ref (factory);
820     engine = bus_factory_proxy_create_engine (factory, engine_desc);
821     g_object_unref (factory);
822
823     return engine;
824 }
825
826 static IBusEngineDesc *
827 _find_engine_desc_by_name(BusIBusImpl *ibus,
828                           const gchar *engine_name)
829 {
830     IBusEngineDesc *engine_desc = NULL;
831     GList *p;
832
833     /* find engine in registered engine list */
834     for (p = ibus->register_engine_list; p != NULL; p = p->next) {
835         engine_desc = (IBusEngineDesc *)p->data;
836         if (g_strcmp0 (ibus_engine_desc_get_name (engine_desc), engine_name) == 0)
837             return engine_desc;
838     }
839
840     /* find engine in preload engine list */
841     for (p = ibus->engine_list; p != NULL; p = p->next) {
842         engine_desc = (IBusEngineDesc *)p->data;
843         if (g_strcmp0 (ibus_engine_desc_get_name (engine_desc), engine_name) == 0)
844             return engine_desc;
845     }
846
847     return NULL;
848 }
849
850 static void
851 _context_request_engine_cb (BusInputContext *context,
852                             const gchar     *engine_name,
853                             BusIBusImpl     *ibus)
854 {
855     IBusEngineDesc *engine_desc = NULL;
856
857     /* context should has focus before request an engine */
858     g_return_if_fail (bus_input_context_has_focus (context));
859
860     if (engine_name == NULL || engine_name[0] == '\0') {
861         /* Use global engine if possible. */
862         if (ibus->use_global_engine) {
863             if (ibus->global_engine) {
864                 bus_ibus_impl_set_context_engine (ibus, context, ibus->global_engine);
865                 return;
866             }
867             else {
868                 gchar *name = bus_ibus_impl_load_global_engine_name_from_config (ibus);
869                 if (name) {
870                     engine_desc = _find_engine_desc_by_name (ibus, name);
871                     g_free (name);
872                 }
873             }
874         }
875         /* request default engine */
876         if (!engine_desc) {
877             if (ibus->register_engine_list) {
878                 engine_desc = (IBusEngineDesc *)ibus->register_engine_list->data;
879             }
880             else if (ibus->engine_list) {
881                 engine_desc = (IBusEngineDesc *)ibus->engine_list->data;
882             }
883          }
884     }
885     else {
886         /* request engine by name */
887         engine_desc = _find_engine_desc_by_name (ibus, engine_name);
888     }
889
890     bus_ibus_impl_set_context_engine_from_desc (ibus, context, engine_desc);
891 }
892
893 static void
894 bus_ibus_impl_context_request_next_engine_in_menu (BusIBusImpl     *ibus,
895                                                    BusInputContext *context)
896 {
897     BusEngineProxy *engine;
898     IBusEngineDesc *desc;
899     IBusEngineDesc *next_desc = NULL;
900     GList *p;
901
902     engine = bus_input_context_get_engine (context);
903     if (engine == NULL) {
904         _context_request_engine_cb (context, NULL, ibus);
905         return;
906     }
907
908     desc = bus_engine_proxy_get_desc (engine);
909
910     p = g_list_find (ibus->register_engine_list, desc);
911     if (p != NULL) {
912         p = p->next;
913     }
914     if (p == NULL) {
915         p = g_list_find (ibus->engine_list, desc);
916         if (p != NULL) {
917             p = p->next;
918         }
919     }
920
921     if (p != NULL) {
922         next_desc = (IBusEngineDesc*) p->data;
923     }
924     else {
925         if (ibus->register_engine_list) {
926             next_desc = (IBusEngineDesc *)ibus->register_engine_list->data;
927         }
928         else if (ibus->engine_list) {
929             next_desc = (IBusEngineDesc *)ibus->engine_list->data;
930         }
931     }
932
933     bus_ibus_impl_set_context_engine_from_desc (ibus, context, next_desc);
934 }
935
936 static void
937 bus_ibus_impl_context_request_previous_engine (BusIBusImpl     *ibus,
938                                                BusInputContext *context)
939 {
940     gchar *engine_name = NULL;
941     if (!ibus->use_global_engine) {
942         engine_name = (gchar *) g_object_get_data (G_OBJECT (context), "previous-engine-name");
943     }
944     else {
945         if (!ibus->global_previous_engine_name) {
946             ibus->global_previous_engine_name = bus_ibus_impl_load_global_previous_engine_name_from_config (ibus);
947         }
948         engine_name = ibus->global_previous_engine_name;
949     }
950
951     /*
952      * If the previous engine name is not found, switch to the next engine
953      * in the menu. This behavior is better than doing nothing.
954      */
955     if (!engine_name) {
956         bus_ibus_impl_context_request_next_engine_in_menu(ibus, context);
957         return;
958     }
959     _context_request_engine_cb (context, engine_name, ibus);
960 }
961
962 static void
963 _global_engine_destroy_cb (BusEngineProxy *engine,
964                            BusIBusImpl    *ibus)
965 {
966     if (ibus->global_engine != engine) {
967         return;
968     }
969
970     g_signal_handlers_disconnect_by_func (ibus->global_engine,
971                 G_CALLBACK (_global_engine_destroy_cb), ibus);
972     g_object_unref (ibus->global_engine);
973     ibus->global_engine = NULL;
974 }
975
976 static void
977 bus_ibus_impl_set_global_engine (BusIBusImpl    *ibus,
978                                  BusEngineProxy *engine)
979 {
980     g_assert (ibus->use_global_engine == TRUE);
981
982     if (ibus->global_engine == engine) {
983         return;
984     }
985
986     g_free (ibus->global_previous_engine_name);
987     ibus->global_previous_engine_name = NULL;
988     if (ibus->global_engine) {
989         /* Save the current global engine's name as previous engine. */
990         const gchar *name = ibus_engine_desc_get_name (bus_engine_proxy_get_desc (ibus->global_engine));
991         ibus->global_previous_engine_name = g_strdup (name);
992
993         ibus_proxy_destroy ((IBusProxy *)ibus->global_engine);
994         /* global_engine should be NULL */
995         g_assert (ibus->global_engine == NULL);
996     }
997
998     if (engine != NULL && !IBUS_PROXY_DESTROYED (engine)) {
999         g_object_ref (engine);
1000         ibus->global_engine = engine;
1001         g_signal_connect (ibus->global_engine, "destroy",
1002                 G_CALLBACK (_global_engine_destroy_cb), ibus);
1003     }
1004
1005     bus_ibus_impl_save_global_engine_name_to_config (ibus);
1006     bus_ibus_impl_save_global_previous_engine_name_to_config (ibus);
1007     bus_ibus_impl_global_engine_changed (ibus);
1008 }
1009
1010 static void
1011 bus_ibus_impl_set_context_engine_from_desc (BusIBusImpl     *ibus,
1012                                             BusInputContext *context,
1013                                             IBusEngineDesc  *engine_desc)
1014 {
1015     if (engine_desc != NULL) {
1016         BusEngineProxy *engine = bus_ibus_impl_create_engine (engine_desc);
1017         if (engine != NULL) {
1018             bus_ibus_impl_set_context_engine (ibus, context, engine);
1019         }
1020     }
1021 }
1022
1023 static void
1024 bus_ibus_impl_set_context_engine (BusIBusImpl     *ibus,
1025                                   BusInputContext *context,
1026                                   BusEngineProxy  *engine) {
1027   g_object_set_data (G_OBJECT (context), "previous-engine-name", NULL);
1028
1029   /* If use_global_engine is disabled, then we need to save the previous engine
1030    * of each input context. */
1031   if (!ibus->use_global_engine) {
1032       BusEngineProxy *previous_engine = bus_input_context_get_engine (context);
1033       if (previous_engine) {
1034           const gchar *name = ibus_engine_desc_get_name (bus_engine_proxy_get_desc (previous_engine));
1035           g_object_set_data_full (G_OBJECT (context), "previous-engine-name",
1036                                   g_strdup (name),
1037                                   g_free);
1038       }
1039   }
1040
1041   bus_input_context_set_engine (context, engine);
1042 }
1043
1044 static void
1045 _context_engine_changed_cb (BusInputContext *context,
1046                             BusIBusImpl     *ibus)
1047 {
1048     BusEngineProxy *engine;
1049
1050     if (context != ibus->focused_context || !ibus->use_global_engine) {
1051         return;
1052     }
1053
1054     engine = bus_input_context_get_engine (context);
1055     if (engine != NULL) {
1056         /* only set global engine if engine is not NULL */
1057         bus_ibus_impl_set_global_engine (ibus, engine);
1058     }
1059 }
1060
1061 static void
1062 _context_focus_out_cb (BusInputContext    *context,
1063                        BusIBusImpl        *ibus)
1064 {
1065     g_assert (BUS_IS_IBUS_IMPL (ibus));
1066     g_assert (BUS_IS_INPUT_CONTEXT (context));
1067
1068     /* Do noting if context does not support focus.
1069      * Actually, the context should emit focus signals, if it does not support focus */
1070     if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
1071         return;
1072     }
1073
1074     /* Do noting if it is not focused context. */
1075     if (ibus->focused_context != context) {
1076         return;
1077     }
1078
1079     ibus->focused_context = NULL;
1080
1081     if (ibus->panel != NULL) {
1082         bus_panel_proxy_focus_out (ibus->panel, context);
1083     }
1084
1085     /* If the use_global_engine option is enabled,
1086      * the global engine shoule be detached from the focused context. */
1087     if (ibus->use_global_engine) {
1088         bus_ibus_impl_set_context_engine (ibus, context, NULL);
1089     }
1090
1091     g_object_unref (context);
1092 }
1093
1094 static void
1095 _context_focus_in_cb (BusInputContext *context,
1096                       BusIBusImpl     *ibus)
1097 {
1098     g_assert (BUS_IS_IBUS_IMPL (ibus));
1099     g_assert (BUS_IS_INPUT_CONTEXT (context));
1100
1101     /* Do nothing if context does not support focus.
1102      * The global engine shoule be detached from the focused context. */
1103     if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
1104         return;
1105     }
1106
1107     /* Do nothing if it is focused context already. */
1108     if (ibus->focused_context == context) {
1109         return;
1110     }
1111
1112     if (ibus->focused_context) {
1113         /* focus out context */
1114         bus_input_context_focus_out (ibus->focused_context);
1115         g_assert (ibus->focused_context == NULL);
1116     }
1117
1118     /* If the use_global_engine option is enabled, then we need:
1119      * - Switch the context to use the global engine or save the context's
1120      *   existing engine as global engine.
1121      * - Set the context's enabled state according to the saved state.
1122      * Note: we get this signal only if the context supports IBUS_CAP_FOCUS. */
1123     if (ibus->use_global_engine) {
1124         if (!ibus->global_engine) {
1125             bus_ibus_impl_set_global_engine (ibus, bus_input_context_get_engine (context));
1126         }
1127         else {
1128             bus_ibus_impl_set_context_engine (ibus, context, ibus->global_engine);
1129             if (ibus->global_engine && bus_engine_proxy_is_enabled (ibus->global_engine)) {
1130                 bus_input_context_enable (context);
1131             }
1132         }
1133     }
1134
1135     if (ibus->panel != NULL) {
1136         bus_panel_proxy_focus_in (ibus->panel, context);
1137     }
1138
1139     g_object_ref (context);
1140     ibus->focused_context = context;
1141 }
1142
1143 static void
1144 _context_destroy_cb (BusInputContext    *context,
1145                      BusIBusImpl        *ibus)
1146 {
1147     g_assert (BUS_IS_IBUS_IMPL (ibus));
1148     g_assert (BUS_IS_INPUT_CONTEXT (context));
1149
1150     if (context == ibus->focused_context) {
1151         /* focus out context */
1152         bus_input_context_focus_out (ibus->focused_context);
1153         g_assert (ibus->focused_context == NULL);
1154     }
1155
1156     ibus->contexts = g_list_remove (ibus->contexts, context);
1157     g_object_unref (context);
1158 }
1159
1160 #if 0
1161 static void
1162 _context_enabled_cb (BusInputContext    *context,
1163                      BusIBusImpl        *ibus)
1164 {
1165 }
1166
1167 static void
1168 _context_disabled_cb (BusInputContext    *context,
1169                       BusIBusImpl        *ibus)
1170 {
1171 }
1172 #endif
1173
1174 static void
1175 _ibus_create_input_context (BusIBusImpl           *ibus,
1176                             GVariant              *parameters,
1177                             GDBusMethodInvocation *invocation)
1178 {
1179     const gchar *client_name = NULL;
1180     g_variant_get (parameters, "(&s)", &client_name);
1181
1182     BusConnection *connection = bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
1183     BusInputContext *context = bus_input_context_new (connection, client_name);
1184     g_object_ref_sink (context);
1185     ibus->contexts = g_list_append (ibus->contexts, context);
1186
1187     static const struct {
1188         gchar *name;
1189         GCallback callback;
1190     } signals [] = {
1191         { "request-engine", G_CALLBACK (_context_request_engine_cb) },
1192         { "engine-changed", G_CALLBACK (_context_engine_changed_cb) },
1193         { "focus-in",       G_CALLBACK (_context_focus_in_cb) },
1194         { "focus-out",      G_CALLBACK (_context_focus_out_cb) },
1195         { "destroy",        G_CALLBACK (_context_destroy_cb) },
1196     #if 0
1197         { "enabled",        G_CALLBACK (_context_enabled_cb) },
1198         { "disabled",       G_CALLBACK (_context_disabled_cb) },
1199     #endif
1200     };
1201
1202     gint i;
1203     for (i = 0; i < G_N_ELEMENTS (signals); i++) {
1204         g_signal_connect (context,
1205                           signals[i].name,
1206                           signals[i].callback,
1207                           ibus);
1208     }
1209
1210     if (ibus->enable_by_default) {
1211         bus_input_context_enable (context);
1212     }
1213
1214     const gchar *path = ibus_service_get_object_path ((IBusService *) context);
1215     bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
1216                                    (IBusService *)context);
1217     g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
1218 }
1219
1220 static void
1221 _ibus_current_input_context (BusIBusImpl           *ibus,
1222                              GVariant              *parameters,
1223                              GDBusMethodInvocation *invocation)
1224 {
1225     if (!ibus->focused_context)
1226     {
1227         g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1228                         "No focused input context");
1229     }
1230     else {
1231         const gchar *path = ibus_service_get_object_path ((IBusService *)ibus->focused_context);
1232         g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
1233     }
1234 }
1235
1236 static void
1237 _factory_destroy_cb (BusFactoryProxy    *factory,
1238                      BusIBusImpl        *ibus)
1239 {
1240     g_assert (BUS_IS_IBUS_IMPL (ibus));
1241     g_assert (BUS_IS_FACTORY_PROXY (factory));
1242
1243     IBusComponent *component;
1244     GList *engines, *p;
1245
1246     ibus->factory_list = g_list_remove (ibus->factory_list, factory);
1247
1248     component = bus_factory_proxy_get_component (factory);
1249
1250     if (component != NULL) {
1251         p = engines = ibus_component_get_engines (component);
1252         for (; p != NULL; p = p->next) {
1253             if (g_list_find (ibus->register_engine_list, p->data)) {
1254                 ibus->register_engine_list = g_list_remove (ibus->register_engine_list, p->data);
1255                 g_object_unref (p->data);
1256             }
1257         }
1258         g_list_free (engines);
1259     }
1260
1261     g_object_unref (factory);
1262
1263     bus_ibus_impl_update_engines_hotkey_profile (ibus);
1264 }
1265
1266 static void
1267 bus_ibus_impl_add_factory (BusIBusImpl     *ibus,
1268                            BusFactoryProxy *factory)
1269 {
1270     g_assert (BUS_IS_IBUS_IMPL (ibus));
1271     g_assert (BUS_IS_FACTORY_PROXY (factory));
1272
1273     g_object_ref_sink (factory);
1274     ibus->factory_list = g_list_append (ibus->factory_list, factory);
1275
1276     g_signal_connect (factory, "destroy", G_CALLBACK (_factory_destroy_cb), ibus);
1277 }
1278
1279
1280 static void
1281 _ibus_register_component (BusIBusImpl           *ibus,
1282                           GVariant              *parameters,
1283                           GDBusMethodInvocation *invocation)
1284 {
1285     GVariant *variant = g_variant_get_child_value (parameters, 0);
1286     IBusComponent *component = (IBusComponent *)ibus_serializable_deserialize (variant);
1287
1288     if (!IBUS_IS_COMPONENT (component)) {
1289         if (component)
1290             g_object_unref (component);
1291         g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1292                         "The first argument should be an IBusComponent.");
1293         return;
1294     }
1295
1296     g_object_ref_sink (component);
1297     BusConnection *connection = bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
1298     BusFactoryProxy *factory = bus_factory_proxy_new (component, connection);
1299
1300     if (factory == NULL) {
1301         g_object_unref (component);
1302         g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1303                         "Create factory failed.");
1304         return;
1305     }
1306
1307     bus_ibus_impl_add_factory (ibus, factory);
1308
1309     GList *engines = ibus_component_get_engines (component);
1310     g_list_foreach (engines, (GFunc) g_object_ref, NULL);
1311     ibus->register_engine_list = g_list_concat (ibus->register_engine_list, engines);
1312     g_object_unref (component);
1313
1314     bus_ibus_impl_update_engines_hotkey_profile (ibus);
1315
1316     g_dbus_method_invocation_return_value (invocation, NULL);
1317 }
1318
1319 static void
1320 _ibus_list_engines (BusIBusImpl           *ibus,
1321                     GVariant              *parameters,
1322                     GDBusMethodInvocation *invocation)
1323 {
1324     GVariantBuilder builder;
1325     g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1326
1327     GList *engines = bus_registry_get_engines (ibus->registry);
1328     GList *p;
1329     for (p = engines; p != NULL; p = p->next) {
1330         g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *)p->data));
1331     }
1332     g_list_free (engines);
1333     g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1334 }
1335
1336 static void
1337 _ibus_list_active_engines (BusIBusImpl           *ibus,
1338                            GVariant              *parameters,
1339                            GDBusMethodInvocation *invocation)
1340 {
1341     GVariantBuilder builder;
1342     g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
1343
1344     GList *p;
1345     for (p = ibus->engine_list; p != NULL; p = p->next) {
1346         g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *)p->data));
1347     }
1348     for (p = ibus->register_engine_list; p != NULL; p = p->next) {
1349         g_variant_builder_add (&builder, "v", ibus_serializable_serialize ((IBusSerializable *)p->data));
1350     }
1351     g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
1352 }
1353
1354
1355 static void
1356 _ibus_exit (BusIBusImpl     *ibus,
1357             GVariant              *parameters,
1358             GDBusMethodInvocation *invocation)
1359 {
1360     gboolean restart = FALSE;
1361     g_variant_get (parameters, "(b)", &restart);
1362
1363     g_dbus_method_invocation_return_value (invocation, NULL);
1364
1365     bus_server_quit ();
1366
1367     if (!restart) {
1368         exit (0);
1369     }
1370     else {
1371         extern gchar **g_argv;
1372         gchar *exe;
1373         gint fd;
1374
1375         exe = g_strdup_printf ("/proc/%d/exe", getpid ());
1376         exe = g_file_read_link (exe, NULL);
1377
1378         if (exe == NULL)
1379             exe = BINDIR"/ibus-daemon";
1380
1381         /* close all fds except stdin, stdout, stderr */
1382         for (fd = 3; fd <= sysconf (_SC_OPEN_MAX); fd ++) {
1383             close (fd);
1384         }
1385
1386         execv (exe, g_argv);
1387
1388         /* If the server binary is replaced while the server is running,
1389          * "readlink /proc/[pid]/exe" might return a path with " (deleted)"
1390          * suffix. */
1391         const gchar suffix[] = " (deleted)";
1392         if (g_str_has_suffix (exe, suffix)) {
1393             exe [strlen (exe) - sizeof (suffix) + 1] = '\0';
1394             execv (exe, g_argv);
1395         }
1396         g_warning ("execv %s failed!", g_argv[0]);
1397         exit (-1);
1398     }
1399
1400     /* should not reach here */
1401     g_assert_not_reached ();
1402 }
1403
1404 static void
1405 _ibus_ping (BusIBusImpl           *ibus,
1406             GVariant              *parameters,
1407             GDBusMethodInvocation *invocation)
1408 {
1409     g_dbus_method_invocation_return_value (invocation, parameters);
1410 }
1411
1412 static void
1413 _ibus_get_use_sys_layout (BusIBusImpl           *ibus,
1414                           GVariant              *parameters,
1415                           GDBusMethodInvocation *invocation)
1416 {
1417     g_dbus_method_invocation_return_value (invocation,
1418                     g_variant_new ("(b)", ibus->use_sys_layout));
1419 }
1420
1421 static void
1422 _ibus_get_use_global_engine (BusIBusImpl           *ibus,
1423                              GVariant              *parameters,
1424                              GDBusMethodInvocation *invocation)
1425 {
1426     g_dbus_method_invocation_return_value (invocation,
1427                     g_variant_new ("(b)", ibus->use_global_engine));
1428 }
1429
1430 static void
1431 _ibus_get_global_engine (BusIBusImpl           *ibus,
1432                          GVariant              *parameters,
1433                          GDBusMethodInvocation *invocation)
1434 {
1435     if (ibus->use_global_engine && ibus->global_engine) {
1436         IBusEngineDesc *desc = bus_engine_proxy_get_desc (ibus->global_engine);
1437         if (desc != NULL) {
1438             GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)desc);
1439             g_dbus_method_invocation_return_value (invocation,
1440                             g_variant_new ("(v)", variant));
1441             return;
1442         }
1443     }
1444     g_dbus_method_invocation_return_error (invocation,
1445                     G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1446                     "No global engine.");
1447 }
1448
1449 static void
1450 _ibus_set_global_engine (BusIBusImpl           *ibus,
1451                          GVariant              *parameters,
1452                          GDBusMethodInvocation *invocation)
1453 {
1454     if (!ibus->use_global_engine) {
1455         g_dbus_method_invocation_return_error (invocation,
1456                         G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1457                         "Global engine feature is disabled.");
1458         return;
1459     }
1460
1461     const gchar *new_engine_name = NULL;
1462     g_variant_get (parameters, "(&s)", &new_engine_name);
1463     const gchar *old_engine_name = NULL;
1464
1465     if (ibus->global_engine) {
1466         old_engine_name = ibus_engine_desc_get_name (bus_engine_proxy_get_desc (ibus->global_engine));
1467     }
1468
1469     if (g_strcmp0 (new_engine_name, old_engine_name) == 0) {
1470         /* If the user requested the same global engine, then we just enable the
1471          * original one. */
1472         if (ibus->focused_context) {
1473             bus_input_context_enable (ibus->focused_context);
1474         }
1475         else if (ibus->global_engine) {
1476             bus_engine_proxy_enable (ibus->global_engine);
1477         }
1478         g_dbus_method_invocation_return_value (invocation, NULL);
1479         return;
1480     }
1481
1482     /* If there is a focused input context, then we just change the engine of
1483      * the focused context, which will then change the global engine
1484      * automatically. Otherwise, we need to change the global engine directly.
1485      */
1486     if (ibus->focused_context) {
1487         _context_request_engine_cb (ibus->focused_context, new_engine_name, ibus);
1488     }
1489     else {
1490         IBusEngineDesc *engine_desc = _find_engine_desc_by_name (ibus, new_engine_name);
1491         if (engine_desc != NULL) {
1492             BusEngineProxy *new_engine = bus_ibus_impl_create_engine (engine_desc);
1493             if (new_engine != NULL) {
1494                 /* Enable the global engine by default, because the user
1495                  * selected it explicitly. */
1496                 bus_engine_proxy_enable (new_engine);
1497
1498                 /* Assume the ownership of the new global engine. Normally it's
1499                  * done by the input context. But as we need to change the global
1500                  * engine directly, so we need to do it here. */
1501                 g_object_ref_sink (new_engine);
1502                 bus_ibus_impl_set_global_engine (ibus, new_engine);
1503
1504                 /* The global engine should already be referenced. */
1505                 g_object_unref (new_engine);
1506             }
1507         }
1508     }
1509     g_dbus_method_invocation_return_value (invocation, NULL);
1510 }
1511
1512 static void
1513 _ibus_is_global_engine_enabled (BusIBusImpl           *ibus,
1514                                 GVariant              *parameters,
1515                                 GDBusMethodInvocation *invocation)
1516 {
1517     gboolean enabled = (ibus->use_global_engine && ibus->global_engine &&
1518                         bus_engine_proxy_is_enabled (ibus->global_engine));
1519     g_dbus_method_invocation_return_value (invocation,
1520                     g_variant_new ("(b)", enabled));
1521 }
1522
1523 static void
1524 bus_ibus_impl_service_method_call (IBusService           *service,
1525                                    GDBusConnection       *connection,
1526                                    const gchar           *sender,
1527                                    const gchar           *object_path,
1528                                    const gchar           *interface_name,
1529                                    const gchar           *method_name,
1530                                    GVariant              *parameters,
1531                                    GDBusMethodInvocation *invocation)
1532 {
1533     if (g_strcmp0 (interface_name, "org.freedesktop.IBus") != 0) {
1534         IBUS_SERVICE_CLASS(bus_ibus_impl_parent_class)->service_method_call (
1535                         service, connection, sender, object_path, interface_name, method_name,
1536                         parameters, invocation);
1537         return;
1538     }
1539
1540     static const struct {
1541         const gchar *method_name;
1542         void (* method_callback) (BusIBusImpl *, GVariant *, GDBusMethodInvocation *);
1543     } methods [] =  {
1544         /* IBus interface */
1545         { "GetAddress",            _ibus_get_address },
1546         { "CreateInputContext",    _ibus_create_input_context },
1547         { "CurrentInputContext",   _ibus_current_input_context },
1548         { "RegisterComponent",     _ibus_register_component },
1549         { "ListEngines",           _ibus_list_engines },
1550         { "ListActiveEngines",     _ibus_list_active_engines },
1551         { "Exit",                  _ibus_exit },
1552         { "Ping",                  _ibus_ping },
1553         { "GetUseSysLayout",       _ibus_get_use_sys_layout },
1554         { "GetUseGlobalEngine",    _ibus_get_use_global_engine },
1555         { "GetGlobalEngine",       _ibus_get_global_engine },
1556         { "SetGlobalEngine",       _ibus_set_global_engine },
1557         { "IsGlobalEngineEnabled", _ibus_is_global_engine_enabled },
1558     };
1559
1560     gint i;
1561     for (i = 0; i < G_N_ELEMENTS (methods); i++) {
1562         if (g_strcmp0 (methods[i].method_name, method_name) == 0) {
1563             methods[i].method_callback ((BusIBusImpl *)service, parameters, invocation);
1564             return;
1565         }
1566     }
1567     g_return_if_reached ();
1568 }
1569
1570 BusIBusImpl *
1571 bus_ibus_impl_get_default (void)
1572 {
1573     static BusIBusImpl *ibus = NULL;
1574
1575     if (ibus == NULL) {
1576         ibus = (BusIBusImpl *) g_object_new (BUS_TYPE_IBUS_IMPL,
1577                                              "object-path", IBUS_PATH_IBUS,
1578                                              NULL);
1579     }
1580     return ibus;
1581 }
1582
1583 BusFactoryProxy *
1584 bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
1585                               const gchar *path)
1586 {
1587     g_assert (BUS_IS_IBUS_IMPL (ibus));
1588
1589     BusFactoryProxy *factory;
1590
1591     factory = (BusFactoryProxy *) g_hash_table_lookup (ibus->factory_dict, path);
1592
1593     return factory;
1594 }
1595
1596 IBusHotkeyProfile *
1597 bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus)
1598 {
1599     g_assert (BUS_IS_IBUS_IMPL (ibus));
1600
1601     return ibus->hotkey_profile;
1602 }
1603
1604 IBusKeymap *
1605 bus_ibus_impl_get_keymap (BusIBusImpl *ibus)
1606 {
1607
1608     g_assert (BUS_IS_IBUS_IMPL (ibus));
1609
1610     return ibus->keymap;
1611 }
1612
1613 BusRegistry *
1614 bus_ibus_impl_get_registry (BusIBusImpl *ibus)
1615 {
1616
1617     g_assert (BUS_IS_IBUS_IMPL (ibus));
1618
1619     return ibus->registry;
1620 }
1621
1622 static void
1623 bus_ibus_impl_emit_signal (BusIBusImpl *ibus,
1624                            const gchar *signal_name,
1625                            GVariant     *parameters)
1626 {
1627
1628     GDBusMessage *message = g_dbus_message_new_signal ("/org/freedesktop/IBus",
1629                                                        "org.freedesktop.DBus",
1630                                                        signal_name);
1631     g_dbus_message_set_sender (message, "org.freedesktop.DBus");
1632     if (parameters)
1633         g_dbus_message_set_body (message, parameters);
1634     bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
1635     g_object_unref (message);
1636 }
1637
1638 static void
1639 bus_ibus_impl_registry_changed (BusIBusImpl *ibus)
1640 {
1641     bus_ibus_impl_emit_signal (ibus, "RegistryChanged", NULL);
1642 }
1643
1644 static void
1645 bus_ibus_impl_global_engine_changed (BusIBusImpl *ibus)
1646 {
1647     bus_ibus_impl_emit_signal (ibus, "GlobalEngineChanged", NULL);
1648 }
1649
1650 gboolean
1651 bus_ibus_impl_filter_keyboard_shortcuts (BusIBusImpl     *ibus,
1652                                          BusInputContext *context,
1653                                          guint           keyval,
1654                                          guint           modifiers,
1655                                          guint           prev_keyval,
1656                                          guint           prev_modifiers)
1657 {
1658     static GQuark trigger = 0;
1659     static GQuark next = 0;
1660     static GQuark previous = 0;
1661
1662     GQuark event;
1663     GList *engine_list;
1664
1665     if (trigger == 0) {
1666         trigger = g_quark_from_static_string ("trigger");
1667         next = g_quark_from_static_string ("next-engine-in-menu");
1668         previous = g_quark_from_static_string ("previous-engine");
1669     }
1670
1671     /* Try global hotkeys first. */
1672     event = ibus_hotkey_profile_filter_key_event (ibus->hotkey_profile,
1673                                                   keyval,
1674                                                   modifiers,
1675                                                   prev_keyval,
1676                                                   prev_modifiers,
1677                                                   0);
1678
1679     if (event == trigger) {
1680         gboolean enabled = bus_input_context_is_enabled (context);
1681         if (enabled) {
1682             bus_input_context_disable (context);
1683         }
1684         else {
1685             bus_input_context_enable (context);
1686         }
1687         return (enabled != bus_input_context_is_enabled (context));
1688     }
1689     if (event == next) {
1690         if (bus_input_context_is_enabled(context)) {
1691             bus_ibus_impl_context_request_next_engine_in_menu (ibus, context);
1692         }
1693         else {
1694             bus_input_context_enable (context);
1695         }
1696         return TRUE;
1697     }
1698     if (event == previous) {
1699         if (bus_input_context_is_enabled(context)) {
1700             bus_ibus_impl_context_request_previous_engine (ibus, context);
1701         }
1702         else {
1703             bus_input_context_enable (context);
1704         }
1705         return TRUE;
1706     }
1707
1708     if (!ibus->engines_hotkey_profile || !ibus->hotkey_to_engines_map) {
1709         return FALSE;
1710     }
1711
1712     /* Then try engines hotkeys. */
1713     event = ibus_hotkey_profile_filter_key_event (ibus->engines_hotkey_profile,
1714                                                   keyval,
1715                                                   modifiers,
1716                                                   prev_keyval,
1717                                                   prev_modifiers,
1718                                                   0);
1719     if (event == 0) {
1720         return FALSE;
1721     }
1722
1723     engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
1724                                        GUINT_TO_POINTER (event));
1725     if (engine_list) {
1726         BusEngineProxy *current_engine = bus_input_context_get_engine (context);
1727         IBusEngineDesc *current_engine_desc =
1728             (current_engine ? bus_engine_proxy_get_desc (current_engine) : NULL);
1729         IBusEngineDesc *new_engine_desc = (IBusEngineDesc *) engine_list->data;
1730
1731         g_assert (new_engine_desc);
1732
1733         /* Find out what engine we should switch to. If the current engine has
1734          * the same hotkey, then we should switch to the next engine with the
1735          * same hotkey in the list. Otherwise, we just switch to the first
1736          * engine in the list. */
1737         GList *p = engine_list;
1738         for (; p->next != NULL; p = p->next) {
1739             if (current_engine_desc == (IBusEngineDesc *) p->data) {
1740                 new_engine_desc = (IBusEngineDesc *) p->next->data;
1741                 break;
1742             }
1743         }
1744
1745         if (current_engine_desc != new_engine_desc) {
1746             bus_ibus_impl_set_context_engine_from_desc (ibus, context, new_engine_desc);
1747         }
1748
1749         return TRUE;
1750     }
1751
1752     return FALSE;
1753 }
1754
1755 static gchar*
1756 bus_ibus_impl_load_global_engine_name_from_config (BusIBusImpl *ibus)
1757 {
1758     g_assert (BUS_IS_IBUS_IMPL (ibus));
1759     g_return_val_if_fail (IBUS_IS_CONFIG (ibus->config), NULL);
1760
1761     GVariant *variant = ibus_config_get_value (ibus->config, "general", "global_engine");
1762     gchar *engine_name = NULL;
1763     if (variant != NULL) {
1764         g_variant_get (variant, "s", &engine_name);
1765         g_variant_unref (variant);
1766     }
1767     return engine_name;
1768 }
1769
1770 static void
1771 bus_ibus_impl_save_global_engine_name_to_config (BusIBusImpl *ibus)
1772 {
1773     g_assert (BUS_IS_IBUS_IMPL (ibus));
1774     g_return_if_fail (IBUS_IS_CONFIG (ibus->config));
1775
1776     if (ibus->use_global_engine && ibus->global_engine) {
1777         IBusEngineDesc *desc = bus_engine_proxy_get_desc (ibus->global_engine);
1778         ibus_config_set_value (ibus->config,
1779                         "general", "global_engine",
1780                         g_variant_new ("s", ibus_engine_desc_get_name (desc)));
1781     }
1782 }
1783
1784 static gchar*
1785 bus_ibus_impl_load_global_previous_engine_name_from_config (BusIBusImpl *ibus)
1786 {
1787     g_assert (BUS_IS_IBUS_IMPL (ibus));
1788     g_return_val_if_fail (IBUS_IS_CONFIG (ibus->config), NULL);
1789
1790     GVariant *value = ibus_config_get_value (ibus->config, "general", "global_previous_engine");
1791     if (value == NULL)
1792         return NULL;
1793     gchar *engine_name = NULL;
1794     g_variant_get (value, "(s)", &engine_name);
1795     g_variant_unref (value);
1796     return engine_name;
1797 }
1798
1799 static void
1800 bus_ibus_impl_save_global_previous_engine_name_to_config (BusIBusImpl *ibus)
1801 {
1802     g_assert (BUS_IS_IBUS_IMPL (ibus));
1803     g_return_if_fail (IBUS_IS_CONFIG (ibus->config));
1804
1805     if (ibus->use_global_engine && ibus->global_previous_engine_name) {
1806         ibus_config_set_value (ibus->config,
1807                         "general", "global_previous_engine",
1808                         g_variant_new ("s", ibus->global_previous_engine_name));
1809     }
1810 }
1811
1812 static void
1813 _add_engine_hotkey (IBusEngineDesc *engine, BusIBusImpl *ibus)
1814 {
1815     const gchar *hotkeys;
1816     gchar **hotkey_list;
1817     gchar **p;
1818     gchar *hotkey;
1819     GList *engine_list;
1820
1821     GQuark event;
1822     guint keyval;
1823     guint modifiers;
1824
1825     if (!engine) {
1826         return;
1827     }
1828
1829     hotkeys = ibus_engine_desc_get_hotkeys (engine);
1830
1831     if (!hotkeys || !*hotkeys) {
1832         return;
1833     }
1834
1835     hotkey_list = g_strsplit_set (hotkeys, ";,", 0);
1836
1837     for (p = hotkey_list; p && *p; ++p) {
1838         hotkey = g_strstrip (*p);
1839         if (!*hotkey || !ibus_key_event_from_string (hotkey, &keyval, &modifiers)) {
1840             continue;
1841         }
1842
1843         /* If the hotkey already exists, we won't need to add it again. */
1844         event = ibus_hotkey_profile_lookup_hotkey (ibus->engines_hotkey_profile,
1845                                                    keyval, modifiers);
1846         if (event == 0) {
1847             event = g_quark_from_string (hotkey);
1848             ibus_hotkey_profile_add_hotkey (ibus->engines_hotkey_profile,
1849                                             keyval, modifiers, event);
1850         }
1851
1852         engine_list = g_hash_table_lookup (ibus->hotkey_to_engines_map,
1853                                            GUINT_TO_POINTER (event));
1854
1855         /* As we will rebuild the engines hotkey map whenever an engine was
1856          * added or removed, we don't need to hold a reference of the engine
1857          * here. */
1858         engine_list = g_list_append (engine_list, engine);
1859
1860         /* We need to steal the value before adding it back, otherwise it will
1861          * be destroyed. */
1862         g_hash_table_steal (ibus->hotkey_to_engines_map, GUINT_TO_POINTER (event));
1863
1864         g_hash_table_insert (ibus->hotkey_to_engines_map,
1865                              GUINT_TO_POINTER (event), engine_list);
1866     }
1867
1868     g_strfreev (hotkey_list);
1869 }
1870
1871 static void
1872 bus_ibus_impl_update_engines_hotkey_profile (BusIBusImpl *ibus)
1873 {
1874     if (ibus->engines_hotkey_profile) {
1875         g_object_unref (ibus->engines_hotkey_profile);
1876     }
1877
1878     if (ibus->hotkey_to_engines_map) {
1879         g_hash_table_unref (ibus->hotkey_to_engines_map);
1880     }
1881
1882     ibus->engines_hotkey_profile = ibus_hotkey_profile_new();
1883     ibus->hotkey_to_engines_map =
1884         g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_list_free);
1885
1886     g_list_foreach (ibus->register_engine_list, (GFunc) _add_engine_hotkey, ibus);
1887     g_list_foreach (ibus->engine_list, (GFunc) _add_engine_hotkey, ibus);
1888 }
1889
1890 gboolean
1891 bus_ibus_impl_is_use_sys_layout (BusIBusImpl *ibus)
1892 {
1893     g_assert (BUS_IS_IBUS_IMPL(ibus));
1894
1895     return ibus->use_sys_layout;
1896 }
1897
1898 BusInputContext *
1899 bus_ibus_impl_get_focused_input_context (BusIBusImpl *ibus)
1900 {
1901     g_assert (BUS_IS_IBUS_IMPL(ibus));
1902
1903     return ibus->focused_context;
1904 }