Launch the second ibus engine too to reduce the launching time.
authorfujiwarat <takao.fujiwara1@gmail.com>
Fri, 8 Mar 2013 02:21:25 +0000 (11:21 +0900)
committerfujiwarat <takao.fujiwara1@gmail.com>
Fri, 8 Mar 2013 02:21:25 +0000 (11:21 +0900)
Currently the first ibus engine only is running but the second engine
is also frequently used. It is good to run the second engine before
user types Ctrl+space.

BUG=RH#838734
TEST=src/tests/ibus-bus

Review URL: https://codereview.appspot.com/7433049

bus/ibusimpl.c
src/ibusbus.c
src/ibusbus.h
src/tests/ibus-bus.c
ui/gtk3/panel.vala

index cafb34a..6218578 100644 (file)
@@ -176,6 +176,9 @@ static const gchar introspection_xml[] =
     "    <method name='IsGlobalEngineEnabled'>\n"
     "      <arg direction='out' type='b' name='enabled' />\n"
     "    </method>\n"
+    "    <method name='PreloadEngines'>\n"
+    "      <arg direction='in' type='as' name='names' />\n"
+    "    </method>\n"
     "    <signal name='RegistryChanged'>\n"
     "    </signal>\n"
     "    <signal name='GlobalEngineChanged'>\n"
@@ -1211,6 +1214,70 @@ _ibus_is_global_engine_enabled (BusIBusImpl           *ibus,
 }
 
 /**
+ * _ibus_preload_engines:
+ *
+ * Implement the "PreloadEngines" method call of the
+ * org.freedesktop.IBus interface.
+ */
+static void
+_ibus_preload_engines (BusIBusImpl           *ibus,
+                       GVariant              *parameters,
+                       GDBusMethodInvocation *invocation)
+{
+    int i, j;
+    const gchar **names = NULL;
+    IBusEngineDesc *desc = NULL;
+    BusComponent *component = NULL;
+    BusFactoryProxy *factory = NULL;
+    GPtrArray *array = g_ptr_array_new ();
+
+    g_variant_get (parameters, "(^a&s)", &names);
+
+    for (i = 0; names[i] != NULL; i++) {
+        gboolean has_component = FALSE;
+
+        desc = bus_ibus_impl_get_engine_desc(ibus, names[i]);
+
+        if (desc == NULL) {
+            g_dbus_method_invocation_return_error (invocation,
+                                                   G_DBUS_ERROR,
+                                                   G_DBUS_ERROR_FAILED,
+                                                   "Can not find engine %s.",
+                                                   names[i]);
+            g_ptr_array_free (array, FALSE);
+            return;
+        }
+
+        component = bus_component_from_engine_desc (desc);
+        factory = bus_component_get_factory (component);
+
+        if (factory != NULL) {
+            continue;
+        }
+
+        for (j = 0; j < array->len; j++) {
+            if (component == (BusComponent *) g_ptr_array_index (array, j)) {
+                has_component = TRUE;
+                break;
+            }
+        }
+
+        if (!has_component) {
+            g_ptr_array_add (array, component);
+        }
+    }
+
+    for (j = 0; j < array->len; j++) {
+        bus_component_start ((BusComponent *) g_ptr_array_index (array, j),
+                             g_verbose);
+    }
+
+    g_ptr_array_free (array, FALSE);
+
+    g_dbus_method_invocation_return_value (invocation, NULL);
+}
+
+/**
  * bus_ibus_impl_service_method_call:
  *
  * Handle a D-Bus method call whose destination and interface name are both "org.freedesktop.IBus"
@@ -1252,6 +1319,7 @@ bus_ibus_impl_service_method_call (IBusService           *service,
         { "GetGlobalEngine",       _ibus_get_global_engine },
         { "SetGlobalEngine",       _ibus_set_global_engine },
         { "IsGlobalEngineEnabled", _ibus_is_global_engine_enabled },
+        { "PreloadEngines",        _ibus_preload_engines },
     };
 
     gint i;
index 9118020..66a8486 100644 (file)
@@ -2006,6 +2006,68 @@ ibus_bus_set_global_engine_async_finish (IBusBus      *bus,
     return _async_finish_void (res, error);
 }
 
+gboolean
+ibus_bus_preload_engines (IBusBus             *bus,
+                          const gchar * const *names)
+{
+    GVariant *result;
+
+    g_return_val_if_fail (IBUS_IS_BUS (bus), FALSE);
+    g_return_val_if_fail (names != NULL && names[0] != NULL, FALSE);
+
+    result = ibus_bus_call_sync (bus,
+                                 IBUS_SERVICE_IBUS,
+                                 IBUS_PATH_IBUS,
+                                 IBUS_INTERFACE_IBUS,
+                                 "PreloadEngines",
+                                 g_variant_new("(^as)", names),
+                                 NULL);
+
+    if (result) {
+        g_variant_unref (result);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+void
+ibus_bus_preload_engines_async (IBusBus             *bus,
+                                const gchar * const *names,
+                                gint                 timeout_msec,
+                                GCancellable        *cancellable,
+                                GAsyncReadyCallback  callback,
+                                gpointer             user_data)
+{
+    g_return_if_fail (IBUS_IS_BUS (bus));
+    g_return_if_fail (names != NULL && names[0] != NULL);
+
+    ibus_bus_call_async (bus,
+                         IBUS_SERVICE_IBUS,
+                         IBUS_PATH_IBUS,
+                         IBUS_INTERFACE_IBUS,
+                         "PreloadEngines",
+                         g_variant_new("(^as)", names),
+                         NULL, /* no return value */
+                         ibus_bus_preload_engines_async,
+                         timeout_msec,
+                         cancellable,
+                         callback,
+                         user_data);
+}
+
+gboolean
+ibus_bus_preload_engines_async_finish (IBusBus       *bus,
+                                       GAsyncResult  *res,
+                                       GError       **error)
+{
+    g_assert (IBUS_IS_BUS (bus));
+    g_assert (g_simple_async_result_is_valid (
+            res, (GObject *) bus,
+            ibus_bus_preload_engines_async));
+    return _async_finish_void (res, error);
+}
+
 static GVariant *
 ibus_bus_call_sync (IBusBus            *bus,
                     const gchar        *bus_name,
index 7673365..1288317 100644 (file)
@@ -995,5 +995,53 @@ void         ibus_bus_set_watch_ibus_signal
  */
 IBusConfig  *ibus_bus_get_config        (IBusBus        *bus);
 
+/**
+ * ibus_bus_preload_engines:
+ * @bus: An #IBusBus.
+ * @names: (array zero-terminated=1): A %NULL-terminated array of engine names.
+ * @returns: %TRUE if components start. %FALSE otherwise.
+ *
+ * Start bus components by engine names synchronously.
+ */
+gboolean     ibus_bus_preload_engines   (IBusBus        *bus,
+                                         const gchar * const *names);
+
+/**
+ * ibus_bus_preload_engines_async:
+ * @bus: An #IBusBus.
+ * @names: (array zero-terminated=1): A %NULL-terminated array of engine names.
+ * @timeout_msec: The timeout in milliseconds or -1 to use the default timeout.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied
+ *      or %NULL if you don't care about the result of the method invocation.
+ * @user_data: The data to pass to callback.
+ *
+ * Start bus components by engine names asynchronously.
+ */
+void         ibus_bus_preload_engines_async
+                                        (IBusBus        *bus,
+                                         const gchar * const
+                                                        *names,
+                                         gint            timeout_msec,
+                                         GCancellable   *cancellable,
+                                         GAsyncReadyCallback
+                                                         callback,
+                                         gpointer        user_data);
+
+/**
+ * ibus_bus_preload_engines_async_finish:
+ * @bus: An #IBusBus.
+ * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to
+ *   ibus_bus_preload_engines_async().
+ * @error: Return location for error or %NULL.
+ * @returns: %TRUE if component starts. %FALSE otherwise.
+ *
+ * Finishes an operation started with ibus_bus_preload_engines_async().
+ */
+gboolean     ibus_bus_preload_engines_async_finish
+                                        (IBusBus        *bus,
+                                         GAsyncResult   *res,
+                                         GError        **error);
+
 G_END_DECLS
 #endif
index da12534..c0d4a10 100644 (file)
@@ -498,6 +498,31 @@ start_set_global_engine_async (void)
 }
 
 static void
+finish_preload_engines_async (GObject      *source_object,
+                              GAsyncResult *res,
+                              gpointer      user_data)
+{
+    GError *error = NULL;
+    ibus_bus_preload_engines_async_finish (bus, res, &error);
+    g_debug ("ibus_bus_preload_engines_async_finish: OK");
+    call_next_async_function ();
+}
+
+static void
+start_preload_engines_async (void)
+{
+    const gchar *preload_engines[] = { "xkb:us::eng", NULL };
+
+    ibus_bus_preload_engines_async (
+            bus,
+            preload_engines,
+            -1, /* timeout */
+            NULL, /* cancellable */
+            finish_preload_engines_async,
+            NULL); /* user_data */
+}
+
+static void
 finish_exit_async (GObject *source_object,
                    GAsyncResult *res,
                    gpointer user_data)
@@ -593,6 +618,7 @@ call_next_async_function (void)
         start_is_global_engine_enabled_async,
         start_set_global_engine_async,
         start_get_global_engine_async,
+        start_preload_engines_async,
         start_exit_async,
     };
     static guint index = 0;
index 18ef5c0..0d7a5b2 100644 (file)
@@ -443,6 +443,17 @@ class Panel : IBus.PanelService {
         }
     }
 
+    private void run_preload_engines(IBus.EngineDesc[] engines, int index) {
+        string[] names = {};
+
+        if (engines.length <= index) {
+            return;
+        }
+
+        names += engines[index].get_name();
+        m_bus.preload_engines_async(names, -1, null);
+    }
+
     private void update_engines(GLib.Variant? var_engines,
                                 GLib.Variant? var_order) {
         string[] engine_names = null;
@@ -473,6 +484,7 @@ class Panel : IBus.PanelService {
         if (m_engines.length == 0) {
             m_engines = engines;
             switch_engine(0, true);
+            run_preload_engines(engines, 1);
         } else {
             var current_engine = m_engines[0];
             m_engines = engines;
@@ -480,10 +492,16 @@ class Panel : IBus.PanelService {
             for (i = 0; i < m_engines.length; i++) {
                 if (current_engine.get_name() == engines[i].get_name()) {
                     switch_engine(i);
+                    if (i != 0) {
+                        run_preload_engines(engines, 0);
+                    } else {
+                        run_preload_engines(engines, 1);
+                    }
                     return;
                 }
             }
             switch_engine(0, true);
+            run_preload_engines(engines, 1);
         }
 
     }