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 = TRUE;
555 ibus->global_engine_enabled = FALSE;
556 ibus->global_engine = NULL;
558 bus_ibus_impl_reload_config (ibus);
560 g_signal_connect (BUS_DEFAULT_DBUS,
561 "name-owner-changed",
562 G_CALLBACK (_dbus_name_owner_changed_cb),
567 bus_ibus_impl_destroy (BusIBusImpl *ibus)
574 bus_registry_stop_all_components (ibus->registry);
580 while ((pid = waitpid (0, &status, WNOHANG)) > 0);
582 if (pid == -1) { /* all children finished */
585 if (pid == 0) { /* no child status changed */
588 if (timeout >= G_USEC_PER_SEC) {
591 old = signal (SIGTERM, SIG_IGN);
592 kill (-getpid (), SIGTERM);
593 signal (SIGTERM, old);
597 g_warning ("Not every child processes exited!");
604 g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
605 g_list_free (ibus->engine_list);
606 ibus->engine_list = NULL;
608 g_list_foreach (ibus->register_engine_list, (GFunc) g_object_unref, NULL);
609 g_list_free (ibus->register_engine_list);
610 ibus->register_engine_list = NULL;
612 if (ibus->factory_dict != NULL) {
613 g_hash_table_destroy (ibus->factory_dict);
614 ibus->factory_dict = NULL;
617 if (ibus->hotkey_profile != NULL) {
618 g_object_unref (ibus->hotkey_profile);
619 ibus->hotkey_profile = NULL;
622 if (ibus->keymap != NULL) {
623 g_object_unref (ibus->keymap);
627 if (ibus->global_engine) {
628 g_object_unref (ibus->global_engine);
629 ibus->global_engine = NULL;
632 bus_server_quit (BUS_DEFAULT_SERVER);
633 ibus_object_destroy ((IBusObject *) BUS_DEFAULT_SERVER);
634 IBUS_OBJECT_CLASS(bus_ibus_impl_parent_class)->destroy (IBUS_OBJECT (ibus));
637 /* introspectable interface */
639 _ibus_introspect (BusIBusImpl *ibus,
640 IBusMessage *message,
641 BusConnection *connection)
643 static const gchar *introspect =
644 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
646 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
647 " <method name=\"Introspect\">\n"
648 " <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
651 " <interface name=\"org.freedesktop.IBus\">\n"
652 " <method name=\"GetAddress\">\n"
653 " <arg name=\"address\" direction=\"out\" type=\"s\"/>\n"
655 " <method name=\"CreateInputContext\">\n"
656 " <arg name=\"name\" direction=\"in\" type=\"s\"/>\n"
657 " <arg name=\"context\" direction=\"out\" type=\"o\"/>\n"
659 " <method name=\"CurrentInputContext\">\n"
660 " <arg name=\"name\" direction=\"out\" type=\"s\"/>\n"
662 " <method name=\"RegisterComponent\">\n"
663 " <arg name=\"components\" direction=\"in\" type=\"v\"/>\n"
665 " <method name=\"ListEngines\">\n"
666 " <arg name=\"engines\" direction=\"out\" type=\"av\"/>\n"
668 " <method name=\"ListActiveEngines\">\n"
669 " <arg name=\"engines\" direction=\"out\" type=\"av\"/>\n"
671 " <method name=\"Exit\">\n"
672 " <arg name=\"restart\" direction=\"in\" type=\"b\"/>\n"
674 " <method name=\"Ping\">\n"
675 " <arg name=\"data\" direction=\"in\" type=\"v\"/>\n"
676 " <arg name=\"data\" direction=\"out\" type=\"v\"/>\n"
678 " <signal name=\"RegistryChanged\">\n"
683 IBusMessage *reply_message;
684 reply_message = ibus_message_new_method_return (message);
685 ibus_message_append_args (reply_message,
686 G_TYPE_STRING, &introspect,
689 return reply_message;
695 _ibus_get_address (BusIBusImpl *ibus,
696 IBusMessage *message,
697 BusConnection *connection)
699 const gchar *address;
702 address = ibus_server_get_address (IBUS_SERVER (BUS_DEFAULT_SERVER));
704 reply = ibus_message_new_method_return (message);
705 ibus_message_append_args (reply,
706 G_TYPE_STRING, &address,
712 static BusEngineProxy *
713 bus_ibus_impl_create_engine (IBusEngineDesc *engine_desc)
716 BusFactoryProxy *factory;
717 BusEngineProxy *engine;
720 factory = bus_factory_proxy_get_from_engine (engine_desc);
722 if (factory == NULL) {
723 /* try to execute the engine */
724 comp = ibus_component_get_from_engine (engine_desc);
727 if (!ibus_component_is_running (comp)) {
728 ibus_component_start (comp, g_verbose);
729 g_get_current_time (&t1);
731 if (g_main_context_pending (NULL)) {
732 g_main_context_iteration (NULL, FALSE);
733 factory = bus_factory_proxy_get_from_engine (engine_desc);
734 if (factory != NULL) {
738 g_get_current_time (&t2);
739 if (t2.tv_sec - t1.tv_sec >= 5)
744 factory = bus_factory_proxy_get_from_engine (engine_desc);
748 if (factory == NULL) {
752 g_object_ref (factory);
753 engine = bus_factory_proxy_create_engine (factory, engine_desc);
754 g_object_unref (factory);
759 static IBusEngineDesc *
760 _find_engine_desc_by_name(BusIBusImpl *ibus,
763 IBusEngineDesc *engine_desc = NULL;
766 /* find engine in registered engine list */
767 for (p = ibus->register_engine_list; p != NULL; p = p->next) {
768 engine_desc = (IBusEngineDesc *)p->data;
769 if (g_strcmp0 (engine_desc->name, engine_name) == 0)
773 /* find engine in preload engine list */
774 for (p = ibus->engine_list; p != NULL; p = p->next) {
775 engine_desc = (IBusEngineDesc *)p->data;
776 if (g_strcmp0 (engine_desc->name, engine_name) == 0)
784 _context_request_engine_cb (BusInputContext *context,
788 IBusEngineDesc *engine_desc = NULL;
789 BusEngineProxy *engine;
791 /* context should has focus before request an engine */
792 g_return_if_fail (bus_input_context_has_focus (context));
794 if (engine_name == NULL || engine_name[0] == '\0') {
795 /* request default engine */
796 if (ibus->register_engine_list) {
797 engine_desc = (IBusEngineDesc *)ibus->register_engine_list->data;
799 else if (ibus->engine_list) {
800 engine_desc = (IBusEngineDesc *)ibus->engine_list->data;
804 /* request engine by name */
805 engine_desc = _find_engine_desc_by_name (ibus, engine_name);
808 if (engine_desc != NULL) {
809 engine = bus_ibus_impl_create_engine (engine_desc);
810 if (engine != NULL) {
811 bus_input_context_set_engine (context, engine);
817 _context_request_next_engine_cb (BusInputContext *context,
820 BusEngineProxy *engine;
821 IBusEngineDesc *desc;
822 IBusEngineDesc *next_desc = NULL;
825 engine = bus_input_context_get_engine (context);
826 if (engine == NULL) {
827 _context_request_engine_cb (context, NULL, ibus);
831 desc = bus_engine_proxy_get_desc (engine);
833 p = g_list_find (ibus->register_engine_list, desc);
838 p = g_list_find (ibus->engine_list, desc);
845 next_desc = (IBusEngineDesc*) p->data;
848 if (ibus->register_engine_list) {
849 next_desc = (IBusEngineDesc *)ibus->register_engine_list->data;
851 else if (ibus->engine_list) {
852 next_desc = (IBusEngineDesc *)ibus->engine_list->data;
856 if (next_desc != NULL) {
857 engine = bus_ibus_impl_create_engine (next_desc);
858 if (engine != NULL) {
859 bus_input_context_set_engine (context, engine);
865 _context_request_prev_engine_cb (BusInputContext *context,
872 _global_engine_destroy_cb (BusEngineProxy *engine,
875 if (ibus->global_engine != engine) {
879 g_signal_handlers_disconnect_by_func (ibus->global_engine,
880 G_CALLBACK (_global_engine_destroy_cb), ibus);
881 g_object_unref (ibus->global_engine);
882 ibus->global_engine = NULL;
886 bus_ibus_impl_set_global_engine (BusIBusImpl *ibus,
887 BusEngineProxy *engine)
889 g_assert (ibus->use_global_engine == TRUE);
891 if (ibus->global_engine == engine) {
895 if (ibus->global_engine) {
896 ibus_object_destroy ((IBusObject *)ibus->global_engine);
897 /* global_engine should be NULL */
898 g_assert (ibus->global_engine == NULL);
901 if (engine != NULL && !IBUS_OBJECT_DESTROYED (engine)) {
902 g_object_ref (engine);
903 ibus->global_engine = engine;
904 g_signal_connect (ibus->global_engine, "destroy",
905 G_CALLBACK (_global_engine_destroy_cb), ibus);
910 _context_engine_changed_cb (BusInputContext *context,
913 BusEngineProxy *engine;
915 if (context != ibus->focused_context ||
916 ibus->use_global_engine != TRUE) {
920 engine = bus_input_context_get_engine (context);
921 bus_ibus_impl_set_global_engine (ibus, engine);
925 _context_focus_out_cb (BusInputContext *context,
928 g_assert (BUS_IS_IBUS_IMPL (ibus));
929 g_assert (BUS_IS_INPUT_CONTEXT (context));
931 /* Do noting if context does not support focus.
932 * Actually, the context should emit focus signals, if it does not support focus */
933 if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
937 /* Do noting if it is not focused context. */
938 if (ibus->focused_context != context) {
942 ibus->focused_context = NULL;
944 if (ibus->panel != NULL) {
945 bus_panel_proxy_focus_out (ibus->panel, context);
948 /* If the use_global_engine option is enabled,
949 * the global engine shoule be detached from the focused context. */
950 if (ibus->use_global_engine) {
951 bus_input_context_set_engine (context, NULL);
954 g_object_unref (context);
958 _context_focus_in_cb (BusInputContext *context,
961 g_assert (BUS_IS_IBUS_IMPL (ibus));
962 g_assert (BUS_IS_INPUT_CONTEXT (context));
964 /* Do nothing if context does not support focus.
965 * The global engine shoule be detached from the focused context. */
966 if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
970 /* Do nothing if it is focused context already. */
971 if (ibus->focused_context == context) {
975 if (ibus->focused_context) {
976 /* focus out context */
977 bus_input_context_focus_out (ibus->focused_context);
978 g_assert (ibus->focused_context == NULL);
981 g_object_ref (context);
982 ibus->focused_context = context;
984 /* If the use_global_engine option is enabled, then we need:
985 * - Switch the context to use the global engine or save the context's
986 * existing engine as global engine.
987 * - Set the context's enabled state according to the saved state.
988 * Note: we get this signal only if the context supports IBUS_CAP_FOCUS. */
989 if (ibus->use_global_engine) {
990 bus_input_context_set_engine (context, ibus->global_engine);
991 if (ibus->global_engine &&
992 bus_engine_proxy_is_enabled (ibus->global_engine)) {
993 bus_input_context_enable (context);
997 if (ibus->panel != NULL) {
998 bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context);
1003 _context_destroy_cb (BusInputContext *context,
1006 g_assert (BUS_IS_IBUS_IMPL (ibus));
1007 g_assert (BUS_IS_INPUT_CONTEXT (context));
1009 if (context == ibus->focused_context) {
1010 /* focus out context */
1011 bus_input_context_focus_out (ibus->focused_context);
1012 g_assert (ibus->focused_context == NULL);
1015 ibus->contexts = g_list_remove (ibus->contexts, context);
1016 g_object_unref (context);
1020 _context_enabled_cb (BusInputContext *context,
1023 if (ibus->focused_context == context && ibus->use_global_engine &&
1024 (bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) != 0) {
1025 ibus->global_engine_enabled = TRUE;
1030 _context_disabled_cb (BusInputContext *context,
1033 if (ibus->focused_context == context && ibus->use_global_engine &&
1034 (bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) != 0) {
1035 ibus->global_engine_enabled = FALSE;
1039 static IBusMessage *
1040 _ibus_create_input_context (BusIBusImpl *ibus,
1041 IBusMessage *message,
1042 BusConnection *connection)
1044 g_assert (BUS_IS_IBUS_IMPL (ibus));
1045 g_assert (message != NULL);
1046 g_assert (BUS_IS_CONNECTION (connection));
1052 BusInputContext *context;
1055 if (!ibus_message_get_args (message,
1057 G_TYPE_STRING, &client,
1059 reply = ibus_message_new_error (message,
1060 DBUS_ERROR_INVALID_ARGS,
1061 "Argument 1 of CreateInputContext should be an string");
1062 ibus_error_free (error);
1066 context = bus_input_context_new (connection, client);
1067 g_object_ref_sink (context);
1068 ibus->contexts = g_list_append (ibus->contexts, context);
1070 static const struct {
1074 { "request-engine", G_CALLBACK (_context_request_engine_cb) },
1075 { "request-next-engine", G_CALLBACK (_context_request_next_engine_cb) },
1076 { "request-prev-engine", G_CALLBACK (_context_request_prev_engine_cb) },
1077 { "engine-changed", G_CALLBACK (_context_engine_changed_cb) },
1078 { "focus-in", G_CALLBACK (_context_focus_in_cb) },
1079 { "focus-out", G_CALLBACK (_context_focus_out_cb) },
1080 { "destroy", G_CALLBACK (_context_destroy_cb) },
1081 { "enabled", G_CALLBACK (_context_enabled_cb) },
1082 { "disabled", G_CALLBACK (_context_disabled_cb) },
1085 for (i = 0; i < G_N_ELEMENTS (signals); i++) {
1086 g_signal_connect (context,
1088 signals[i].callback,
1092 path = ibus_service_get_path ((IBusService *) context);
1093 reply = ibus_message_new_method_return (message);
1094 ibus_message_append_args (reply,
1095 IBUS_TYPE_OBJECT_PATH, &path,
1098 bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
1099 (IBusService *)context);
1103 static IBusMessage *
1104 _ibus_current_input_context (BusIBusImpl *ibus,
1105 IBusMessage *message,
1106 BusConnection *connection)
1108 g_assert (BUS_IS_IBUS_IMPL (ibus));
1109 g_assert (message != NULL);
1110 g_assert (BUS_IS_CONNECTION (connection));
1115 if (!ibus->focused_context)
1117 reply = ibus_message_new_error (message,
1119 "No input context focused");
1123 reply = ibus_message_new_method_return (message);
1124 path = ibus_service_get_path((IBusService *)ibus->focused_context);
1125 ibus_message_append_args (reply,
1126 G_TYPE_STRING, &path,
1133 _factory_destroy_cb (BusFactoryProxy *factory,
1136 g_assert (BUS_IS_IBUS_IMPL (ibus));
1137 g_assert (BUS_IS_FACTORY_PROXY (factory));
1139 IBusComponent *component;
1142 ibus->factory_list = g_list_remove (ibus->factory_list, factory);
1144 component = bus_factory_proxy_get_component (factory);
1146 if (component != NULL) {
1147 p = engines = ibus_component_get_engines (component);
1148 for (; p != NULL; p = p->next) {
1149 if (g_list_find (ibus->register_engine_list, p->data)) {
1150 ibus->register_engine_list = g_list_remove (ibus->register_engine_list, p->data);
1151 g_object_unref (p->data);
1154 g_list_free (engines);
1157 g_object_unref (factory);
1161 bus_ibus_impl_add_factory (BusIBusImpl *ibus,
1162 BusFactoryProxy *factory)
1164 g_assert (BUS_IS_IBUS_IMPL (ibus));
1165 g_assert (BUS_IS_FACTORY_PROXY (factory));
1167 g_object_ref_sink (factory);
1168 ibus->factory_list = g_list_append (ibus->factory_list, factory);
1170 g_signal_connect (factory, "destroy", G_CALLBACK (_factory_destroy_cb), ibus);
1174 static IBusMessage *
1175 _ibus_register_component (BusIBusImpl *ibus,
1176 IBusMessage *message,
1177 BusConnection *connection)
1183 IBusComponent *component;
1184 BusFactoryProxy *factory;
1186 retval = ibus_message_get_args (message, &error,
1187 IBUS_TYPE_COMPONENT, &component,
1191 reply = ibus_message_new_error_printf (message,
1192 DBUS_ERROR_INVALID_ARGS,
1193 "1st Argument must be IBusComponent: %s",
1195 ibus_error_free (error);
1199 g_object_ref_sink (component);
1200 factory = bus_factory_proxy_new (component, connection);
1202 if (factory == NULL) {
1203 reply = ibus_message_new_error (message,
1205 "Can not create factory");
1209 bus_ibus_impl_add_factory (ibus, factory);
1211 engines = ibus_component_get_engines (component);
1213 g_list_foreach (engines, (GFunc) g_object_ref, NULL);
1214 ibus->register_engine_list = g_list_concat (ibus->register_engine_list, engines);
1215 g_object_unref (component);
1217 reply = ibus_message_new_method_return (message);
1221 static IBusMessage *
1222 _ibus_list_engines (BusIBusImpl *ibus,
1223 IBusMessage *message,
1224 BusConnection *connection)
1227 IBusMessageIter iter, sub_iter;
1230 reply = ibus_message_new_method_return (message);
1232 ibus_message_iter_init_append (reply, &iter);
1233 ibus_message_iter_open_container (&iter, IBUS_TYPE_ARRAY, "v", &sub_iter);
1235 engines = bus_registry_get_engines (ibus->registry);
1236 for (p = engines; p != NULL; p = p->next) {
1237 ibus_message_iter_append (&sub_iter, IBUS_TYPE_ENGINE_DESC, &(p->data));
1239 g_list_free (engines);
1240 ibus_message_iter_close_container (&iter, &sub_iter);
1245 static IBusMessage *
1246 _ibus_list_active_engines (BusIBusImpl *ibus,
1247 IBusMessage *message,
1248 BusConnection *connection)
1251 IBusMessageIter iter, sub_iter;
1254 reply = ibus_message_new_method_return (message);
1256 ibus_message_iter_init_append (reply, &iter);
1257 ibus_message_iter_open_container (&iter, IBUS_TYPE_ARRAY, "v", &sub_iter);
1259 for (p = ibus->engine_list; p != NULL; p = p->next) {
1260 ibus_message_iter_append (&sub_iter, IBUS_TYPE_ENGINE_DESC, &(p->data));
1263 for (p = ibus->register_engine_list; p != NULL; p = p->next) {
1264 ibus_message_iter_append (&sub_iter, IBUS_TYPE_ENGINE_DESC, &(p->data));
1266 ibus_message_iter_close_container (&iter, &sub_iter);
1272 static IBusMessage *
1273 _ibus_exit (BusIBusImpl *ibus,
1274 IBusMessage *message,
1275 BusConnection *connection)
1281 if (!ibus_message_get_args (message,
1283 G_TYPE_BOOLEAN, &restart,
1285 reply = ibus_message_new_error (message,
1286 DBUS_ERROR_INVALID_ARGS,
1287 "Argument 1 of Exit should be an boolean");
1288 ibus_error_free (error);
1292 reply = ibus_message_new_method_return (message);
1293 ibus_connection_send ((IBusConnection *) connection, reply);
1294 ibus_connection_flush ((IBusConnection *) connection);
1295 ibus_message_unref (reply);
1297 ibus_object_destroy ((IBusObject *) BUS_DEFAULT_SERVER);
1303 extern gchar **g_argv;
1307 exe = g_strdup_printf ("/proc/%d/exe", getpid ());
1308 exe = g_file_read_link (exe, NULL);
1311 exe = BINDIR"/ibus-daemon";
1313 /* close all fds except stdin, stdout, stderr */
1314 for (fd = 3; fd <= sysconf (_SC_OPEN_MAX); fd ++) {
1318 execv (exe, g_argv);
1319 g_warning ("execv %s failed!", g_argv[0]);
1323 /* should not reach here */
1324 g_assert_not_reached ();
1329 static IBusMessage *
1330 _ibus_ping (BusIBusImpl *ibus,
1331 IBusMessage *message,
1332 BusConnection *connection)
1335 IBusMessageIter src, dst;
1337 reply = ibus_message_new_method_return (message);
1339 ibus_message_iter_init (message, &src);
1340 ibus_message_iter_init_append (reply, &dst);
1342 ibus_message_iter_copy_data (&dst, &src);
1348 bus_ibus_impl_ibus_message (BusIBusImpl *ibus,
1349 BusConnection *connection,
1350 IBusMessage *message)
1352 g_assert (BUS_IS_IBUS_IMPL (ibus));
1353 g_assert (BUS_IS_CONNECTION (connection));
1354 g_assert (message != NULL);
1357 IBusMessage *reply_message = NULL;
1359 static const struct {
1360 const gchar *interface;
1362 IBusMessage *(* handler) (BusIBusImpl *, IBusMessage *, BusConnection *);
1364 /* Introspectable interface */
1365 { DBUS_INTERFACE_INTROSPECTABLE,
1366 "Introspect", _ibus_introspect },
1367 /* IBus interface */
1368 { IBUS_INTERFACE_IBUS, "GetAddress", _ibus_get_address },
1369 { IBUS_INTERFACE_IBUS, "CreateInputContext", _ibus_create_input_context },
1370 { IBUS_INTERFACE_IBUS, "CurrentInputContext", _ibus_current_input_context },
1371 { IBUS_INTERFACE_IBUS, "RegisterComponent", _ibus_register_component },
1372 { IBUS_INTERFACE_IBUS, "ListEngines", _ibus_list_engines },
1373 { IBUS_INTERFACE_IBUS, "ListActiveEngines", _ibus_list_active_engines },
1374 { IBUS_INTERFACE_IBUS, "Exit", _ibus_exit },
1375 { IBUS_INTERFACE_IBUS, "Ping", _ibus_ping },
1378 ibus_message_set_sender (message, bus_connection_get_unique_name (connection));
1379 ibus_message_set_destination (message, DBUS_SERVICE_DBUS);
1381 if (ibus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL) {
1382 for (i = 0; i < G_N_ELEMENTS (handlers); i++) {
1383 if (ibus_message_is_method_call (message,
1384 handlers[i].interface,
1385 handlers[i].name)) {
1387 reply_message = handlers[i].handler (ibus, message, connection);
1388 if (reply_message) {
1390 ibus_message_set_sender (reply_message, DBUS_SERVICE_DBUS);
1391 ibus_message_set_destination (reply_message, bus_connection_get_unique_name (connection));
1392 ibus_message_set_no_reply (reply_message, TRUE);
1394 ibus_connection_send ((IBusConnection *) connection, reply_message);
1395 ibus_message_unref (reply_message);
1398 g_signal_stop_emission_by_name (ibus, "ibus-message");
1404 return IBUS_SERVICE_CLASS(bus_ibus_impl_parent_class)->ibus_message (
1405 (IBusService *) ibus,
1406 (IBusConnection *) connection,
1411 bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
1414 g_assert (BUS_IS_IBUS_IMPL (ibus));
1416 BusFactoryProxy *factory;
1418 factory = (BusFactoryProxy *) g_hash_table_lookup (ibus->factory_dict, path);
1424 bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus)
1426 g_assert (BUS_IS_IBUS_IMPL (ibus));
1428 return ibus->hotkey_profile;
1432 bus_ibus_impl_get_keymap (BusIBusImpl *ibus)
1435 g_assert (BUS_IS_IBUS_IMPL (ibus));
1437 return ibus->keymap;
1441 bus_ibus_impl_get_registry (BusIBusImpl *ibus)
1444 g_assert (BUS_IS_IBUS_IMPL (ibus));
1446 return ibus->registry;
1450 bus_ibus_impl_registry_changed (BusIBusImpl *ibus)
1452 g_assert (BUS_IS_IBUS_IMPL (ibus));
1454 IBusMessage *message;
1456 message = ibus_message_new_signal (IBUS_PATH_IBUS,
1457 IBUS_INTERFACE_IBUS,
1459 ibus_message_append_args (message,
1461 ibus_message_set_sender (message, IBUS_SERVICE_IBUS);
1463 bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
1465 ibus_message_unref (message);