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_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,
59 static void bus_ibus_impl_set_preload_engines
62 static void bus_ibus_impl_set_use_sys_layout
66 static void bus_ibus_impl_registry_changed (BusIBusImpl *ibus);
67 static void _factory_destroy_cb (BusFactoryProxy *factory,
70 G_DEFINE_TYPE(BusIBusImpl, bus_ibus_impl, IBUS_TYPE_SERVICE)
73 bus_ibus_impl_get_default (void)
75 static BusIBusImpl *ibus = NULL;
78 ibus = (BusIBusImpl *) g_object_new (BUS_TYPE_IBUS_IMPL,
79 "path", IBUS_PATH_IBUS,
81 bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
88 bus_ibus_impl_class_init (BusIBusImplClass *klass)
90 IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
92 ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_ibus_impl_destroy;
94 IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) bus_ibus_impl_ibus_message;
99 _panel_destroy_cb (BusPanelProxy *panel,
102 g_assert (BUS_IS_PANEL_PROXY (panel));
103 g_assert (BUS_IS_IBUS_IMPL (ibus));
105 g_return_if_fail (ibus->panel == panel);
108 g_object_unref (panel);
112 bus_ibus_impl_set_hotkey (BusIBusImpl *ibus,
116 g_assert (BUS_IS_IBUS_IMPL (ibus));
121 ibus_hotkey_profile_remove_hotkey_by_event (ibus->hotkey_profile, hotkey);
127 g_return_if_fail (G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY);
128 array = g_value_get_boxed (value);
130 for (i = 0; i < array->n_values; i++) {
133 str = g_value_array_get_nth (array, i);
134 g_return_if_fail (G_VALUE_TYPE (str) == G_TYPE_STRING);
136 ibus_hotkey_profile_add_hotkey_from_string (ibus->hotkey_profile,
137 g_value_get_string (str),
144 bus_ibus_impl_set_trigger (BusIBusImpl *ibus,
147 GQuark hotkey = g_quark_from_static_string ("trigger");
148 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
150 ibus_hotkey_profile_add_hotkey (ibus->hotkey_profile,
158 bus_ibus_impl_set_next_engine (BusIBusImpl *ibus,
161 GQuark hotkey = g_quark_from_static_string ("next-engine");
162 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
166 bus_ibus_impl_set_prev_engine (BusIBusImpl *ibus,
169 GQuark hotkey = g_quark_from_static_string ("prev-engine");
170 bus_ibus_impl_set_hotkey (ibus, hotkey, value);
174 bus_ibus_impl_set_preload_engines (BusIBusImpl *ibus,
177 GList *engine_list = NULL;
179 g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
180 g_list_free (ibus->engine_list);
182 if (value != NULL && G_VALUE_TYPE (value) == G_TYPE_VALUE_ARRAY) {
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;
191 if (G_VALUE_TYPE (&array->values[i]) != G_TYPE_STRING)
194 engine_name = g_value_get_string (&array->values[i]);
196 engine = bus_registry_find_engine_by_name (ibus->registry, engine_name);
198 if (engine == NULL || g_list_find (engine_list, engine) != NULL)
201 engine_list = g_list_append (engine_list, engine);
205 g_list_foreach (engine_list, (GFunc) g_object_ref, NULL);
206 ibus->engine_list = engine_list;
208 if (ibus->engine_list) {
209 IBusComponent *component;
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);
219 bus_ibus_impl_set_use_sys_layout (BusIBusImpl *ibus,
222 if (value != NULL && G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) {
223 ibus->use_sys_layout = g_value_get_boolean (value);
228 _engine_desc_cmp (IBusEngineDesc *desc1,
229 IBusEngineDesc *desc2)
231 return - ((gint) desc1->rank) + ((gint) desc2->rank);
235 bus_ibus_impl_set_default_preload_engines (BusIBusImpl *ibus)
237 g_assert (BUS_IS_IBUS_IMPL (ibus));
239 static gboolean done = FALSE;
240 GValue value = { 0 };
241 GList *engines, *list;
245 if (done || ibus->config == NULL) {
249 if (ibus_config_get_value (ibus->config, "general", "preload_engines", &value)) {
251 g_value_unset (&value);
256 lang = g_strdup (setlocale (LC_ALL, NULL));
257 p = index (lang, '.');
262 engines = bus_registry_get_engines_by_language (ibus->registry, lang);
263 if (engines == NULL) {
264 p = index (lang, '_');
267 engines = bus_registry_get_engines_by_language (ibus->registry, lang);
272 /* sort engines by rank */
273 engines = g_list_sort (engines, (GCompareFunc) _engine_desc_cmp);
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;
280 desc = (IBusEngineDesc *)list->data;
282 /* ignore engines with rank <== 0 */
285 g_value_init (&name, G_TYPE_STRING);
286 g_value_set_string (&name, desc->name);
287 g_value_array_append (array, &name);
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);
296 bus_ibus_impl_reload_config (BusIBusImpl *ibus)
298 g_assert (BUS_IS_IBUS_IMPL (ibus));
301 GValue value = { 0 };
303 const static struct {
306 void ( *func) (BusIBusImpl *, GValue *);
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 },
316 for (i = 0; entries[i].section != NULL; i++) {
317 if (ibus->config != NULL &&
318 ibus_config_get_value (ibus->config,
322 entries[i].func (ibus, &value);
323 g_value_unset (&value);
326 entries[i].func (ibus, NULL);
332 _config_value_changed_cb (IBusConfig *config,
338 g_assert (IBUS_IS_CONFIG (config));
342 g_assert (BUS_IS_IBUS_IMPL (ibus));
346 const static struct {
349 void ( *func) (BusIBusImpl *, GValue *);
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 },
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);
369 _config_destroy_cb (IBusConfig *config,
372 g_assert (IBUS_IS_CONFIG (config));
373 g_assert (BUS_IS_IBUS_IMPL (ibus));
375 g_assert (ibus->config == config);
377 g_object_unref (ibus->config);
382 _registry_changed_cb (BusRegistry *registry,
385 bus_ibus_impl_registry_changed (ibus);
389 _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
391 const gchar *old_name,
392 const gchar *new_name,
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));
401 BusFactoryProxy *factory;
403 if (g_strcmp0 (name, IBUS_SERVICE_PANEL) == 0) {
404 if (g_strcmp0 (new_name, "") != 0) {
405 BusConnection *connection;
407 if (ibus->panel != NULL) {
408 ibus_object_destroy (IBUS_OBJECT (ibus->panel));
412 connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
413 g_return_if_fail (connection != NULL);
415 ibus->panel = bus_panel_proxy_new (connection);
416 g_object_ref_sink (ibus->panel);
418 g_signal_connect (ibus->panel,
420 G_CALLBACK (_panel_destroy_cb),
423 if (ibus->focused_context != NULL) {
424 bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context);
428 else if (g_strcmp0 (name, IBUS_SERVICE_CONFIG) == 0) {
429 if (g_strcmp0 (new_name, "") != 0) {
430 BusConnection *connection;
432 if (ibus->config != NULL) {
433 ibus_object_destroy (IBUS_OBJECT (ibus->config));
437 connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
438 g_return_if_fail (connection != NULL);
440 ibus->config = g_object_new (IBUS_TYPE_CONFIG,
442 "path", IBUS_PATH_CONFIG,
443 "connection", connection,
445 g_object_ref_sink (ibus->config);
447 g_signal_connect (ibus->config,
449 G_CALLBACK (_config_value_changed_cb),
452 g_signal_connect (ibus->config,
454 G_CALLBACK (_config_destroy_cb),
457 bus_ibus_impl_set_default_preload_engines (ibus);
458 bus_ibus_impl_reload_config (ibus);
462 factory = bus_registry_name_owner_changed (ibus->registry, name, old_name, new_name);
465 bus_ibus_impl_add_factory (ibus, factory);
470 bus_ibus_impl_init (BusIBusImpl *ibus)
472 ibus->factory_dict = g_hash_table_new_full (
476 (GDestroyNotify) g_object_unref);
478 ibus->engine_list = NULL;
479 ibus->register_engine_list = NULL;
480 ibus->contexts = NULL;
481 ibus->focused_context = NULL;
485 ibus->registry = bus_registry_new ();
487 g_signal_connect (ibus->registry,
489 G_CALLBACK (_registry_changed_cb),
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);
498 ibus->hotkey_profile = ibus_hotkey_profile_new ();
499 ibus->keymap = ibus_keymap_get ("us");
501 ibus->use_sys_layout = FALSE;
503 bus_ibus_impl_reload_config (ibus);
505 g_signal_connect (BUS_DEFAULT_DBUS,
506 "name-owner-changed",
507 G_CALLBACK (_dbus_name_owner_changed_cb),
512 bus_ibus_impl_destroy (BusIBusImpl *ibus)
519 bus_registry_stop_all_components (ibus->registry);
525 while ((pid = waitpid (0, &status, WNOHANG)) > 0);
527 if (pid == -1) { /* all children finished */
530 if (pid == 0) { /* no child status changed */
533 if (timeout >= G_USEC_PER_SEC) {
536 old = signal (SIGTERM, SIG_IGN);
537 kill (-getpid (), SIGTERM);
538 signal (SIGTERM, old);
542 g_warning ("Not every child processes exited!");
549 g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL);
550 g_list_free (ibus->engine_list);
551 ibus->engine_list = NULL;
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;
557 if (ibus->factory_dict != NULL) {
558 g_hash_table_destroy (ibus->factory_dict);
559 ibus->factory_dict = NULL;
562 if (ibus->hotkey_profile != NULL) {
563 g_object_unref (ibus->hotkey_profile);
564 ibus->hotkey_profile = NULL;
567 if (ibus->keymap != NULL) {
568 g_object_unref (ibus->keymap);
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));
577 /* introspectable interface */
579 _ibus_introspect (BusIBusImpl *ibus,
580 IBusMessage *message,
581 BusConnection *connection)
583 static const gchar *introspect =
584 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
586 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
587 " <method name=\"Introspect\">\n"
588 " <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
591 " <interface name=\"org.freedesktop.IBus\">\n"
592 " <method name=\"GetAddress\">\n"
593 " <arg name=\"address\" direction=\"out\" type=\"s\"/>\n"
595 " <method name=\"CreateInputContext\">\n"
596 " <arg name=\"name\" direction=\"in\" type=\"s\"/>\n"
597 " <arg name=\"context\" direction=\"out\" type=\"o\"/>\n"
599 " <method name=\"CurrentInputContext\">\n"
600 " <arg name=\"name\" direction=\"out\" type=\"s\"/>\n"
602 " <method name=\"RegisterComponent\">\n"
603 " <arg name=\"components\" direction=\"in\" type=\"v\"/>\n"
605 " <method name=\"ListEngines\">\n"
606 " <arg name=\"engines\" direction=\"out\" type=\"av\"/>\n"
608 " <method name=\"ListActiveEngines\">\n"
609 " <arg name=\"engines\" direction=\"out\" type=\"av\"/>\n"
611 " <method name=\"Exit\">\n"
612 " <arg name=\"restart\" direction=\"in\" type=\"b\"/>\n"
614 " <method name=\"Ping\">\n"
615 " <arg name=\"data\" direction=\"in\" type=\"v\"/>\n"
616 " <arg name=\"data\" direction=\"out\" type=\"v\"/>\n"
618 " <signal name=\"RegistryChanged\">\n"
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,
629 return reply_message;
635 _ibus_get_address (BusIBusImpl *ibus,
636 IBusMessage *message,
637 BusConnection *connection)
639 const gchar *address;
642 address = ibus_server_get_address (IBUS_SERVER (BUS_DEFAULT_SERVER));
644 reply = ibus_message_new_method_return (message);
645 ibus_message_append_args (reply,
646 G_TYPE_STRING, &address,
652 static BusEngineProxy *
653 bus_ibus_impl_create_engine (IBusEngineDesc *engine_desc)
656 BusFactoryProxy *factory;
657 BusEngineProxy *engine;
660 factory = bus_factory_proxy_get_from_engine (engine_desc);
662 if (factory == NULL) {
663 /* try to execute the engine */
664 comp = ibus_component_get_from_engine (engine_desc);
667 if (!ibus_component_is_running (comp)) {
668 ibus_component_start (comp, g_verbose);
669 g_get_current_time (&t1);
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) {
678 g_get_current_time (&t2);
679 if (t2.tv_sec - t1.tv_sec >= 5)
684 factory = bus_factory_proxy_get_from_engine (engine_desc);
688 if (factory == NULL) {
692 g_object_ref (factory);
693 engine = bus_factory_proxy_create_engine (factory, engine_desc);
694 g_object_unref (factory);
700 _context_request_engine_cb (BusInputContext *context,
704 IBusEngineDesc *engine_desc = NULL;
705 BusEngineProxy *engine;
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;
712 else if (ibus->engine_list) {
713 engine_desc = (IBusEngineDesc *)ibus->engine_list->data;
717 /* request engine by name */
719 gboolean found = FALSE;
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) {
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) {
746 if (engine_desc == NULL) {
750 engine = bus_ibus_impl_create_engine (engine_desc);
752 if (engine == NULL) {
756 bus_input_context_set_engine (context, engine);
760 _context_request_next_engine_cb (BusInputContext *context,
763 BusEngineProxy *engine;
764 IBusEngineDesc *desc;
765 IBusEngineDesc *next_desc = NULL;
768 engine = bus_input_context_get_engine (context);
769 if (engine == NULL) {
770 _context_request_engine_cb (context, NULL, ibus);
774 desc = bus_engine_proxy_get_desc (engine);
776 p = g_list_find (ibus->register_engine_list, desc);
781 p = g_list_find (ibus->engine_list, desc);
788 next_desc = (IBusEngineDesc*) p->data;
791 if (ibus->register_engine_list) {
792 next_desc = (IBusEngineDesc *)ibus->register_engine_list->data;
794 else if (ibus->engine_list) {
795 next_desc = (IBusEngineDesc *)ibus->engine_list->data;
799 if (next_desc != NULL) {
800 engine = bus_ibus_impl_create_engine (next_desc);
801 bus_input_context_set_engine (context, engine);
806 _context_request_prev_engine_cb (BusInputContext *context,
813 _context_focus_out_cb (BusInputContext *context,
816 g_assert (BUS_IS_IBUS_IMPL (ibus));
817 g_assert (BUS_IS_INPUT_CONTEXT (context));
819 if (ibus->focused_context != context)
822 if (ibus->panel != NULL) {
823 bus_panel_proxy_focus_out (ibus->panel, context);
827 g_object_unref (context);
828 ibus->focused_context = NULL;
833 _context_focus_in_cb (BusInputContext *context,
836 g_assert (BUS_IS_IBUS_IMPL (ibus));
837 g_assert (BUS_IS_INPUT_CONTEXT (context));
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);
845 g_object_ref (context);
846 ibus->focused_context = context;
848 if (ibus->panel != NULL) {
849 bus_panel_proxy_focus_in (ibus->panel, ibus->focused_context);
855 _context_destroy_cb (BusInputContext *context,
858 g_assert (BUS_IS_IBUS_IMPL (ibus));
859 g_assert (BUS_IS_INPUT_CONTEXT (context));
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);
867 ibus->contexts = g_list_remove (ibus->contexts, context);
868 g_object_unref (context);
872 _ibus_create_input_context (BusIBusImpl *ibus,
873 IBusMessage *message,
874 BusConnection *connection)
876 g_assert (BUS_IS_IBUS_IMPL (ibus));
877 g_assert (message != NULL);
878 g_assert (BUS_IS_CONNECTION (connection));
884 BusInputContext *context;
887 if (!ibus_message_get_args (message,
889 G_TYPE_STRING, &client,
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);
898 context = bus_input_context_new (connection, client);
899 g_object_ref_sink (context);
900 ibus->contexts = g_list_append (ibus->contexts, context);
902 static const struct {
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) },
914 for (i = 0; i < G_N_ELEMENTS (signals); i++) {
915 g_signal_connect (context,
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,
927 bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
928 (IBusService *)context);
933 _ibus_current_input_context (BusIBusImpl *ibus,
934 IBusMessage *message,
935 BusConnection *connection)
937 g_assert (BUS_IS_IBUS_IMPL (ibus));
938 g_assert (message != NULL);
939 g_assert (BUS_IS_CONNECTION (connection));
944 if (!ibus->focused_context)
946 reply = ibus_message_new_error (message,
948 "No input context focused");
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,
962 _factory_destroy_cb (BusFactoryProxy *factory,
965 g_assert (BUS_IS_IBUS_IMPL (ibus));
966 g_assert (BUS_IS_FACTORY_PROXY (factory));
968 IBusComponent *component;
971 ibus->factory_list = g_list_remove (ibus->factory_list, factory);
973 component = bus_factory_proxy_get_component (factory);
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);
983 g_list_free (engines);
986 g_object_unref (factory);
990 bus_ibus_impl_add_factory (BusIBusImpl *ibus,
991 BusFactoryProxy *factory)
993 g_assert (BUS_IS_IBUS_IMPL (ibus));
994 g_assert (BUS_IS_FACTORY_PROXY (factory));
996 g_object_ref_sink (factory);
997 ibus->factory_list = g_list_append (ibus->factory_list, factory);
999 g_signal_connect (factory, "destroy", G_CALLBACK (_factory_destroy_cb), ibus);
1003 static IBusMessage *
1004 _ibus_register_component (BusIBusImpl *ibus,
1005 IBusMessage *message,
1006 BusConnection *connection)
1012 IBusComponent *component;
1013 BusFactoryProxy *factory;
1015 retval = ibus_message_get_args (message, &error,
1016 IBUS_TYPE_COMPONENT, &component,
1020 reply = ibus_message_new_error_printf (message,
1021 DBUS_ERROR_INVALID_ARGS,
1022 "1st Argument must be IBusComponent: %s",
1024 ibus_error_free (error);
1028 g_object_ref_sink (component);
1029 factory = bus_factory_proxy_new (component, connection);
1031 if (factory == NULL) {
1032 reply = ibus_message_new_error (message,
1034 "Can not create factory");
1038 bus_ibus_impl_add_factory (ibus, factory);
1040 engines = ibus_component_get_engines (component);
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);
1046 reply = ibus_message_new_method_return (message);
1050 static IBusMessage *
1051 _ibus_list_engines (BusIBusImpl *ibus,
1052 IBusMessage *message,
1053 BusConnection *connection)
1056 IBusMessageIter iter, sub_iter;
1059 reply = ibus_message_new_method_return (message);
1061 ibus_message_iter_init_append (reply, &iter);
1062 ibus_message_iter_open_container (&iter, IBUS_TYPE_ARRAY, "v", &sub_iter);
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));
1068 g_list_free (engines);
1069 ibus_message_iter_close_container (&iter, &sub_iter);
1074 static IBusMessage *
1075 _ibus_list_active_engines (BusIBusImpl *ibus,
1076 IBusMessage *message,
1077 BusConnection *connection)
1080 IBusMessageIter iter, sub_iter;
1083 reply = ibus_message_new_method_return (message);
1085 ibus_message_iter_init_append (reply, &iter);
1086 ibus_message_iter_open_container (&iter, IBUS_TYPE_ARRAY, "v", &sub_iter);
1088 for (p = ibus->engine_list; p != NULL; p = p->next) {
1089 ibus_message_iter_append (&sub_iter, IBUS_TYPE_ENGINE_DESC, &(p->data));
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));
1095 ibus_message_iter_close_container (&iter, &sub_iter);
1101 static IBusMessage *
1102 _ibus_exit (BusIBusImpl *ibus,
1103 IBusMessage *message,
1104 BusConnection *connection)
1110 if (!ibus_message_get_args (message,
1112 G_TYPE_BOOLEAN, &restart,
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);
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);
1126 ibus_object_destroy ((IBusObject *) BUS_DEFAULT_SERVER);
1132 extern gchar **g_argv;
1136 exe = g_strdup_printf ("/proc/%d/exe", getpid ());
1137 exe = g_file_read_link (exe, NULL);
1140 exe = BINDIR"/ibus-daemon";
1142 /* close all fds except stdin, stdout, stderr */
1143 for (fd = 3; fd <= sysconf (_SC_OPEN_MAX); fd ++) {
1147 execv (exe, g_argv);
1148 g_warning ("execv %s failed!", g_argv[0]);
1152 /* should not reach here */
1153 g_assert_not_reached ();
1158 static IBusMessage *
1159 _ibus_ping (BusIBusImpl *ibus,
1160 IBusMessage *message,
1161 BusConnection *connection)
1164 IBusMessageIter src, dst;
1166 reply = ibus_message_new_method_return (message);
1168 ibus_message_iter_init (message, &src);
1169 ibus_message_iter_init_append (reply, &dst);
1171 ibus_message_iter_copy_data (&dst, &src);
1177 bus_ibus_impl_ibus_message (BusIBusImpl *ibus,
1178 BusConnection *connection,
1179 IBusMessage *message)
1181 g_assert (BUS_IS_IBUS_IMPL (ibus));
1182 g_assert (BUS_IS_CONNECTION (connection));
1183 g_assert (message != NULL);
1186 IBusMessage *reply_message = NULL;
1188 static const struct {
1189 const gchar *interface;
1191 IBusMessage *(* handler) (BusIBusImpl *, IBusMessage *, BusConnection *);
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 },
1207 ibus_message_set_sender (message, bus_connection_get_unique_name (connection));
1208 ibus_message_set_destination (message, DBUS_SERVICE_DBUS);
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)) {
1216 reply_message = handlers[i].handler (ibus, message, connection);
1217 if (reply_message) {
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);
1223 ibus_connection_send ((IBusConnection *) connection, reply_message);
1224 ibus_message_unref (reply_message);
1227 g_signal_stop_emission_by_name (ibus, "ibus-message");
1233 return IBUS_SERVICE_CLASS(bus_ibus_impl_parent_class)->ibus_message (
1234 (IBusService *) ibus,
1235 (IBusConnection *) connection,
1240 bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
1243 g_assert (BUS_IS_IBUS_IMPL (ibus));
1245 BusFactoryProxy *factory;
1247 factory = (BusFactoryProxy *) g_hash_table_lookup (ibus->factory_dict, path);
1253 bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus)
1255 g_assert (BUS_IS_IBUS_IMPL (ibus));
1257 return ibus->hotkey_profile;
1261 bus_ibus_impl_get_keymap (BusIBusImpl *ibus)
1264 g_assert (BUS_IS_IBUS_IMPL (ibus));
1266 return ibus->keymap;
1270 bus_ibus_impl_get_registry (BusIBusImpl *ibus)
1273 g_assert (BUS_IS_IBUS_IMPL (ibus));
1275 return ibus->registry;
1279 bus_ibus_impl_registry_changed (BusIBusImpl *ibus)
1281 g_assert (BUS_IS_IBUS_IMPL (ibus));
1283 IBusMessage *message;
1285 message = ibus_message_new_signal (IBUS_PATH_IBUS,
1286 IBUS_INTERFACE_IBUS,
1288 ibus_message_append_args (message,
1290 ibus_message_set_sender (message, IBUS_SERVICE_IBUS);
1292 bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
1294 ibus_message_unref (message);