Blob Blame History Raw
From ff5db39a4651f4ecd3c2ba19dd315ed7b83662f4 Mon Sep 17 00:00:00 2001
From: fujiwarat <takao.fujiwara1@gmail.com>
Date: Fri, 5 Aug 2011 20:21:14 +0900
Subject: [PATCH] Add create-engine signal in IBusFactory for non-C
 applications.

---
 bus/ibusimpl.c          |    6 +++-
 bus/inputcontext.c      |    5 ++++
 src/ibusfactory.c       |   54 ++++++++++++++++++++++++++++++++++++++++-------
 src/ibusfactory.h       |    7 +++++-
 src/ibusmarshalers.list |    1 +
 src/ibusservice.h       |    5 +--
 6 files changed, 64 insertions(+), 14 deletions(-)

diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c
index 853465c..f13d8e0 100644
--- a/bus/ibusimpl.c
+++ b/bus/ibusimpl.c
@@ -1604,8 +1604,10 @@ _ibus_register_component (BusIBusImpl           *ibus,
                                                 g_object_ref_sink (buscomp));
     GList *engines = bus_component_get_engines (buscomp);
     g_list_foreach (engines, (GFunc) g_object_ref, NULL);
-    ibus->register_engine_list = g_list_concat (ibus->register_engine_list,
-                                               engines);
+    /* We always override the register_engine_list or need to prepare
+     * unregister_component() method so that both ibus gtk and gnome-shell
+     * can call register_component. */
+    ibus->register_engine_list = engines;
 
     g_signal_connect (buscomp, "destroy", G_CALLBACK (_component_destroy_cb), ibus);
 
diff --git a/bus/inputcontext.c b/bus/inputcontext.c
index 47ac9d5..4e8cdc5 100644
--- a/bus/inputcontext.c
+++ b/bus/inputcontext.c
@@ -2285,6 +2285,11 @@ new_engine_cb (GObject             *obj,
                                              "Opertation was cancelled");
         }
         else {
+            if (data->context->engine != NULL) {
+                /* Send a Disabled signal. */
+                bus_input_context_unset_engine (data->context);
+                bus_input_context_disable (data->context);
+            }
             bus_input_context_set_engine (data->context, engine);
             g_object_unref (engine);
             bus_input_context_enable (data->context);
diff --git a/src/ibusfactory.c b/src/ibusfactory.c
index 11d9a6d..f72f51e 100644
--- a/src/ibusfactory.c
+++ b/src/ibusfactory.c
@@ -21,6 +21,7 @@
  */
 #include "ibusfactory.h"
 #include "ibusengine.h"
+#include "ibusmarshalers.h"
 #include "ibusshare.h"
 #include "ibusinternal.h"
 
@@ -28,6 +29,7 @@
    (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_FACTORY, IBusFactoryPrivate))
 
 enum {
+    CREATE_ENGINE,
     LAST_SIGNAL,
 };
 
@@ -42,6 +44,8 @@ struct _IBusFactoryPrivate {
     GHashTable     *engine_table;
 };
 
+static guint            factory_signals[LAST_SIGNAL] = { 0 };
+
 /* functions prototype */
 static void      ibus_factory_destroy        (IBusFactory        *factory);
 static void      ibus_factory_set_property   (IBusFactory        *engine,
@@ -113,6 +117,17 @@ ibus_factory_class_init (IBusFactoryClass *class)
     ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml);
 
     g_type_class_add_private (class, sizeof (IBusFactoryPrivate));
+
+    factory_signals[CREATE_ENGINE] =
+        g_signal_new (I_("create-engine"),
+            G_TYPE_FROM_CLASS (gobject_class),
+            G_SIGNAL_RUN_LAST,
+            G_STRUCT_OFFSET (IBusFactoryClass, create_engine),
+            NULL, NULL,
+            _ibus_marshal_OBJECT__STRING,
+            IBUS_TYPE_ENGINE,
+            1,
+            G_TYPE_STRING);
 }
 
 static void
@@ -190,8 +205,20 @@ ibus_factory_service_method_call (IBusService           *service,
 
     if (g_strcmp0 (method_name, "CreateEngine") == 0) {
         gchar *engine_name = NULL;
+        GType engine_type;
+        IBusEngine *engine = NULL;
+
         g_variant_get (parameters, "(&s)", &engine_name);
-        GType engine_type = (GType )g_hash_table_lookup (factory->priv->engine_table, engine_name);
+        engine_type = (GType) g_hash_table_lookup (factory->priv->engine_table, engine_name);
+
+        if (engine_type == G_TYPE_INVALID) {
+            g_signal_emit (factory, factory_signals[CREATE_ENGINE],
+                           0, engine_name, &engine);
+
+            if (engine != NULL && IBUS_IS_ENGINE (engine)) {
+                engine_type = G_OBJECT_TYPE (engine);
+            }
+        }
 
         if (engine_type == G_TYPE_INVALID) {
             gchar *error_message = g_strdup_printf ("Can not fond engine %s", engine_name);
@@ -201,14 +228,25 @@ ibus_factory_service_method_call (IBusService           *service,
                                                    error_message);
             g_free (error_message);
         }
-        else {
-            gchar *object_path = g_strdup_printf ("/org/freedesktop/IBus/Engine/%d",
-                                            ++factory->priv->id);
-            IBusEngine *engine = ibus_engine_new_type (engine_type,
-                                                       engine_name,
-                                                       object_path,
-                                                       ibus_service_get_connection ((IBusService *)factory));
+        else  {
+            gchar *object_path = NULL;
+            if (engine == NULL) {
+                object_path = g_strdup_printf ("/org/freedesktop/IBus/Engine/%d",
+                                               ++factory->priv->id);
+                engine = ibus_engine_new_type (engine_type,
+                                               engine_name,
+                                               object_path,
+                                               ibus_service_get_connection ((IBusService *)factory));
+            } else {
+                GValue value = { 0, };
+                g_value_init (&value, G_TYPE_STRING);
+                g_object_get_property (G_OBJECT (engine), "object-path", &value);
+                object_path = g_value_dup_string (&value);
+                g_value_unset (&value);
+            }
+
             g_assert (engine != NULL);
+            g_assert (object_path != NULL);
             g_object_ref_sink (engine);
             factory->priv->engine_list = g_list_append (factory->priv->engine_list, engine);
             g_signal_connect (engine,
diff --git a/src/ibusfactory.h b/src/ibusfactory.h
index 47c06e0..03d1dea 100644
--- a/src/ibusfactory.h
+++ b/src/ibusfactory.h
@@ -42,6 +42,7 @@
 
 #include "ibusservice.h"
 #include "ibusserializable.h"
+#include "ibusengine.h"
 
 G_BEGIN_DECLS
 
@@ -127,10 +128,14 @@ struct _IBusFactoryClass {
     IBusServiceClass parent;
 
     /* signals */
+    IBusEngine *
+                (* create_engine)
+                                    (IBusFactory    *factory,
+                                     const gchar    *engine_name);
 
     /*< private >*/
     /* padding */
-    gpointer pdummy[8];
+    gpointer pdummy[7];
 };
 
 /**
diff --git a/src/ibusmarshalers.list b/src/ibusmarshalers.list
index c073c6e..82b4aea 100644
--- a/src/ibusmarshalers.list
+++ b/src/ibusmarshalers.list
@@ -23,3 +23,4 @@ VOID:STRING,STRING,VARIANT
 VOID:STRING,STRING,STRING
 VOID:UINT
 VOID:UINT,POINTER
+OBJECT:STRING
diff --git a/src/ibusservice.h b/src/ibusservice.h
index 7a3fea7..94f9bb7 100644
--- a/src/ibusservice.h
+++ b/src/ibusservice.h
@@ -135,9 +135,9 @@ IBusService     *ibus_service_new               (GDBusConnection    *connection,
 const gchar     *ibus_service_get_object_path   (IBusService        *service);
 
 /**
- * ibus_service_get_connections:
+ * ibus_service_get_connection:
  * @service: An IBusService.
- * @returns: (transfer all) (element-type GDBusConnection): A newly allocated list of connections.
+ * @returns: (transfer none): A #GDBusConnection of an #IBusService instance.
  *
  * Returns a connections.
  */
@@ -190,7 +190,6 @@ gboolean         ibus_service_emit_signal       (IBusService        *service,
  * ibus_service_class_add_interfaces:
  * @klass: An IBusServiceClass.
  * @xml_data: The introspection xml data.
- * @error: Error.
  *
  * Set the interface introspection information with the service class.
  */
-- 
1.7.5.4