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.
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.
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.
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.
23 #include <sys/types.h>
32 #include "connection.h"
34 #include "factoryproxy.h"
35 #include "panelproxy.h"
36 #include "inputcontext.h"
47 // static guint _signals[LAST_SIGNAL] = { 0 };
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,
58 static void bus_ibus_impl_set_preload_engines
61 static void bus_ibus_impl_set_use_sys_layout
64 static void bus_ibus_impl_set_embed_preedit_text
68 static void bus_ibus_impl_set_use_global_engine
71 static void bus_ibus_impl_set_global_engine (BusIBusImpl *ibus,
72 BusEngineProxy *engine);
74 static void bus_ibus_impl_registry_changed (BusIBusImpl *ibus);
75 static void _factory_destroy_cb (BusFactoryProxy *factory,
78 G_DEFINE_TYPE(BusIBusImpl, bus_ibus_impl, IBUS_TYPE_SERVICE)
81 bus_ibus_impl_get_default (void)
83 static BusIBusImpl *ibus = NULL;
86 ibus = (BusIBusImpl *) g_object_new (BUS_TYPE_IBUS_IMPL,
87 "path", IBUS_PATH_IBUS,
89 bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
96 bus_ibus_impl_class_init (BusIBusImplClass *klass)
98 IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
100 ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_ibus_impl_destroy;
102 IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) bus_ibus_impl_ibus_message;
107 _panel_destroy_cb (BusPanelProxy *panel,
110 g_assert (BUS_IS_PANEL_PROXY (panel));
111 g_assert (BUS_IS_IBUS_IMPL (ibus));
113 g_return_if_fail (ibus->panel == panel);
116 g_object_unref (panel);
120 bus_ibus_impl_set_hotkey (BusIBusImpl *ibus,
124 g_assert (BUS_IS_IBUS_IMPL (ibus));
129 ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
135 g_return_if_fail (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
136 array = g_value_get_boxed (value);
138 for (i = 0; i < array->n_values; i++) {
141 str = g_value_array_get_nth (array, i);
142 g_return_if_fail (G_VALUE_TYPE (str) == G_TYPE_STRING);
144 ibus_hotkey_profile_add_hotkey_from_string (ibus->hotkey_profile,
145 g_value_get_string (str),
152 bus_ibus_impl_set_trigger (BusIBusImpl *ibus,
155 GQuark hotkey = g_quark_from_static_string ("trigger");
156 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
158 ibus_hotkey_profile_add_hotkey (ibus->hotkey_profile,
166 bus_ibus_impl_set_next_engine (BusIBusImpl *ibus,
169 GQuark hotkey = g_quark_from_static_string ("next-engine");
170 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
174 bus_ibus_impl_set_prev_engine (BusIBusImpl *ibus,
177 GQuark hotkey = g_quark_from_static_string ("prev-engine");
178 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
182 bus_ibus_impl_set_preload_engines (BusIBusImpl *ibus,
185 GList *engine_list = NULL;
187 g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
188 g_list_free (ibus->engine_list);
190 if (value != NULL && G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY) {
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;
199 if (G_VALUE_TYPE (&array->values[i]) != G_TYPE_STRING)
202 engine_name = g_value_get_string (&array->values[i]);
204 engine = bus_registry_find_engine_by_name (ibus->registry, engine_name);
206 if (engine == NULL || g_list_find (engine_list, engine) != NULL)
209 engine_list = g_list_append (engine_list, engine);
213 g_list_foreach (engine_list, (GFunc) g_object_ref, NULL);
214 ibus->engine_list = engine_list;
216 if (ibus->engine_list) {
217 IBusComponent *component;
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);
227 bus_ibus_impl_set_use_sys_layout (BusIBusImpl *ibus,
230 if (value != NULL && G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) {
231 ibus->use_sys_layout = g_value_get_boolean (value);
236 bus_ibus_impl_set_embed_preedit_text (BusIBusImpl *ibus,
238 if (value != NULL && G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) {
239 ibus->embed_preedit_text = g_value_get_boolean (value);
245 bus_ibus_impl_set_use_global_engine (BusIBusImpl *ibus,
250 if (value == NULL || G_VALUE_TYPE (value) != G_TYPE_BOOLEAN) {
254 new_value = g_value_get_boolean (value);
255 if (ibus->use_global_engine == new_value) {
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));
266 /* turn off use_global_engine option */
267 bus_ibus_impl_set_global_engine (ibus, NULL);
268 ibus->use_global_engine = FALSE;
273 _engine_desc_cmp (IBusEngineDesc *desc1,
274 IBusEngineDesc *desc2)
276 return - ((gint) desc1->rank) + ((gint) desc2->rank);
280 bus_ibus_impl_set_default_preload_engines (BusIBusImpl *ibus)
282 g_assert (BUS_IS_IBUS_IMPL (ibus));
284 static gboolean done = FALSE;
285 GValue value = { 0 };
286 GList *engines, *list;
290 if (done || ibus->config == NULL) {
294 if (ibus_config_get_value (ibus->config, "general", "preload_engines", &value)) {
296 g_value_unset (&value);
301 lang = g_strdup (setlocale (LC_ALL, NULL));
302 p = index (lang, '.');
307 engines = bus_registry_get_engines_by_language (ibus->registry, lang);
308 if (engines == NULL) {
309 p = index (lang, '_');
312 engines = bus_registry_get_engines_by_language (ibus->registry, lang);
317 /* sort engines by rank */
318 engines = g_list_sort (engines, (GCompareFunc) _engine_desc_cmp);
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;
325 desc = (IBusEngineDesc *)list->data;
327 /* ignore engines with rank <== 0 */
330 g_value_init (&name, G_TYPE_STRING);
331 g_value_set_string (&name, desc->name);
332 g_value_array_append (array, &name);
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);
341 bus_ibus_impl_reload_config (BusIBusImpl *ibus)
343 g_assert (BUS_IS_IBUS_IMPL (ibus));
346 GValue value = { 0 };
348 const static struct {
351 void ( *func) (BusIBusImpl *, GValue *);
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 },
363 for (i = 0; entries[i].section != NULL; i++) {
364 if (ibus->config != NULL &&
365 ibus_config_get_value (ibus->config,
369 entries[i].func (ibus, &value);
370 g_value_unset (&value);
373 entries[i].func (ibus, NULL);
379 _config_value_changed_cb (IBusConfig *config,
385 g_assert (IBUS_IS_CONFIG (config));
389 g_assert (BUS_IS_IBUS_IMPL (ibus));
393 const static struct {
396 void ( *func) (BusIBusImpl *, GValue *);
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 },
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);
418 _config_destroy_cb (IBusConfig *config,
421 g_assert (IBUS_IS_CONFIG (config));
422 g_assert (BUS_IS_IBUS_IMPL (ibus));
424 g_assert (ibus->config == config);
426 g_object_unref (ibus->config);
431 _registry_changed_cb (BusRegistry *registry,
434 bus_ibus_impl_registry_changed (ibus);
438 _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
440 const gchar *old_name,
441 const gchar *new_name,
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));
450 BusFactoryProxy *factory;
452 if (g_strcmp0 (name, IBUS_SERVICE_PANEL) == 0) {
453 if (g_strcmp0 (new_name, "") != 0) {
454 BusConnection *connection;
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);
462 connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
463 g_return_if_fail (connection != NULL);
465 ibus->panel = bus_panel_proxy_new (connection);
466 g_object_ref_sink (ibus->panel);
468 g_signal_connect (ibus->panel,
470 G_CALLBACK (_panel_destroy_cb),
473 if (ibus->focused_context != NULL) {
474 bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context);
478 else if (g_strcmp0 (name, IBUS_SERVICE_CONFIG) == 0) {
479 if (g_strcmp0 (new_name, "") != 0) {
480 BusConnection *connection;
482 if (ibus->config != NULL) {
483 ibus_object_destroy (IBUS_OBJECT (ibus->config));
484 /* config should be NULL */
485 g_assert (ibus->config == NULL);
488 connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
489 g_return_if_fail (connection != NULL);
491 ibus->config = g_object_new (IBUS_TYPE_CONFIG,
493 "path", IBUS_PATH_CONFIG,
494 "connection", connection,
496 g_object_ref_sink (ibus->config);
498 g_signal_connect (ibus->config,
500 G_CALLBACK (_config_value_changed_cb),
503 g_signal_connect (ibus->config,
505 G_CALLBACK (_config_destroy_cb),
508 bus_ibus_impl_set_default_preload_engines (ibus);
509 bus_ibus_impl_reload_config (ibus);
513 factory = bus_registry_name_owner_changed (ibus->registry, name, old_name, new_name);
516 bus_ibus_impl_add_factory (ibus, factory);
521 bus_ibus_impl_init (BusIBusImpl *ibus)
523 ibus->factory_dict = g_hash_table_new_full (
527 (GDestroyNotify) g_object_unref);
529 ibus->engine_list = NULL;
530 ibus->register_engine_list = NULL;
531 ibus->contexts = NULL;
532 ibus->focused_context = NULL;
536 ibus->registry = bus_registry_new ();
538 g_signal_connect (ibus->registry,
540 G_CALLBACK (_registry_changed_cb),
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);
549 ibus->hotkey_profile = ibus_hotkey_profile_new ();
550 ibus->keymap = ibus_keymap_get ("us");
552 ibus->use_sys_layout = FALSE;
553 ibus->embed_preedit_text = TRUE;
554 ibus->use_global_engine = FALSE;
555 ibus->global_engine = NULL;
557 bus_ibus_impl_reload_config (ibus);
559 g_signal_connect (BUS_DEFAULT_DBUS,
560 "name-owner-changed",
561 G_CALLBACK (_dbus_name_owner_changed_cb),
566 bus_ibus_impl_destroy (BusIBusImpl *ibus)
573 bus_registry_stop_all_components (ibus->registry);
579 while ((pid = waitpid (0, &status, WNOHANG)) > 0);
581 if (pid == -1) { /* all children finished */
584 if (pid == 0) { /* no child status changed */
587 if (timeout >= G_USEC_PER_SEC) {
590 old = signal (SIGTERM, SIG_IGN);
591 kill (-getpid (), SIGTERM);
592 signal (SIGTERM, old);
596 g_warning ("Not every child processes exited!");
603 g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
604 g_list_free (ibus->engine_list);
605 ibus->engine_list = NULL;
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;
611 if (ibus->factory_dict != NULL) {
612 g_hash_table_destroy (ibus->factory_dict);
613 ibus->factory_dict = NULL;
616 if (ibus->hotkey_profile != NULL) {
617 g_object_unref (ibus->hotkey_profile);
618 ibus->hotkey_profile = NULL;
621 if (ibus->keymap != NULL) {
622 g_object_unref (ibus->keymap);
626 if (ibus->global_engine) {
627 g_object_unref (ibus->global_engine);
628 ibus->global_engine = NULL;
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));
636 /* introspectable interface */
638 _ibus_introspect (BusIBusImpl *ibus,
639 IBusMessage *message,
640 BusConnection *connection)
642 static const gchar *introspect =
643 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
645 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
646 " <method name=\"Introspect\">\n"
647 " <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
650 " <interface name=\"org.freedesktop.IBus\">\n"
651 " <method name=\"GetAddress\">\n"
652 " <arg name=\"address\" direction=\"out\" type=\"s\"/>\n"
654 " <method name=\"CreateInputContext\">\n"
655 " <arg name=\"name\" direction=\"in\" type=\"s\"/>\n"
656 " <arg name=\"context\" direction=\"out\" type=\"o\"/>\n"
658 " <method name=\"CurrentInputContext\">\n"
659 " <arg name=\"name\" direction=\"out\" type=\"s\"/>\n"
661 " <method name=\"RegisterComponent\">\n"
662 " <arg name=\"components\" direction=\"in\" type=\"v\"/>\n"
664 " <method name=\"ListEngines\">\n"
665 " <arg name=\"engines\" direction=\"out\" type=\"av\"/>\n"
667 " <method name=\"ListActiveEngines\">\n"
668 " <arg name=\"engines\" direction=\"out\" type=\"av\"/>\n"
670 " <method name=\"Exit\">\n"
671 " <arg name=\"restart\" direction=\"in\" type=\"b\"/>\n"
673 " <method name=\"Ping\">\n"
674 " <arg name=\"data\" direction=\"in\" type=\"v\"/>\n"
675 " <arg name=\"data\" direction=\"out\" type=\"v\"/>\n"
677 " <signal name=\"RegistryChanged\">\n"
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,
688 return reply_message;
694 _ibus_get_address (BusIBusImpl *ibus,
695 IBusMessage *message,
696 BusConnection *connection)
698 const gchar *address;
701 address = ibus_server_get_address (IBUS_SERVER (BUS_DEFAULT_SERVER));
703 reply = ibus_message_new_method_return (message);
704 ibus_message_append_args (reply,
705 G_TYPE_STRING, &address,
711 static BusEngineProxy *
712 bus_ibus_impl_create_engine (IBusEngineDesc *engine_desc)
715 BusFactoryProxy *factory;
716 BusEngineProxy *engine;
719 factory = bus_factory_proxy_get_from_engine (engine_desc);
721 if (factory == NULL) {
722 /* try to execute the engine */
723 comp = ibus_component_get_from_engine (engine_desc);
726 if (!ibus_component_is_running (comp)) {
727 ibus_component_start (comp, g_verbose);
728 g_get_current_time (&t1);
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) {
737 g_get_current_time (&t2);
738 if (t2.tv_sec - t1.tv_sec >= 5)
743 factory = bus_factory_proxy_get_from_engine (engine_desc);
747 if (factory == NULL) {
751 g_object_ref (factory);
752 engine = bus_factory_proxy_create_engine (factory, engine_desc);
753 g_object_unref (factory);
758 static IBusEngineDesc *
759 _find_engine_desc_by_name(BusIBusImpl *ibus,
762 IBusEngineDesc *engine_desc = NULL;
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)
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)
783 _context_request_engine_cb (BusInputContext *context,
787 IBusEngineDesc *engine_desc = NULL;
788 BusEngineProxy *engine;
790 /* context should has focus before request an engine */
791 g_return_if_fail (bus_input_context_has_focus (context));
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;
798 else if (ibus->engine_list) {
799 engine_desc = (IBusEngineDesc *)ibus->engine_list->data;
803 /* request engine by name */
804 engine_desc = _find_engine_desc_by_name (ibus, engine_name);
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);
816 _context_request_next_engine_cb (BusInputContext *context,
819 BusEngineProxy *engine;
820 IBusEngineDesc *desc;
821 IBusEngineDesc *next_desc = NULL;
824 engine = bus_input_context_get_engine (context);
825 if (engine == NULL) {
826 _context_request_engine_cb (context, NULL, ibus);
830 desc = bus_engine_proxy_get_desc (engine);
832 p = g_list_find (ibus->register_engine_list, desc);
837 p = g_list_find (ibus->engine_list, desc);
844 next_desc = (IBusEngineDesc*) p->data;
847 if (ibus->register_engine_list) {
848 next_desc = (IBusEngineDesc *)ibus->register_engine_list->data;
850 else if (ibus->engine_list) {
851 next_desc = (IBusEngineDesc *)ibus->engine_list->data;
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);
864 _context_request_prev_engine_cb (BusInputContext *context,
871 _global_engine_destroy_cb (BusEngineProxy *engine,
874 if (ibus->global_engine != engine) {
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;
885 bus_ibus_impl_set_global_engine (BusIBusImpl *ibus,
886 BusEngineProxy *engine)
888 g_assert (ibus->use_global_engine == TRUE);
890 if (ibus->global_engine == engine) {
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);
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);
909 _context_engine_changed_cb (BusInputContext *context,
912 BusEngineProxy *engine;
914 if (context != ibus->focused_context ||
915 ibus->use_global_engine != TRUE) {
919 engine = bus_input_context_get_engine (context);
920 bus_ibus_impl_set_global_engine (ibus, engine);
924 _context_focus_out_cb (BusInputContext *context,
927 g_assert (BUS_IS_IBUS_IMPL (ibus));
928 g_assert (BUS_IS_INPUT_CONTEXT (context));
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) {
936 /* Do noting if it is not focused context. */
937 if (ibus->focused_context != context) {
941 ibus->focused_context = NULL;
943 if (ibus->panel != NULL) {
944 bus_panel_proxy_focus_out (ibus->panel, context);
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);
953 g_object_unref (context);
957 _context_focus_in_cb (BusInputContext *context,
960 g_assert (BUS_IS_IBUS_IMPL (ibus));
961 g_assert (BUS_IS_INPUT_CONTEXT (context));
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) {
969 /* Do nothing if it is focused context already. */
970 if (ibus->focused_context == context) {
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);
980 g_object_ref (context);
981 ibus->focused_context = context;
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);
996 if (ibus->panel != NULL) {
997 bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context);
1002 _context_destroy_cb (BusInputContext *context,
1005 g_assert (BUS_IS_IBUS_IMPL (ibus));
1006 g_assert (BUS_IS_INPUT_CONTEXT (context));
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);
1014 ibus->contexts = g_list_remove (ibus->contexts, context);
1015 g_object_unref (context);
1020 _context_enabled_cb (BusInputContext *context,
1026 _context_disabled_cb (BusInputContext *context,
1032 static IBusMessage *
1033 _ibus_create_input_context (BusIBusImpl *ibus,
1034 IBusMessage *message,
1035 BusConnection *connection)
1037 g_assert (BUS_IS_IBUS_IMPL (ibus));
1038 g_assert (message != NULL);
1039 g_assert (BUS_IS_CONNECTION (connection));
1045 BusInputContext *context;
1048 if (!ibus_message_get_args (message,
1050 G_TYPE_STRING, &client,
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);
1059 context = bus_input_context_new (connection, client);
1060 g_object_ref_sink (context);
1061 ibus->contexts = g_list_append (ibus->contexts, context);
1063 static const struct {
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) },
1075 { "enabled", G_CALLBACK (_context_enabled_cb) },
1076 { "disabled", G_CALLBACK (_context_disabled_cb) },
1080 for (i = 0; i < G_N_ELEMENTS (signals); i++) {
1081 g_signal_connect (context,
1083 signals[i].callback,
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,
1093 bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
1094 (IBusService *)context);
1098 static IBusMessage *
1099 _ibus_current_input_context (BusIBusImpl *ibus,
1100 IBusMessage *message,
1101 BusConnection *connection)
1103 g_assert (BUS_IS_IBUS_IMPL (ibus));
1104 g_assert (message != NULL);
1105 g_assert (BUS_IS_CONNECTION (connection));
1110 if (!ibus->focused_context)
1112 reply = ibus_message_new_error (message,
1114 "No input context focused");
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,
1128 _factory_destroy_cb (BusFactoryProxy *factory,
1131 g_assert (BUS_IS_IBUS_IMPL (ibus));
1132 g_assert (BUS_IS_FACTORY_PROXY (factory));
1134 IBusComponent *component;
1137 ibus->factory_list = g_list_remove (ibus->factory_list, factory);
1139 component = bus_factory_proxy_get_component (factory);
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);
1149 g_list_free (engines);
1152 g_object_unref (factory);
1156 bus_ibus_impl_add_factory (BusIBusImpl *ibus,
1157 BusFactoryProxy *factory)
1159 g_assert (BUS_IS_IBUS_IMPL (ibus));
1160 g_assert (BUS_IS_FACTORY_PROXY (factory));
1162 g_object_ref_sink (factory);
1163 ibus->factory_list = g_list_append (ibus->factory_list, factory);
1165 g_signal_connect (factory, "destroy", G_CALLBACK (_factory_destroy_cb), ibus);
1169 static IBusMessage *
1170 _ibus_register_component (BusIBusImpl *ibus,
1171 IBusMessage *message,
1172 BusConnection *connection)
1178 IBusComponent *component;
1179 BusFactoryProxy *factory;
1181 retval = ibus_message_get_args (message, &error,
1182 IBUS_TYPE_COMPONENT, &component,
1186 reply = ibus_message_new_error_printf (message,
1187 DBUS_ERROR_INVALID_ARGS,
1188 "1st Argument must be IBusComponent: %s",
1190 ibus_error_free (error);
1194 g_object_ref_sink (component);
1195 factory = bus_factory_proxy_new (component, connection);
1197 if (factory == NULL) {
1198 reply = ibus_message_new_error (message,
1200 "Can not create factory");
1204 bus_ibus_impl_add_factory (ibus, factory);
1206 engines = ibus_component_get_engines (component);
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);
1212 reply = ibus_message_new_method_return (message);
1216 static IBusMessage *
1217 _ibus_list_engines (BusIBusImpl *ibus,
1218 IBusMessage *message,
1219 BusConnection *connection)
1222 IBusMessageIter iter, sub_iter;
1225 reply = ibus_message_new_method_return (message);
1227 ibus_message_iter_init_append (reply, &iter);
1228 ibus_message_iter_open_container (&iter, IBUS_TYPE_ARRAY, "v", &sub_iter);
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));
1234 g_list_free (engines);
1235 ibus_message_iter_close_container (&iter, &sub_iter);
1240 static IBusMessage *
1241 _ibus_list_active_engines (BusIBusImpl *ibus,
1242 IBusMessage *message,
1243 BusConnection *connection)
1246 IBusMessageIter iter, sub_iter;
1249 reply = ibus_message_new_method_return (message);
1251 ibus_message_iter_init_append (reply, &iter);
1252 ibus_message_iter_open_container (&iter, IBUS_TYPE_ARRAY, "v", &sub_iter);
1254 for (p = ibus->engine_list; p != NULL; p = p->next) {
1255 ibus_message_iter_append (&sub_iter, IBUS_TYPE_ENGINE_DESC, &(p->data));
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));
1261 ibus_message_iter_close_container (&iter, &sub_iter);
1267 static IBusMessage *
1268 _ibus_exit (BusIBusImpl *ibus,
1269 IBusMessage *message,
1270 BusConnection *connection)
1276 if (!ibus_message_get_args (message,
1278 G_TYPE_BOOLEAN, &restart,
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);
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);
1292 ibus_object_destroy ((IBusObject *) BUS_DEFAULT_SERVER);
1298 extern gchar **g_argv;
1302 exe = g_strdup_printf ("/proc/%d/exe", getpid ());
1303 exe = g_file_read_link (exe, NULL);
1306 exe = BINDIR"/ibus-daemon";
1308 /* close all fds except stdin, stdout, stderr */
1309 for (fd = 3; fd <= sysconf (_SC_OPEN_MAX); fd ++) {
1313 execv (exe, g_argv);
1314 g_warning ("execv %s failed!", g_argv[0]);
1318 /* should not reach here */
1319 g_assert_not_reached ();
1324 static IBusMessage *
1325 _ibus_ping (BusIBusImpl *ibus,
1326 IBusMessage *message,
1327 BusConnection *connection)
1330 IBusMessageIter src, dst;
1332 reply = ibus_message_new_method_return (message);
1334 ibus_message_iter_init (message, &src);
1335 ibus_message_iter_init_append (reply, &dst);
1337 ibus_message_iter_copy_data (&dst, &src);
1343 bus_ibus_impl_ibus_message (BusIBusImpl *ibus,
1344 BusConnection *connection,
1345 IBusMessage *message)
1347 g_assert (BUS_IS_IBUS_IMPL (ibus));
1348 g_assert (BUS_IS_CONNECTION (connection));
1349 g_assert (message != NULL);
1352 IBusMessage *reply_message = NULL;
1354 static const struct {
1355 const gchar *interface;
1357 IBusMessage *(* handler) (BusIBusImpl *, IBusMessage *, BusConnection *);
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 },
1373 ibus_message_set_sender (message, bus_connection_get_unique_name (connection));
1374 ibus_message_set_destination (message, DBUS_SERVICE_DBUS);
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)) {
1382 reply_message = handlers[i].handler (ibus, message, connection);
1383 if (reply_message) {
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);
1389 ibus_connection_send ((IBusConnection *) connection, reply_message);
1390 ibus_message_unref (reply_message);
1393 g_signal_stop_emission_by_name (ibus, "ibus-message");
1399 return IBUS_SERVICE_CLASS(bus_ibus_impl_parent_class)->ibus_message (
1400 (IBusService *) ibus,
1401 (IBusConnection *) connection,
1406 bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
1409 g_assert (BUS_IS_IBUS_IMPL (ibus));
1411 BusFactoryProxy *factory;
1413 factory = (BusFactoryProxy *) g_hash_table_lookup (ibus->factory_dict, path);
1419 bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus)
1421 g_assert (BUS_IS_IBUS_IMPL (ibus));
1423 return ibus->hotkey_profile;
1427 bus_ibus_impl_get_keymap (BusIBusImpl *ibus)
1430 g_assert (BUS_IS_IBUS_IMPL (ibus));
1432 return ibus->keymap;
1436 bus_ibus_impl_get_registry (BusIBusImpl *ibus)
1439 g_assert (BUS_IS_IBUS_IMPL (ibus));
1441 return ibus->registry;
1445 bus_ibus_impl_registry_changed (BusIBusImpl *ibus)
1447 g_assert (BUS_IS_IBUS_IMPL (ibus));
1449 IBusMessage *message;
1451 message = ibus_message_new_signal (IBUS_PATH_IBUS,
1452 IBUS_INTERFACE_IBUS,
1454 ibus_message_append_args (message,
1456 ibus_message_set_sender (message, IBUS_SERVICE_IBUS);
1458 bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
1460 ibus_message_unref (message);