diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c index e92b373..3af090d 100644 --- a/bus/ibusimpl.c +++ b/bus/ibusimpl.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "ibusimpl.h" #include "dbusimpl.h" @@ -388,6 +389,41 @@ bus_ibus_impl_init (BusIBusImpl *ibus) static void bus_ibus_impl_destroy (BusIBusImpl *ibus) { + pid_t pid; + glong timeout; + gint status; + gboolean flag; + + bus_registry_stop_all_components (ibus->registry); + + pid = 0; + timeout = 0; + flag = FALSE; + while (1) { + while ((pid = waitpid (0, &status, WNOHANG)) > 0); + + if (pid == -1) { /* all children finished */ + break; + } + if (pid == 0) { /* no child status changed */ + usleep (1000); + timeout += 1000; + if (timeout >= G_USEC_PER_SEC) { + if (flag == FALSE) { + gpointer old; + old = signal (SIGTERM, SIG_IGN); + kill (-getpid (), SIGTERM); + signal (SIGTERM, old); + flag = TRUE; + } + else { + g_warning ("Not every child processes exited!"); + break; + } + } + } + }; + g_list_foreach (ibus->engine_list, (GFunc) g_object_unref, NULL); g_list_free (ibus->engine_list); ibus->engine_list = NULL; @@ -407,7 +443,7 @@ bus_ibus_impl_destroy (BusIBusImpl *ibus) } bus_server_quit (BUS_DEFAULT_SERVER); - + ibus_object_destroy ((IBusObject *) BUS_DEFAULT_SERVER); IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (ibus)); } @@ -832,7 +868,6 @@ _ibus_list_active_engines (BusIBusImpl *ibus, return reply; } -extern gchar **g_argv; static IBusMessage * _ibus_exit (BusIBusImpl *ibus, @@ -859,32 +894,28 @@ _ibus_exit (BusIBusImpl *ibus, ibus_connection_flush ((IBusConnection *) connection); ibus_message_unref (reply); - + ibus_object_destroy ((IBusObject *) ibus); + if (!restart) { exit (0); } else { - glong timeout; - gint fd; - gint status; - - bus_registry_stop_all_components (ibus->registry); - ibus_object_destroy ((IBusObject *) BUS_DEFAULT_SERVER); - for (fd = 3; fd <= sysconf (_SC_OPEN_MAX); fd++) { - close (fd); + extern gchar **g_argv; + gchar *exe; + + exe = g_strdup_printf ("/proc/%d/exe", getpid ()); + if (!g_file_test (exe, G_FILE_TEST_EXISTS)) { + g_free (exe); + exe = g_argv[0]; } - for (timeout = 0; waitpid (0, &status, WNOHANG) != -1;) { - usleep (1000); - timeout += 1000; - if (timeout >= G_USEC_PER_SEC * 2) { - g_warning ("Not every child processes exited!"); - } - }; - execv (g_argv[0], g_argv); + execv (exe, g_argv); g_warning ("execv %s failed!", g_argv[0]); exit (-1); } + /* should not reach here */ + g_assert_not_reached (); + return NULL; } diff --git a/bus/inputcontext.c b/bus/inputcontext.c index be45bbe..e8fc1da 100644 --- a/bus/inputcontext.c +++ b/bus/inputcontext.c @@ -100,6 +100,8 @@ static gboolean bus_input_context_send_signal (BusInputContext *context const gchar *signal_name, GType first_arg_type, ...); + +static void bus_input_context_unset_engine (BusInputContext *context); static void _engine_destroy_cb (BusEngineProxy *factory, BusInputContext *context); @@ -486,11 +488,7 @@ bus_input_context_destroy (BusInputContext *context) } if (priv->engine) { - g_signal_handlers_disconnect_by_func (priv->engine, - G_CALLBACK (_engine_destroy_cb), - context); - g_object_unref (priv->engine); - priv->engine = NULL; + bus_input_context_unset_engine (context); } if (priv->connection) { @@ -562,7 +560,7 @@ _ic_process_key_event_reply_cb (gpointer data, retval = (gboolean) GPOINTER_TO_INT (data); call_data = (CallData *) user_data; - + BusInputContextPrivate *priv; priv = BUS_INPUT_CONTEXT_GET_PRIVATE (call_data->context); @@ -1122,7 +1120,7 @@ _engine_destroy_cb (BusEngineProxy *engine, g_assert (priv->engine == engine); - bus_input_context_set_engine (context, NULL); + bus_input_context_unset_engine (context); } static void @@ -1408,6 +1406,48 @@ bus_input_context_disable (BusInputContext *context) 0); } +const static struct { + const gchar *name; + GCallback callback; +} signals [] = { + { "commit-text", G_CALLBACK (_engine_commit_text_cb) }, + { "forward-key-event", G_CALLBACK (_engine_forward_key_event_cb) }, + { "update-preedit-text", G_CALLBACK (_engine_update_preedit_text_cb) }, + { "show-preedit-text", G_CALLBACK (_engine_show_preedit_text_cb) }, + { "hide-preedit-text", G_CALLBACK (_engine_hide_preedit_text_cb) }, + { "update-auxiliary-text", G_CALLBACK (_engine_update_auxiliary_text_cb) }, + { "show-auxiliary-text", G_CALLBACK (_engine_show_auxiliary_text_cb) }, + { "hide-auxiliary-text", G_CALLBACK (_engine_hide_auxiliary_text_cb) }, + { "update-lookup-table", G_CALLBACK (_engine_update_lookup_table_cb) }, + { "show-lookup-table", G_CALLBACK (_engine_show_lookup_table_cb) }, + { "hide-lookup-table", G_CALLBACK (_engine_hide_lookup_table_cb) }, + { "page-up-lookup-table", G_CALLBACK (_engine_page_up_lookup_table_cb) }, + { "page-down-lookup-table", G_CALLBACK (_engine_page_down_lookup_table_cb) }, + { "cursor-up-lookup-table", G_CALLBACK (_engine_cursor_up_lookup_table_cb) }, + { "cursor-down-lookup-table", G_CALLBACK (_engine_cursor_down_lookup_table_cb) }, + { "register-properties", G_CALLBACK (_engine_register_properties_cb) }, + { "update-property", G_CALLBACK (_engine_update_property_cb) }, + { "destroy", G_CALLBACK (_engine_destroy_cb) }, + { NULL, 0 } +}; + +static void +bus_input_context_unset_engine (BusInputContext *context) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + + BusInputContextPrivate *priv; + priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); + + if (priv->engine) { + gint i; + for (i = 0; signals[i].name != NULL; i++) { + g_signal_handlers_disconnect_by_func (priv->engine, signals[i].callback, context); + } + g_object_unref (priv->engine); + priv->engine = NULL; + } +} void bus_input_context_set_engine (BusInputContext *context, @@ -1420,56 +1460,25 @@ bus_input_context_set_engine (BusInputContext *context, priv = BUS_INPUT_CONTEXT_GET_PRIVATE (context); if (priv->engine != NULL) { - g_signal_handlers_disconnect_by_func (priv->engine, _engine_destroy_cb, context); - ibus_object_destroy ((IBusObject *) priv->engine); - g_object_unref (priv->engine); - priv->engine = NULL; + bus_input_context_unset_engine (context); } if (engine == NULL) { bus_input_context_disable (context); - g_signal_emit (context, - context_signals[ENGINE_CHANGED], - 0); - return; } - - priv->engine = engine; - g_object_ref (priv->engine); - - gint i; - const static struct { - const gchar *name; - GCallback callback; - } signals [] = { - { "commit-text", G_CALLBACK (_engine_commit_text_cb) }, - { "forward-key-event", G_CALLBACK (_engine_forward_key_event_cb) }, - { "update-preedit-text", G_CALLBACK (_engine_update_preedit_text_cb) }, - { "show-preedit-text", G_CALLBACK (_engine_show_preedit_text_cb) }, - { "hide-preedit-text", G_CALLBACK (_engine_hide_preedit_text_cb) }, - { "update-auxiliary-text", G_CALLBACK (_engine_update_auxiliary_text_cb) }, - { "show-auxiliary-text", G_CALLBACK (_engine_show_auxiliary_text_cb) }, - { "hide-auxiliary-text", G_CALLBACK (_engine_hide_auxiliary_text_cb) }, - { "update-lookup-table", G_CALLBACK (_engine_update_lookup_table_cb) }, - { "show-lookup-table", G_CALLBACK (_engine_show_lookup_table_cb) }, - { "hide-lookup-table", G_CALLBACK (_engine_hide_lookup_table_cb) }, - { "page-up-lookup-table", G_CALLBACK (_engine_page_up_lookup_table_cb) }, - { "page-down-lookup-table", G_CALLBACK (_engine_page_down_lookup_table_cb) }, - { "cursor-up-lookup-table", G_CALLBACK (_engine_cursor_up_lookup_table_cb) }, - { "cursor-down-lookup-table", G_CALLBACK (_engine_cursor_down_lookup_table_cb) }, - { "register-properties", G_CALLBACK (_engine_register_properties_cb) }, - { "update-property", G_CALLBACK (_engine_update_property_cb) }, - { "destroy", G_CALLBACK (_engine_destroy_cb) }, - { NULL, 0 } - }; - - for (i = 0; signals[i].name != NULL; i++) { - g_signal_connect (priv->engine, - signals[i].name, - signals[i].callback, - context); + else { + gint i; + priv->engine = engine; + g_object_ref (priv->engine); + + for (i = 0; signals[i].name != NULL; i++) { + g_signal_connect (priv->engine, + signals[i].name, + signals[i].callback, + context); + } + bus_engine_proxy_set_cursor_location (priv->engine, priv->x, priv->y, priv->w, priv->h); } - g_signal_emit (context, context_signals[ENGINE_CHANGED], 0); diff --git a/bus/main.c b/bus/main.c index eec1df0..71c8dbe 100644 --- a/bus/main.c +++ b/bus/main.c @@ -29,6 +29,7 @@ gchar **g_argv = NULL; static gboolean daemonize = FALSE; static gboolean single = FALSE; static gboolean xim = FALSE; +static gboolean replace = FALSE; static gchar *panel = "default"; static gchar *config = "default"; static gchar *desktop = "gnome"; @@ -45,7 +46,8 @@ static const GOptionEntry entries[] = { "panel", 'p', 0, G_OPTION_ARG_STRING, &panel, "specify the cmdline of panel program.", "cmdline" }, { "config", 'c', 0, G_OPTION_ARG_STRING, &config, "specify the cmdline of config program.", "cmdline" }, { "address", 'a', 0, G_OPTION_ARG_STRING, &address, "specify the address of ibus daemon.", "address" }, - { "re-scan", 'r', 0, G_OPTION_ARG_NONE, &g_rescan, "force to re-scan components, and re-create registry cache.", NULL }, + { "replace", 'r', 0, G_OPTION_ARG_NONE, &replace, "if there is an old ibus-daemon is running, it will be replaced.", NULL }, + { "re-scan", 't', 0, G_OPTION_ARG_NONE, &g_rescan, "force to re-scan components, and re-create registry cache.", NULL }, { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "verbose.", NULL }, { NULL }, }; @@ -88,6 +90,7 @@ main (gint argc, gchar **argv) { GOptionContext *context; BusServer *server; + IBusBus *bus; GError *error = NULL; @@ -103,9 +106,6 @@ main (gint argc, gchar **argv) exit (-1); } - /* create a new process group */ - setpgrp (); - if (daemonize) { if (daemon (1, 0) != 0) { g_printerr ("Can not daemonize ibus.\n"); @@ -113,8 +113,28 @@ main (gint argc, gchar **argv) } } + /* create a new process group */ + setpgrp (); + g_type_init (); + /* check if ibus-daemon is running in this session */ + bus = ibus_bus_new (); + + if (ibus_bus_is_connected (bus)) { + if (!replace) { + g_printerr ("current session already has an ibus-daemon.\n"); + exit (-1); + } + ibus_bus_exit (bus, FALSE); + while (ibus_bus_is_connected (bus)) { + g_main_context_iteration (NULL, TRUE); + } + } + g_object_unref (bus); + bus = NULL; + + /* create ibus server */ server = bus_server_get_default (); bus_server_listen (server); diff --git a/src/ibusbus.c b/src/ibusbus.c index 9965761..a567359 100644 --- a/src/ibusbus.c +++ b/src/ibusbus.c @@ -639,15 +639,20 @@ ibus_bus_exit (IBusBus *bus, { g_assert (IBUS_IS_BUS (bus)); + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + gboolean result; result = ibus_bus_call (bus, IBUS_SERVICE_IBUS, IBUS_PATH_IBUS, IBUS_INTERFACE_IBUS, - "Kill", + "Exit", G_TYPE_BOOLEAN, &restart, G_TYPE_INVALID, G_TYPE_INVALID); + ibus_connection_flush (priv->connection); + return result; } diff --git a/src/ibuscomponent.c b/src/ibuscomponent.c index 9ca487d..59690b8 100644 --- a/src/ibuscomponent.c +++ b/src/ibuscomponent.c @@ -679,7 +679,7 @@ ibus_component_start (IBusComponent *component) error = NULL; retval = g_spawn_async (NULL, argv, NULL, - G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, + G_SPAWN_DO_NOT_REAP_CHILD /* | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL */, NULL, NULL, &(component->pid), &error); g_strfreev (argv) diff --git a/ui/gtk/menu.py b/ui/gtk/menu.py index 9a3b30a..6f6c7d1 100644 --- a/ui/gtk/menu.py +++ b/ui/gtk/menu.py @@ -92,7 +92,7 @@ class ImageMenuItem (gtk.ImageMenuItem, PropItem): } def __init__ (self, prop): - gtk.ImageMenuItem.__init__ (self, label = prop.label) + gtk.ImageMenuItem.__init__ (self, label = prop.label.text) PropItem.__init__ (self, prop) if self._prop.icon: @@ -128,7 +128,7 @@ class CheckMenuItem (gtk.CheckMenuItem, PropItem): } def __init__ (self, prop): - gtk.CheckMenuItem.__init__ (self, label = prop.label) + gtk.CheckMenuItem.__init__ (self, label = prop.label.text) PropItem.__init__ (self, prop) self.set_active (self._prop._state == ibus.PROP_STATE_CHECKED) diff --git a/ui/gtk/panel.py b/ui/gtk/panel.py index e7850e6..d3cd249 100644 --- a/ui/gtk/panel.py +++ b/ui/gtk/panel.py @@ -74,9 +74,7 @@ class Panel(ibus.PanelBase): # add icon search path icon_theme = gtk.icon_theme_get_default() - dir = path.dirname(__file__) - icondir = path.join(dir, "..", "icons") - icon_theme.prepend_search_path(icondir) + icon_theme.prepend_search_path(self.__icons_dir) self.__language_bar = LanguageBar() self.__language_bar.connect("property-activate", diff --git a/ui/gtk/toolitem.py b/ui/gtk/toolitem.py index 0e4e4ad..09ad686 100644 --- a/ui/gtk/toolitem.py +++ b/ui/gtk/toolitem.py @@ -46,7 +46,7 @@ class ToolButton(gtk.ToolButton, PropItem): widget = icon.IconWidget(icon_name, 18) gtk.ToolButton.set_icon_widget(self, widget) self.set_is_important(False) - elif self._prop.label: + elif self._prop.label.text: gtk.ToolButton.set_icon_widget(self, None) self.set_is_important(True) else: