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