Change the default setting of use_global_engine, and remove some unused
[platform/upstream/ibus.git] / bus / ibusimpl.c
1 /* vim:set et sts=4: */
2 /* ibus - The Input Bus
3  * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
4  * Copyright (C) 2008-2010 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include <unistd.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <signal.h>
26 #include <stdlib.h>
27 #include <locale.h>
28 #include <strings.h>
29 #include "ibusimpl.h"
30 #include "dbusimpl.h"
31 #include "server.h"
32 #include "connection.h"
33 #include "registry.h"
34 #include "factoryproxy.h"
35 #include "panelproxy.h"
36 #include "inputcontext.h"
37 #include "option.h"
38
39 enum {
40     LAST_SIGNAL,
41 };
42
43 enum {
44     PROP_0,
45 };
46
47 // static guint            _signals[LAST_SIGNAL] = { 0 };
48
49 /* functions prototype */
50 static void     bus_ibus_impl_destroy           (BusIBusImpl        *ibus);
51 static gboolean bus_ibus_impl_ibus_message      (BusIBusImpl        *ibus,
52                                                  BusConnection      *connection,
53                                                  IBusMessage        *message);
54 static void     bus_ibus_impl_add_factory       (BusIBusImpl        *ibus,
55                                                  BusFactoryProxy    *factory);
56 static void     bus_ibus_impl_set_trigger       (BusIBusImpl        *ibus,
57                                                  GValue             *value);
58 static void     bus_ibus_impl_set_preload_engines
59                                                 (BusIBusImpl        *ibus,
60                                                  GValue             *value);
61 static void     bus_ibus_impl_set_use_sys_layout
62                                                 (BusIBusImpl        *ibus,
63                                                  GValue             *value);
64 static void     bus_ibus_impl_set_embed_preedit_text
65                                                 (BusIBusImpl        *ibus,
66                                                  GValue             *value);
67
68 static void     bus_ibus_impl_set_use_global_engine
69                                                 (BusIBusImpl        *ibus,
70                                                  GValue             *value);
71 static void     bus_ibus_impl_set_global_engine (BusIBusImpl        *ibus,
72                                                  BusEngineProxy     *engine);
73
74 static void     bus_ibus_impl_registry_changed  (BusIBusImpl        *ibus);
75 static void     _factory_destroy_cb             (BusFactoryProxy    *factory,
76                                                  BusIBusImpl        *ibus);
77
78 G_DEFINE_TYPE(BusIBusImpl, bus_ibus_impl, IBUS_TYPE_SERVICE)
79
80 BusIBusImpl *
81 bus_ibus_impl_get_default (void)
82 {
83     static BusIBusImpl *ibus = NULL;
84
85     if (ibus == NULL) {
86         ibus = (BusIBusImpl *) g_object_new (BUS_TYPE_IBUS_IMPL,
87                                              "path", IBUS_PATH_IBUS,
88                                              NULL);
89         bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
90                                        (IBusService *)ibus);
91     }
92     return ibus;
93 }
94
95 static void
96 bus_ibus_impl_class_init (BusIBusImplClass *klass)
97 {
98     IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
99
100     ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_ibus_impl_destroy;
101
102     IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) bus_ibus_impl_ibus_message;
103
104 }
105
106 static void
107 _panel_destroy_cb (BusPanelProxy *panel,
108                    BusIBusImpl   *ibus)
109 {
110     g_assert (BUS_IS_PANEL_PROXY (panel));
111     g_assert (BUS_IS_IBUS_IMPL (ibus));
112
113     g_return_if_fail (ibus->panel == panel);
114
115     ibus->panel = NULL;
116     g_object_unref (panel);
117 }
118
119 static void
120 bus_ibus_impl_set_hotkey (BusIBusImpl *ibus,
121                           GQuark       hotkey,
122                           GValue      *value)
123 {
124     g_assert (BUS_IS_IBUS_IMPL (ibus));
125
126     GValueArray *array;
127     gint i;
128
129     ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
130
131     if (value == NULL) {
132         return;
133     }
134
135     g_return_if_fail (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
136     array = g_value_get_boxed (value);
137
138     for (i = 0; i < array->n_values; i++) {
139        GValue *str;
140
141        str = g_value_array_get_nth (array, i);
142        g_return_if_fail (G_VALUE_TYPE (str) == G_TYPE_STRING);
143
144        ibus_hotkey_profile_add_hotkey_from_string (ibus->hotkey_profile,
145                                                    g_value_get_string (str),
146                                                    hotkey);
147    }
148
149 }
150
151 static void
152 bus_ibus_impl_set_trigger (BusIBusImpl *ibus,
153                            GValue      *value)
154 {
155     GQuark hotkey = g_quark_from_static_string ("trigger");
156     bus_ibus_impl_set_hotkey (ibus, hotkey, value);
157     if (value == NULL) {
158         ibus_hotkey_profile_add_hotkey (ibus->hotkey_profile,
159                                         IBUS_space,
160                                         IBUS_CONTROL_MASK,
161                                         hotkey);
162     }
163 }
164
165 static void
166 bus_ibus_impl_set_next_engine (BusIBusImpl *ibus,
167                                GValue      *value)
168 {
169     GQuark hotkey = g_quark_from_static_string ("next-engine");
170     bus_ibus_impl_set_hotkey (ibus, hotkey, value);
171 }
172
173 static void
174 bus_ibus_impl_set_prev_engine (BusIBusImpl *ibus,
175                                GValue      *value)
176 {
177     GQuark hotkey = g_quark_from_static_string ("prev-engine");
178     bus_ibus_impl_set_hotkey (ibus, hotkey, value);
179 }
180
181 static void
182 bus_ibus_impl_set_preload_engines (BusIBusImpl *ibus,
183                                    GValue      *value)
184 {
185     GList *engine_list = NULL;
186
187     g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
188     g_list_free (ibus->engine_list);
189
190     if (value != NULL && G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY) {
191         GValueArray *array;
192         gint i;
193
194         array = (GValueArray *) g_value_get_boxed (value);
195         for (i = 0; array && i < array->n_values; i++) {
196             const gchar *engine_name;
197             IBusEngineDesc *engine;
198
199             if (G_VALUE_TYPE (&array->values[i]) != G_TYPE_STRING)
200                 continue;
201
202             engine_name = g_value_get_string (&array->values[i]);
203
204             engine = bus_registry_find_engine_by_name (ibus->registry, engine_name);
205
206             if (engine == NULL || g_list_find (engine_list, engine) != NULL)
207                 continue;
208
209             engine_list = g_list_append (engine_list, engine);
210         }
211     }
212
213     g_list_foreach (engine_list, (GFunc) g_object_ref, NULL);
214     ibus->engine_list = engine_list;
215
216     if (ibus->engine_list) {
217         IBusComponent *component;
218
219         component = ibus_component_get_from_engine ((IBusEngineDesc *) ibus->engine_list->data);
220         if (component && !ibus_component_is_running (component)) {
221             ibus_component_start (component, g_verbose);
222         }
223     }
224 }
225
226 static void
227 bus_ibus_impl_set_use_sys_layout (BusIBusImpl *ibus,
228                                   GValue      *value)
229 {
230     if (value != NULL && G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) {
231         ibus->use_sys_layout = g_value_get_boolean (value);
232     }
233 }
234
235 static void
236 bus_ibus_impl_set_embed_preedit_text (BusIBusImpl        *ibus,
237                                                              GValue             *value){
238     if (value != NULL && G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) {
239         ibus->embed_preedit_text = g_value_get_boolean (value);
240     }
241
242 }
243
244 static void
245 bus_ibus_impl_set_use_global_engine (BusIBusImpl *ibus,
246                                      GValue      *value)
247 {
248     gboolean new_value;
249
250     if (value == NULL || G_VALUE_TYPE (value) != G_TYPE_BOOLEAN) {
251         return;
252     }
253
254     new_value = g_value_get_boolean (value);
255     if (ibus->use_global_engine == new_value) {
256         return;
257     }
258
259     if (new_value == TRUE) {
260         /* turn on use_global_engine option */
261         ibus->use_global_engine = TRUE;
262         if (ibus->focused_context != NULL)
263             bus_ibus_impl_set_global_engine (ibus, bus_input_context_get_engine (ibus->focused_context));
264     }
265     else {
266         /* turn off use_global_engine option */
267         bus_ibus_impl_set_global_engine (ibus, NULL);
268         ibus->use_global_engine = FALSE;
269     }
270 }
271
272 static gint
273 _engine_desc_cmp (IBusEngineDesc *desc1,
274                   IBusEngineDesc *desc2)
275 {
276     return - ((gint) desc1->rank) + ((gint) desc2->rank);
277 }
278
279 static void
280 bus_ibus_impl_set_default_preload_engines (BusIBusImpl *ibus)
281 {
282     g_assert (BUS_IS_IBUS_IMPL (ibus));
283
284     static gboolean done = FALSE;
285     GValue value = { 0 };
286     GList *engines, *list;
287     gchar *lang, *p;
288     GValueArray *array;
289
290     if (done || ibus->config == NULL) {
291         return;
292     }
293
294     if (ibus_config_get_value (ibus->config, "general", "preload_engines", &value)) {
295         done = TRUE;
296         g_value_unset (&value);
297         return;
298     }
299
300     done = TRUE;
301     lang = g_strdup (setlocale (LC_ALL, NULL));
302     p = index (lang, '.');
303     if (p) {
304         *p = '\0';
305     }
306
307     engines = bus_registry_get_engines_by_language (ibus->registry, lang);
308     if (engines == NULL) {
309         p = index (lang, '_');
310         if (p) {
311             *p = '\0';
312             engines = bus_registry_get_engines_by_language (ibus->registry, lang);
313         }
314     }
315     g_free (lang);
316
317     /* sort engines by rank */
318     engines = g_list_sort (engines, (GCompareFunc) _engine_desc_cmp);
319
320     g_value_init (&value, G_TYPE_VALUE_ARRAY);
321     array = g_value_array_new (5);
322     for (list = engines; list != NULL; list = list->next) {
323         IBusEngineDesc *desc;
324         GValue name = { 0 };
325         desc = (IBusEngineDesc *)list->data;
326
327         /* ignore engines with rank <== 0 */
328         if (desc->rank <= 0)
329             break;
330         g_value_init (&name, G_TYPE_STRING);
331         g_value_set_string (&name, desc->name);
332         g_value_array_append (array, &name);
333     }
334     g_value_take_boxed (&value, array);
335     ibus_config_set_value (ibus->config, "general", "preload_engines", &value);
336     g_value_unset (&value);
337     g_list_free (engines);
338 }
339
340 static void
341 bus_ibus_impl_reload_config (BusIBusImpl *ibus)
342 {
343     g_assert (BUS_IS_IBUS_IMPL (ibus));
344
345     gint i;
346     GValue value = { 0 };
347
348     const static struct {
349         gchar *section;
350         gchar *key;
351         void ( *func) (BusIBusImpl *, GValue *);
352     } entries [] = {
353         { "general/hotkey", "trigger", bus_ibus_impl_set_trigger },
354         { "general/hotkey", "next_engine", bus_ibus_impl_set_next_engine },
355         { "general/hotkey", "prev_engine", bus_ibus_impl_set_prev_engine },
356         { "general", "preload_engines", bus_ibus_impl_set_preload_engines },
357         { "general", "use_system_keyboard_layout", bus_ibus_impl_set_use_sys_layout },
358         { "general", "use_global_engine", bus_ibus_impl_set_use_global_engine },
359         { "general", "embed_preedit_text", bus_ibus_impl_set_embed_preedit_text },
360         { NULL, NULL, NULL },
361     };
362
363     for (i = 0; entries[i].section != NULL; i++) {
364         if (ibus->config != NULL &&
365             ibus_config_get_value (ibus->config,
366                                    entries[i].section,
367                                    entries[i].key,
368                                    &value)) {
369             entries[i].func (ibus, &value);
370             g_value_unset (&value);
371         }
372         else {
373             entries[i].func (ibus, NULL);
374         }
375     }
376 }
377
378 static void
379 _config_value_changed_cb (IBusConfig  *config,
380                           gchar       *section,
381                           gchar       *key,
382                           GValue      *value,
383                           BusIBusImpl *ibus)
384 {
385     g_assert (IBUS_IS_CONFIG (config));
386     g_assert (section);
387     g_assert (key);
388     g_assert (value);
389     g_assert (BUS_IS_IBUS_IMPL (ibus));
390
391     gint i;
392
393     const static struct {
394         gchar *section;
395         gchar *key;
396         void ( *func) (BusIBusImpl *, GValue *);
397     } entries [] = {
398         { "general/hotkey", "trigger",     bus_ibus_impl_set_trigger },
399         { "general/hotkey", "next_engine", bus_ibus_impl_set_next_engine },
400         { "general/hotkey", "prev_engine", bus_ibus_impl_set_prev_engine },
401         { "general", "preload_engines",    bus_ibus_impl_set_preload_engines },
402         { "general", "use_system_keyboard_layout", bus_ibus_impl_set_use_sys_layout },
403         { "general", "use_global_engine", bus_ibus_impl_set_use_global_engine },
404         { "general", "embed_preedit_text", bus_ibus_impl_set_embed_preedit_text },
405         { NULL, NULL, NULL },
406     };
407
408     for (i = 0; entries[i].section != NULL; i++) {
409         if (g_strcmp0 (entries[i].section, section) == 0 &&
410             g_strcmp0 (entries[i].key, key) == 0) {
411             entries[i].func (ibus, value);
412             break;
413         }
414     }
415 }
416
417 static void
418 _config_destroy_cb (IBusConfig  *config,
419                     BusIBusImpl *ibus)
420 {
421     g_assert (IBUS_IS_CONFIG (config));
422     g_assert (BUS_IS_IBUS_IMPL (ibus));
423
424     g_assert (ibus->config == config);
425
426     g_object_unref (ibus->config);
427     ibus->config = NULL;
428 }
429
430 static void
431 _registry_changed_cb (BusRegistry *registry,
432                       BusIBusImpl *ibus)
433 {
434     bus_ibus_impl_registry_changed (ibus);
435 }
436
437 static void
438 _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
439                              const gchar *name,
440                              const gchar *old_name,
441                              const gchar *new_name,
442                              BusIBusImpl *ibus)
443 {
444     g_assert (BUS_IS_DBUS_IMPL (dbus));
445     g_assert (name != NULL);
446     g_assert (old_name != NULL);
447     g_assert (new_name != NULL);
448     g_assert (BUS_IS_IBUS_IMPL (ibus));
449
450     BusFactoryProxy *factory;
451
452     if (g_strcmp0 (name, IBUS_SERVICE_PANEL) == 0) {
453         if (g_strcmp0 (new_name, "") != 0) {
454             BusConnection *connection;
455
456             if (ibus->panel != NULL) {
457                 ibus_object_destroy (IBUS_OBJECT (ibus->panel));
458                 /* panel should be NULL after destroy */
459                 g_assert (ibus->panel == NULL);
460             }
461
462             connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
463             g_return_if_fail (connection != NULL);
464
465             ibus->panel = bus_panel_proxy_new (connection);
466             g_object_ref_sink (ibus->panel);
467
468             g_signal_connect (ibus->panel,
469                               "destroy",
470                               G_CALLBACK (_panel_destroy_cb),
471                               ibus);
472
473             if (ibus->focused_context != NULL) {
474                 bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context);
475             }
476         }
477     }
478     else if (g_strcmp0 (name, IBUS_SERVICE_CONFIG) == 0) {
479         if (g_strcmp0 (new_name, "") != 0) {
480             BusConnection *connection;
481
482             if (ibus->config != NULL) {
483                 ibus_object_destroy (IBUS_OBJECT (ibus->config));
484                 /* config should be NULL */
485                 g_assert (ibus->config == NULL);
486             }
487
488             connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
489             g_return_if_fail (connection != NULL);
490
491             ibus->config = g_object_new (IBUS_TYPE_CONFIG,
492                                          "name", NULL,
493                                          "path", IBUS_PATH_CONFIG,
494                                          "connection", connection,
495                                          NULL);
496             g_object_ref_sink (ibus->config);
497
498             g_signal_connect (ibus->config,
499                               "value-changed",
500                               G_CALLBACK (_config_value_changed_cb),
501                               ibus);
502
503             g_signal_connect (ibus->config,
504                               "destroy",
505                               G_CALLBACK (_config_destroy_cb),
506                               ibus);
507
508             bus_ibus_impl_set_default_preload_engines (ibus);
509             bus_ibus_impl_reload_config (ibus);
510         }
511     }
512
513     factory = bus_registry_name_owner_changed (ibus->registry, name, old_name, new_name);
514
515     if (factory) {
516         bus_ibus_impl_add_factory (ibus, factory);
517     }
518 }
519
520 static void
521 bus_ibus_impl_init (BusIBusImpl *ibus)
522 {
523     ibus->factory_dict = g_hash_table_new_full (
524                             g_str_hash,
525                             g_str_equal,
526                             NULL,
527                             (GDestroyNotify) g_object_unref);
528
529     ibus->engine_list = NULL;
530     ibus->register_engine_list = NULL;
531     ibus->contexts = NULL;
532     ibus->focused_context = NULL;
533     ibus->panel = NULL;
534     ibus->config = NULL;
535
536     ibus->registry = bus_registry_new ();
537
538     g_signal_connect (ibus->registry,
539                       "changed",
540                       G_CALLBACK (_registry_changed_cb),
541                       ibus);
542 #ifdef G_THREADS_ENABLED
543     extern gint g_monitor_timeout;
544     if (g_monitor_timeout != 0) {
545         bus_registry_start_monitor_changes (ibus->registry);
546     }
547 #endif
548
549     ibus->hotkey_profile = ibus_hotkey_profile_new ();
550     ibus->keymap = ibus_keymap_get ("us");
551
552     ibus->use_sys_layout = FALSE;
553     ibus->embed_preedit_text = TRUE;
554     ibus->use_global_engine = FALSE;
555     ibus->global_engine = NULL;
556
557     bus_ibus_impl_reload_config (ibus);
558
559     g_signal_connect (BUS_DEFAULT_DBUS,
560                       "name-owner-changed",
561                       G_CALLBACK (_dbus_name_owner_changed_cb),
562                       ibus);
563 }
564
565 static void
566 bus_ibus_impl_destroy (BusIBusImpl *ibus)
567 {
568     pid_t pid;
569     glong timeout;
570     gint status;
571     gboolean flag;
572
573     bus_registry_stop_all_components (ibus->registry);
574
575     pid = 0;
576     timeout = 0;
577     flag = FALSE;
578     while (1) {
579         while ((pid = waitpid (0, &status, WNOHANG)) > 0);
580
581         if (pid == -1) { /* all children finished */
582             break;
583         }
584         if (pid == 0) { /* no child status changed */
585             g_usleep (1000);
586             timeout += 1000;
587             if (timeout >= G_USEC_PER_SEC) {
588                 if (flag == FALSE) {
589                     gpointer old;
590                     old = signal (SIGTERM, SIG_IGN);
591                     kill (-getpid (), SIGTERM);
592                     signal (SIGTERM, old);
593                     flag = TRUE;
594                 }
595                 else {
596                     g_warning ("Not every child processes exited!");
597                     break;
598                 }
599             }
600         }
601     };
602
603     g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
604     g_list_free (ibus->engine_list);
605     ibus->engine_list = NULL;
606
607     g_list_foreach (ibus->register_engine_list, (GFunc) g_object_unref, NULL);
608     g_list_free (ibus->register_engine_list);
609     ibus->register_engine_list = NULL;
610
611     if (ibus->factory_dict != NULL) {
612         g_hash_table_destroy (ibus->factory_dict);
613         ibus->factory_dict = NULL;
614     }
615
616     if (ibus->hotkey_profile != NULL) {
617         g_object_unref (ibus->hotkey_profile);
618         ibus->hotkey_profile = NULL;
619     }
620
621     if (ibus->keymap != NULL) {
622         g_object_unref (ibus->keymap);
623         ibus->keymap = NULL;
624     }
625
626     if (ibus->global_engine) {
627         g_object_unref (ibus->global_engine);
628         ibus->global_engine = NULL;
629     }
630
631     bus_server_quit (BUS_DEFAULT_SERVER);
632     ibus_object_destroy ((IBusObject *) BUS_DEFAULT_SERVER);
633     IBUS_OBJECT_CLASS(bus_ibus_impl_parent_class)->destroy (IBUS_OBJECT (ibus));
634 }
635
636 /* introspectable interface */
637 static IBusMessage *
638 _ibus_introspect (BusIBusImpl     *ibus,
639                   IBusMessage     *message,
640                   BusConnection   *connection)
641 {
642     static const gchar *introspect =
643         DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
644         "<node>\n"
645         "  <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
646         "    <method name=\"Introspect\">\n"
647         "      <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
648         "    </method>\n"
649         "  </interface>\n"
650         "  <interface name=\"org.freedesktop.IBus\">\n"
651         "    <method name=\"GetAddress\">\n"
652         "      <arg name=\"address\" direction=\"out\" type=\"s\"/>\n"
653         "    </method>\n"
654         "    <method name=\"CreateInputContext\">\n"
655         "      <arg name=\"name\" direction=\"in\" type=\"s\"/>\n"
656         "      <arg name=\"context\" direction=\"out\" type=\"o\"/>\n"
657         "    </method>\n"
658         "    <method name=\"CurrentInputContext\">\n"
659         "      <arg name=\"name\" direction=\"out\" type=\"s\"/>\n"
660         "    </method>\n"
661         "    <method name=\"RegisterComponent\">\n"
662         "      <arg name=\"components\" direction=\"in\" type=\"v\"/>\n"
663         "    </method>\n"
664         "    <method name=\"ListEngines\">\n"
665         "      <arg name=\"engines\" direction=\"out\" type=\"av\"/>\n"
666         "    </method>\n"
667         "    <method name=\"ListActiveEngines\">\n"
668         "      <arg name=\"engines\" direction=\"out\" type=\"av\"/>\n"
669         "    </method>\n"
670         "    <method name=\"Exit\">\n"
671         "      <arg name=\"restart\" direction=\"in\" type=\"b\"/>\n"
672         "    </method>\n"
673         "    <method name=\"Ping\">\n"
674         "      <arg name=\"data\" direction=\"in\" type=\"v\"/>\n"
675         "      <arg name=\"data\" direction=\"out\" type=\"v\"/>\n"
676         "    </method>\n"
677         "    <signal name=\"RegistryChanged\">\n"
678         "    </signal>\n"
679         "  </interface>\n"
680         "</node>\n";
681
682     IBusMessage *reply_message;
683     reply_message = ibus_message_new_method_return (message);
684     ibus_message_append_args (reply_message,
685                               G_TYPE_STRING, &introspect,
686                               G_TYPE_INVALID);
687
688     return reply_message;
689 }
690
691
692
693 static IBusMessage *
694 _ibus_get_address (BusIBusImpl     *ibus,
695                    IBusMessage     *message,
696                    BusConnection   *connection)
697 {
698     const gchar *address;
699     IBusMessage *reply;
700
701     address = ibus_server_get_address (IBUS_SERVER (BUS_DEFAULT_SERVER));
702
703     reply = ibus_message_new_method_return (message);
704     ibus_message_append_args (reply,
705                               G_TYPE_STRING, &address,
706                               G_TYPE_INVALID);
707
708     return reply;
709 }
710
711 static BusEngineProxy *
712 bus_ibus_impl_create_engine (IBusEngineDesc *engine_desc)
713 {
714     IBusComponent *comp;
715     BusFactoryProxy *factory;
716     BusEngineProxy *engine;
717     GTimeVal t1, t2;
718
719     factory = bus_factory_proxy_get_from_engine (engine_desc);
720
721     if (factory == NULL) {
722         /* try to execute the engine */
723         comp = ibus_component_get_from_engine (engine_desc);
724         g_assert (comp);
725
726         if (!ibus_component_is_running (comp)) {
727             ibus_component_start (comp, g_verbose);
728             g_get_current_time (&t1);
729             while (1) {
730                 if (g_main_context_pending (NULL)) {
731                     g_main_context_iteration (NULL, FALSE);
732                     factory = bus_factory_proxy_get_from_engine (engine_desc);
733                     if (factory != NULL) {
734                         break;
735                     }
736                 }
737                 g_get_current_time (&t2);
738                 if (t2.tv_sec - t1.tv_sec >= 5)
739                     break;
740             }
741         }
742         else {
743             factory = bus_factory_proxy_get_from_engine (engine_desc);
744         }
745     }
746
747     if (factory == NULL) {
748         return NULL;
749     }
750
751     g_object_ref (factory);
752     engine = bus_factory_proxy_create_engine (factory, engine_desc);
753     g_object_unref (factory);
754
755     return engine;
756 }
757
758 static IBusEngineDesc *
759 _find_engine_desc_by_name(BusIBusImpl *ibus,
760                           gchar *engine_name)
761 {
762     IBusEngineDesc *engine_desc = NULL;
763     GList *p;
764
765     /* find engine in registered engine list */
766     for (p = ibus->register_engine_list; p != NULL; p = p->next) {
767         engine_desc = (IBusEngineDesc *)p->data;
768         if (g_strcmp0 (engine_desc->name, engine_name) == 0)
769             return engine_desc;
770     }
771
772     /* find engine in preload engine list */
773     for (p = ibus->engine_list; p != NULL; p = p->next) {
774         engine_desc = (IBusEngineDesc *)p->data;
775         if (g_strcmp0 (engine_desc->name, engine_name) == 0)
776             return engine_desc;
777     }
778
779     return NULL;
780 }
781
782 static void
783 _context_request_engine_cb (BusInputContext *context,
784                             gchar           *engine_name,
785                             BusIBusImpl     *ibus)
786 {
787     IBusEngineDesc *engine_desc = NULL;
788     BusEngineProxy *engine;
789
790     /* context should has focus before request an engine */
791     g_return_if_fail (bus_input_context_has_focus (context));
792
793     if (engine_name == NULL || engine_name[0] == '\0') {
794         /* request default engine */
795         if (ibus->register_engine_list) {
796             engine_desc = (IBusEngineDesc *)ibus->register_engine_list->data;
797         }
798         else if (ibus->engine_list) {
799             engine_desc = (IBusEngineDesc *)ibus->engine_list->data;
800         }
801     }
802     else {
803         /* request engine by name */
804         engine_desc = _find_engine_desc_by_name (ibus, engine_name);
805     }
806
807     if (engine_desc != NULL) {
808         engine = bus_ibus_impl_create_engine (engine_desc);
809         if (engine != NULL) {
810             bus_input_context_set_engine (context, engine);
811         }
812     }
813 }
814
815 static void
816 _context_request_next_engine_cb (BusInputContext *context,
817                                  BusIBusImpl     *ibus)
818 {
819     BusEngineProxy *engine;
820     IBusEngineDesc *desc;
821     IBusEngineDesc *next_desc = NULL;
822     GList *p;
823
824     engine = bus_input_context_get_engine (context);
825     if (engine == NULL) {
826         _context_request_engine_cb (context, NULL, ibus);
827         return;
828     }
829
830     desc = bus_engine_proxy_get_desc (engine);
831
832     p = g_list_find (ibus->register_engine_list, desc);
833     if (p != NULL) {
834         p = p->next;
835     }
836     if (p == NULL) {
837         p = g_list_find (ibus->engine_list, desc);
838         if (p != NULL) {
839             p = p->next;
840         }
841     }
842
843     if (p != NULL) {
844         next_desc = (IBusEngineDesc*) p->data;
845     }
846     else {
847         if (ibus->register_engine_list) {
848             next_desc = (IBusEngineDesc *)ibus->register_engine_list->data;
849         }
850         else if (ibus->engine_list) {
851             next_desc = (IBusEngineDesc *)ibus->engine_list->data;
852         }
853     }
854
855     if (next_desc != NULL) {
856         engine = bus_ibus_impl_create_engine (next_desc);
857         if (engine != NULL) {
858             bus_input_context_set_engine (context, engine);
859         }
860     }
861 }
862
863 static void
864 _context_request_prev_engine_cb (BusInputContext *context,
865                                  BusIBusImpl     *ibus)
866 {
867
868 }
869
870 static void
871 _global_engine_destroy_cb (BusEngineProxy *engine,
872                            BusIBusImpl    *ibus)
873 {
874     if (ibus->global_engine != engine) {
875         return;
876     }
877
878     g_signal_handlers_disconnect_by_func (ibus->global_engine,
879                 G_CALLBACK (_global_engine_destroy_cb), ibus);
880     g_object_unref (ibus->global_engine);
881     ibus->global_engine = NULL;
882 }
883
884 static void
885 bus_ibus_impl_set_global_engine (BusIBusImpl    *ibus,
886                                  BusEngineProxy *engine)
887 {
888     g_assert (ibus->use_global_engine == TRUE);
889
890     if (ibus->global_engine == engine) {
891         return;
892     }
893
894     if (ibus->global_engine) {
895         ibus_object_destroy ((IBusObject *)ibus->global_engine);
896         /* global_engine should be NULL */
897         g_assert (ibus->global_engine == NULL);
898     }
899
900     if (engine != NULL && !IBUS_OBJECT_DESTROYED (engine)) {
901         g_object_ref (engine);
902         ibus->global_engine = engine;
903         g_signal_connect (ibus->global_engine, "destroy",
904                 G_CALLBACK (_global_engine_destroy_cb), ibus);
905     }
906 }
907
908 static void
909 _context_engine_changed_cb (BusInputContext *context,
910                             BusIBusImpl     *ibus)
911 {
912     BusEngineProxy *engine;
913
914     if (context != ibus->focused_context ||
915         ibus->use_global_engine != TRUE) {
916         return;
917     }
918
919     engine = bus_input_context_get_engine (context);
920     bus_ibus_impl_set_global_engine (ibus, engine);
921 }
922
923 static void
924 _context_focus_out_cb (BusInputContext    *context,
925                        BusIBusImpl        *ibus)
926 {
927     g_assert (BUS_IS_IBUS_IMPL (ibus));
928     g_assert (BUS_IS_INPUT_CONTEXT (context));
929
930     /* Do noting if context does not support focus.
931      * Actually, the context should emit focus signals, if it does not support focus */
932     if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
933         return;
934     }
935
936     /* Do noting if it is not focused context. */
937     if (ibus->focused_context != context) {
938         return;
939     }
940
941     ibus->focused_context = NULL;
942
943     if (ibus->panel != NULL) {
944         bus_panel_proxy_focus_out (ibus->panel, context);
945     }
946
947     /* If the use_global_engine option is enabled,
948      * the global engine shoule be detached from the focused context. */
949     if (ibus->use_global_engine) {
950         bus_input_context_set_engine (context, NULL);
951     }
952
953     g_object_unref (context);
954 }
955
956 static void
957 _context_focus_in_cb (BusInputContext *context,
958                       BusIBusImpl     *ibus)
959 {
960     g_assert (BUS_IS_IBUS_IMPL (ibus));
961     g_assert (BUS_IS_INPUT_CONTEXT (context));
962
963     /* Do nothing if context does not support focus.
964      * The global engine shoule be detached from the focused context. */
965     if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
966         return;
967     }
968
969     /* Do nothing if it is focused context already. */
970     if (ibus->focused_context == context) {
971         return;
972     }
973
974     if (ibus->focused_context) {
975         /* focus out context */
976         bus_input_context_focus_out (ibus->focused_context);
977         g_assert (ibus->focused_context == NULL);
978     }
979
980     g_object_ref (context);
981     ibus->focused_context = context;
982
983     /* If the use_global_engine option is enabled, then we need:
984      * - Switch the context to use the global engine or save the context's
985      *   existing engine as global engine.
986      * - Set the context's enabled state according to the saved state.
987      * Note: we get this signal only if the context supports IBUS_CAP_FOCUS. */
988     if (ibus->use_global_engine) {
989         bus_input_context_set_engine (context, ibus->global_engine);
990         if (ibus->global_engine &&
991             bus_engine_proxy_is_enabled (ibus->global_engine)) {
992             bus_input_context_enable (context);
993         }
994     }
995
996     if (ibus->panel != NULL) {
997         bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context);
998     }
999 }
1000
1001 static void
1002 _context_destroy_cb (BusInputContext    *context,
1003                      BusIBusImpl        *ibus)
1004 {
1005     g_assert (BUS_IS_IBUS_IMPL (ibus));
1006     g_assert (BUS_IS_INPUT_CONTEXT (context));
1007
1008     if (context == ibus->focused_context) {
1009         /* focus out context */
1010         bus_input_context_focus_out (ibus->focused_context);
1011         g_assert (ibus->focused_context == NULL);
1012     }
1013
1014     ibus->contexts = g_list_remove (ibus->contexts, context);
1015     g_object_unref (context);
1016 }
1017
1018 #if 0
1019 static void
1020 _context_enabled_cb (BusInputContext    *context,
1021                      BusIBusImpl        *ibus)
1022 {
1023 }
1024
1025 static void
1026 _context_disabled_cb (BusInputContext    *context,
1027                       BusIBusImpl        *ibus)
1028 {
1029 }
1030 #endif
1031
1032 static IBusMessage *
1033 _ibus_create_input_context (BusIBusImpl     *ibus,
1034                             IBusMessage     *message,
1035                             BusConnection   *connection)
1036 {
1037     g_assert (BUS_IS_IBUS_IMPL (ibus));
1038     g_assert (message != NULL);
1039     g_assert (BUS_IS_CONNECTION (connection));
1040
1041     gint i;
1042     gchar *client;
1043     IBusError *error;
1044     IBusMessage *reply;
1045     BusInputContext *context;
1046     const gchar *path;
1047
1048     if (!ibus_message_get_args (message,
1049                                 &error,
1050                                 G_TYPE_STRING, &client,
1051                                 G_TYPE_INVALID)) {
1052         reply = ibus_message_new_error (message,
1053                                         DBUS_ERROR_INVALID_ARGS,
1054                                         "Argument 1 of CreateInputContext should be an string");
1055         ibus_error_free (error);
1056         return reply;
1057     }
1058
1059     context = bus_input_context_new (connection, client);
1060     g_object_ref_sink (context);
1061     ibus->contexts = g_list_append (ibus->contexts, context);
1062
1063     static const struct {
1064         gchar *name;
1065         GCallback callback;
1066     } signals [] = {
1067         { "request-engine",      G_CALLBACK (_context_request_engine_cb) },
1068         { "request-next-engine", G_CALLBACK (_context_request_next_engine_cb) },
1069         { "request-prev-engine", G_CALLBACK (_context_request_prev_engine_cb) },
1070         { "engine-changed", G_CALLBACK (_context_engine_changed_cb) },
1071         { "focus-in",       G_CALLBACK (_context_focus_in_cb) },
1072         { "focus-out",      G_CALLBACK (_context_focus_out_cb) },
1073         { "destroy",        G_CALLBACK (_context_destroy_cb) },
1074     #if 0
1075         { "enabled",        G_CALLBACK (_context_enabled_cb) },
1076         { "disabled",       G_CALLBACK (_context_disabled_cb) },
1077     #endif
1078     };
1079
1080     for (i = 0; i < G_N_ELEMENTS (signals); i++) {
1081         g_signal_connect (context,
1082                           signals[i].name,
1083                           signals[i].callback,
1084                           ibus);
1085     }
1086
1087     path = ibus_service_get_path ((IBusService *) context);
1088     reply = ibus_message_new_method_return (message);
1089     ibus_message_append_args (reply,
1090                               IBUS_TYPE_OBJECT_PATH, &path,
1091                               G_TYPE_INVALID);
1092
1093     bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
1094                                    (IBusService *)context);
1095     return reply;
1096 }
1097
1098 static IBusMessage *
1099 _ibus_current_input_context (BusIBusImpl     *ibus,
1100                             IBusMessage     *message,
1101                             BusConnection   *connection)
1102 {
1103     g_assert (BUS_IS_IBUS_IMPL (ibus));
1104     g_assert (message != NULL);
1105     g_assert (BUS_IS_CONNECTION (connection));
1106
1107     IBusMessage *reply;
1108     const gchar *path;
1109
1110     if (!ibus->focused_context)
1111     {
1112         reply = ibus_message_new_error (message,
1113                                         DBUS_ERROR_FAILED,
1114                                         "No input context focused");
1115         return reply;
1116     }
1117
1118     reply = ibus_message_new_method_return (message);
1119     path = ibus_service_get_path((IBusService *)ibus->focused_context);
1120     ibus_message_append_args (reply,
1121                               G_TYPE_STRING, &path,
1122                               G_TYPE_INVALID);
1123
1124     return reply;
1125 }
1126
1127 static void
1128 _factory_destroy_cb (BusFactoryProxy    *factory,
1129                      BusIBusImpl        *ibus)
1130 {
1131     g_assert (BUS_IS_IBUS_IMPL (ibus));
1132     g_assert (BUS_IS_FACTORY_PROXY (factory));
1133
1134     IBusComponent *component;
1135     GList *engines, *p;
1136
1137     ibus->factory_list = g_list_remove (ibus->factory_list, factory);
1138
1139     component = bus_factory_proxy_get_component (factory);
1140
1141     if (component != NULL) {
1142         p = engines = ibus_component_get_engines (component);
1143         for (; p != NULL; p = p->next) {
1144             if (g_list_find (ibus->register_engine_list, p->data)) {
1145                 ibus->register_engine_list = g_list_remove (ibus->register_engine_list, p->data);
1146                 g_object_unref (p->data);
1147             }
1148         }
1149         g_list_free (engines);
1150     }
1151
1152     g_object_unref (factory);
1153 }
1154
1155 static void
1156 bus_ibus_impl_add_factory (BusIBusImpl     *ibus,
1157                            BusFactoryProxy *factory)
1158 {
1159     g_assert (BUS_IS_IBUS_IMPL (ibus));
1160     g_assert (BUS_IS_FACTORY_PROXY (factory));
1161
1162     g_object_ref_sink (factory);
1163     ibus->factory_list = g_list_append (ibus->factory_list, factory);
1164
1165     g_signal_connect (factory, "destroy", G_CALLBACK (_factory_destroy_cb), ibus);
1166 }
1167
1168
1169 static IBusMessage *
1170 _ibus_register_component (BusIBusImpl     *ibus,
1171                           IBusMessage     *message,
1172                           BusConnection   *connection)
1173 {
1174     IBusMessage *reply;
1175     IBusError *error;
1176     gboolean retval;
1177     GList *engines;
1178     IBusComponent *component;
1179     BusFactoryProxy *factory;
1180
1181     retval = ibus_message_get_args (message, &error,
1182                                     IBUS_TYPE_COMPONENT, &component,
1183                                     G_TYPE_INVALID);
1184
1185     if (!retval) {
1186         reply = ibus_message_new_error_printf (message,
1187                                                DBUS_ERROR_INVALID_ARGS,
1188                                                "1st Argument must be IBusComponent: %s",
1189                                                error->message);
1190         ibus_error_free (error);
1191         return reply;
1192     }
1193
1194     g_object_ref_sink (component);
1195     factory = bus_factory_proxy_new (component, connection);
1196
1197     if (factory == NULL) {
1198         reply = ibus_message_new_error (message,
1199                                         DBUS_ERROR_FAILED,
1200                                         "Can not create factory");
1201         return reply;
1202     }
1203
1204     bus_ibus_impl_add_factory (ibus, factory);
1205
1206     engines = ibus_component_get_engines (component);
1207
1208     g_list_foreach (engines, (GFunc) g_object_ref, NULL);
1209     ibus->register_engine_list = g_list_concat (ibus->register_engine_list, engines);
1210     g_object_unref (component);
1211
1212     reply = ibus_message_new_method_return (message);
1213     return reply;
1214 }
1215
1216 static IBusMessage *
1217 _ibus_list_engines (BusIBusImpl   *ibus,
1218                     IBusMessage   *message,
1219                     BusConnection *connection)
1220 {
1221     IBusMessage *reply;
1222     IBusMessageIter iter, sub_iter;
1223     GList *engines, *p;
1224
1225     reply = ibus_message_new_method_return (message);
1226
1227     ibus_message_iter_init_append (reply, &iter);
1228     ibus_message_iter_open_container (&iter, IBUS_TYPE_ARRAY, "v", &sub_iter);
1229
1230     engines = bus_registry_get_engines (ibus->registry);
1231     for (p = engines; p != NULL; p = p->next) {
1232         ibus_message_iter_append (&sub_iter, IBUS_TYPE_ENGINE_DESC, &(p->data));
1233     }
1234     g_list_free (engines);
1235     ibus_message_iter_close_container (&iter, &sub_iter);
1236
1237     return reply;
1238 }
1239
1240 static IBusMessage *
1241 _ibus_list_active_engines (BusIBusImpl   *ibus,
1242                            IBusMessage   *message,
1243                            BusConnection *connection)
1244 {
1245     IBusMessage *reply;
1246     IBusMessageIter iter, sub_iter;
1247     GList *p;
1248
1249     reply = ibus_message_new_method_return (message);
1250
1251     ibus_message_iter_init_append (reply, &iter);
1252     ibus_message_iter_open_container (&iter, IBUS_TYPE_ARRAY, "v", &sub_iter);
1253
1254     for (p = ibus->engine_list; p != NULL; p = p->next) {
1255         ibus_message_iter_append (&sub_iter, IBUS_TYPE_ENGINE_DESC, &(p->data));
1256     }
1257
1258     for (p = ibus->register_engine_list; p != NULL; p = p->next) {
1259         ibus_message_iter_append (&sub_iter, IBUS_TYPE_ENGINE_DESC, &(p->data));
1260     }
1261     ibus_message_iter_close_container (&iter, &sub_iter);
1262
1263     return reply;
1264 }
1265
1266
1267 static IBusMessage *
1268 _ibus_exit (BusIBusImpl     *ibus,
1269             IBusMessage     *message,
1270             BusConnection   *connection)
1271 {
1272     IBusMessage *reply;
1273     IBusError *error;
1274     gboolean restart;
1275
1276     if (!ibus_message_get_args (message,
1277                                 &error,
1278                                 G_TYPE_BOOLEAN, &restart,
1279                                 G_TYPE_INVALID)) {
1280         reply = ibus_message_new_error (message,
1281                                         DBUS_ERROR_INVALID_ARGS,
1282                                         "Argument 1 of Exit should be an boolean");
1283         ibus_error_free (error);
1284         return reply;
1285     }
1286
1287     reply = ibus_message_new_method_return (message);
1288     ibus_connection_send ((IBusConnection *) connection, reply);
1289     ibus_connection_flush ((IBusConnection *) connection);
1290     ibus_message_unref (reply);
1291
1292     ibus_object_destroy ((IBusObject *) BUS_DEFAULT_SERVER);
1293
1294     if (!restart) {
1295         exit (0);
1296     }
1297     else {
1298         extern gchar **g_argv;
1299         gchar *exe;
1300         gint fd;
1301
1302         exe = g_strdup_printf ("/proc/%d/exe", getpid ());
1303         exe = g_file_read_link (exe, NULL);
1304
1305         if (exe == NULL)
1306             exe = BINDIR"/ibus-daemon";
1307
1308         /* close all fds except stdin, stdout, stderr */
1309         for (fd = 3; fd <= sysconf (_SC_OPEN_MAX); fd ++) {
1310             close (fd);
1311         }
1312
1313         execv (exe, g_argv);
1314         g_warning ("execv %s failed!", g_argv[0]);
1315         exit (-1);
1316     }
1317
1318     /* should not reach here */
1319     g_assert_not_reached ();
1320
1321     return NULL;
1322 }
1323
1324 static IBusMessage *
1325 _ibus_ping (BusIBusImpl     *ibus,
1326             IBusMessage     *message,
1327             BusConnection   *connection)
1328 {
1329     IBusMessage *reply;
1330     IBusMessageIter src, dst;
1331
1332     reply = ibus_message_new_method_return (message);
1333
1334     ibus_message_iter_init (message, &src);
1335     ibus_message_iter_init_append (reply, &dst);
1336
1337     ibus_message_iter_copy_data (&dst, &src);
1338
1339     return reply;
1340 }
1341
1342 static gboolean
1343 bus_ibus_impl_ibus_message (BusIBusImpl     *ibus,
1344                             BusConnection   *connection,
1345                             IBusMessage     *message)
1346 {
1347     g_assert (BUS_IS_IBUS_IMPL (ibus));
1348     g_assert (BUS_IS_CONNECTION (connection));
1349     g_assert (message != NULL);
1350
1351     gint i;
1352     IBusMessage *reply_message = NULL;
1353
1354     static const struct {
1355         const gchar *interface;
1356         const gchar *name;
1357         IBusMessage *(* handler) (BusIBusImpl *, IBusMessage *, BusConnection *);
1358     } handlers[] =  {
1359         /* Introspectable interface */
1360         { DBUS_INTERFACE_INTROSPECTABLE,
1361                                "Introspect",            _ibus_introspect },
1362         /* IBus interface */
1363         { IBUS_INTERFACE_IBUS, "GetAddress",            _ibus_get_address },
1364         { IBUS_INTERFACE_IBUS, "CreateInputContext",    _ibus_create_input_context },
1365         { IBUS_INTERFACE_IBUS, "CurrentInputContext",   _ibus_current_input_context },
1366         { IBUS_INTERFACE_IBUS, "RegisterComponent",     _ibus_register_component },
1367         { IBUS_INTERFACE_IBUS, "ListEngines",           _ibus_list_engines },
1368         { IBUS_INTERFACE_IBUS, "ListActiveEngines",     _ibus_list_active_engines },
1369         { IBUS_INTERFACE_IBUS, "Exit",                  _ibus_exit },
1370         { IBUS_INTERFACE_IBUS, "Ping",                  _ibus_ping },
1371     };
1372
1373     ibus_message_set_sender (message, bus_connection_get_unique_name (connection));
1374     ibus_message_set_destination (message, DBUS_SERVICE_DBUS);
1375
1376     if (ibus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL) {
1377         for (i = 0; i < G_N_ELEMENTS (handlers); i++) {
1378             if (ibus_message_is_method_call (message,
1379                                              handlers[i].interface,
1380                                              handlers[i].name)) {
1381
1382                 reply_message = handlers[i].handler (ibus, message, connection);
1383                 if (reply_message) {
1384
1385                     ibus_message_set_sender (reply_message, DBUS_SERVICE_DBUS);
1386                     ibus_message_set_destination (reply_message, bus_connection_get_unique_name (connection));
1387                     ibus_message_set_no_reply (reply_message, TRUE);
1388
1389                     ibus_connection_send ((IBusConnection *) connection, reply_message);
1390                     ibus_message_unref (reply_message);
1391                 }
1392
1393                 g_signal_stop_emission_by_name (ibus, "ibus-message");
1394                 return TRUE;
1395             }
1396         }
1397     }
1398
1399     return IBUS_SERVICE_CLASS(bus_ibus_impl_parent_class)->ibus_message (
1400                                     (IBusService *) ibus,
1401                                     (IBusConnection *) connection,
1402                                     message);
1403 }
1404
1405 BusFactoryProxy *
1406 bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
1407                               const gchar *path)
1408 {
1409     g_assert (BUS_IS_IBUS_IMPL (ibus));
1410
1411     BusFactoryProxy *factory;
1412
1413     factory = (BusFactoryProxy *) g_hash_table_lookup (ibus->factory_dict, path);
1414
1415     return factory;
1416 }
1417
1418 IBusHotkeyProfile *
1419 bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus)
1420 {
1421     g_assert (BUS_IS_IBUS_IMPL (ibus));
1422
1423     return ibus->hotkey_profile;
1424 }
1425
1426 IBusKeymap *
1427 bus_ibus_impl_get_keymap (BusIBusImpl *ibus)
1428 {
1429
1430     g_assert (BUS_IS_IBUS_IMPL (ibus));
1431
1432     return ibus->keymap;
1433 }
1434
1435 BusRegistry *
1436 bus_ibus_impl_get_registry (BusIBusImpl *ibus)
1437 {
1438
1439     g_assert (BUS_IS_IBUS_IMPL (ibus));
1440
1441     return ibus->registry;
1442 }
1443
1444 static void
1445 bus_ibus_impl_registry_changed (BusIBusImpl *ibus)
1446 {
1447     g_assert (BUS_IS_IBUS_IMPL (ibus));
1448
1449     IBusMessage *message;
1450
1451     message = ibus_message_new_signal (IBUS_PATH_IBUS,
1452                                        IBUS_INTERFACE_IBUS,
1453                                        "RegistryChanged");
1454     ibus_message_append_args (message,
1455                               G_TYPE_INVALID);
1456     ibus_message_set_sender (message, IBUS_SERVICE_IBUS);
1457
1458     bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
1459
1460     ibus_message_unref (message);
1461
1462 }