From 85d6a6d5d7e5673ac3bbc285589da18c48b562ae Mon Sep 17 00:00:00 2001 From: fujiwarat Date: Sun, 14 Aug 2011 08:44:35 +0900 Subject: [PATCH] Add create-engine signal in IBusFactory for non-C applications. --- bus/inputcontext.c | 5 ++ src/ibusfactory.c | 107 ++++++++++++++++++++++++++++++++++++++++------- src/ibusfactory.h | 7 +++- src/ibusmarshalers.list | 1 + src/ibusservice.h | 5 +- 5 files changed, 105 insertions(+), 20 deletions(-) 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..f28f074 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, @@ -95,6 +99,47 @@ static const gchar introspection_xml[] = " " ""; +static IBusEngine * +_ibus_factory_create_engine (IBusFactory *factory, + const gchar *engine_name) +{ + GType engine_type; + gchar *object_path = NULL; + IBusEngine *engine = NULL; + + engine_type = (GType) g_hash_table_lookup (factory->priv->engine_table, + engine_name); + + g_return_val_if_fail (engine_type != G_TYPE_INVALID, 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)); + g_free (object_path); + + return engine; +} + +static gboolean +_ibus_factory_create_engine_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy) +{ + gboolean retval = TRUE; + GObject *object = g_value_get_object (handler_return); + + if (object != NULL) { + g_value_copy (handler_return, return_accu); + retval = FALSE; + } + + return retval; +} + static void ibus_factory_class_init (IBusFactoryClass *class) { @@ -109,10 +154,34 @@ ibus_factory_class_init (IBusFactoryClass *class) IBUS_SERVICE_CLASS (class)->service_method_call = ibus_factory_service_method_call; IBUS_SERVICE_CLASS (class)->service_get_property = ibus_factory_service_get_property; IBUS_SERVICE_CLASS (class)->service_set_property = ibus_factory_service_set_property; + class->create_engine = _ibus_factory_create_engine; ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml); g_type_class_add_private (class, sizeof (IBusFactoryPrivate)); + + /** + * IBusFactory::create-engine: + * @factory: the factory which received the signal + * @engine_name: the engine_name which received the signal + * @returns: (transfer none): An IBusEngine + * + * The ::create-engine signal is a signal to create IBusEngine + * with @engine_name, which gets emitted when IBusFactory + * received CreateEngine dbus method. The callback functions + * will be called until a callback returns a non-null object + * of IBusEngine. */ + 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), + _ibus_factory_create_engine_accumulator, + NULL, + _ibus_marshal_OBJECT__STRING, + IBUS_TYPE_ENGINE, + 1, + G_TYPE_STRING); } static void @@ -190,25 +259,23 @@ ibus_factory_service_method_call (IBusService *service, if (g_strcmp0 (method_name, "CreateEngine") == 0) { gchar *engine_name = NULL; + IBusEngine *engine = NULL; + g_variant_get (parameters, "(&s)", &engine_name); - GType engine_type = (GType )g_hash_table_lookup (factory->priv->engine_table, engine_name); + g_signal_emit (factory, factory_signals[CREATE_ENGINE], + 0, engine_name, &engine); + + if (engine != NULL) { + gchar *object_path = NULL; + 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); - if (engine_type == G_TYPE_INVALID) { - gchar *error_message = g_strdup_printf ("Can not fond engine %s", engine_name); - g_dbus_method_invocation_return_error (invocation, - G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - 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)); 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, @@ -219,6 +286,14 @@ ibus_factory_service_method_call (IBusService *service, g_variant_new ("(o)", object_path)); g_free (object_path); } + else { + gchar *error_message = g_strdup_printf ("Can not fond engine %s", engine_name); + g_dbus_method_invocation_return_error (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + error_message); + g_free (error_message); + } return; } 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