Blame src/ibusfactory.c

Packit Service 1d8f1c
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
Packit Service 1d8f1c
/* vim:set et sts=4: */
Packit Service 1d8f1c
/* ibus - The Input Bus
Packit Service 1d8f1c
 * Copyright (C) 2008-2015 Peng Huang <shawn.p.huang@gmail.com>
Packit Service 1d8f1c
 * Copyright (C) 2008-2015 Red Hat, Inc.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * This library is free software; you can redistribute it and/or
Packit Service 1d8f1c
 * modify it under the terms of the GNU Lesser General Public
Packit Service 1d8f1c
 * License as published by the Free Software Foundation; either
Packit Service 1d8f1c
 * version 2.1 of the License, or (at your option) any later version.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * This library is distributed in the hope that it will be useful,
Packit Service 1d8f1c
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 1d8f1c
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 1d8f1c
 * Lesser General Public License for more details.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * You should have received a copy of the GNU Lesser General Public
Packit Service 1d8f1c
 * License along with this library; if not, write to the Free Software
Packit Service 1d8f1c
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
Packit Service 1d8f1c
 * USA
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
#include "ibusfactory.h"
Packit Service 1d8f1c
#include "ibusengine.h"
Packit Service 1d8f1c
#include "ibusmarshalers.h"
Packit Service 1d8f1c
#include "ibusshare.h"
Packit Service 1d8f1c
#include "ibusinternal.h"
Packit Service 1d8f1c
Packit Service 1d8f1c
#define IBUS_FACTORY_GET_PRIVATE(o)  \
Packit Service 1d8f1c
   (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_FACTORY, IBusFactoryPrivate))
Packit Service 1d8f1c
Packit Service 1d8f1c
enum {
Packit Service 1d8f1c
    CREATE_ENGINE,
Packit Service 1d8f1c
    LAST_SIGNAL,
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
enum {
Packit Service 1d8f1c
    PROP_0,
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
/* IBusFactoryPriv */
Packit Service 1d8f1c
struct _IBusFactoryPrivate {
Packit Service 1d8f1c
    guint id;
Packit Service 1d8f1c
    GList          *engine_list;
Packit Service 1d8f1c
    GHashTable     *engine_table;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
static guint            factory_signals[LAST_SIGNAL] = { 0 };
Packit Service 1d8f1c
Packit Service 1d8f1c
/* functions prototype */
Packit Service 1d8f1c
static void      ibus_factory_destroy        (IBusFactory        *factory);
Packit Service 1d8f1c
static void      ibus_factory_set_property   (IBusFactory        *engine,
Packit Service 1d8f1c
                                              guint               prop_id,
Packit Service 1d8f1c
                                              const GValue       *value,
Packit Service 1d8f1c
                                              GParamSpec         *pspec);
Packit Service 1d8f1c
static void      ibus_factory_get_property   (IBusFactory        *factory,
Packit Service 1d8f1c
                                              guint               prop_id,
Packit Service 1d8f1c
                                              GValue             *value,
Packit Service 1d8f1c
                                              GParamSpec         *pspec);
Packit Service 1d8f1c
static void      ibus_factory_service_method_call
Packit Service 1d8f1c
                                              (IBusService        *service,
Packit Service 1d8f1c
                                               GDBusConnection    *connection,
Packit Service 1d8f1c
                                               const gchar        *sender,
Packit Service 1d8f1c
                                               const gchar        *object_path,
Packit Service 1d8f1c
                                               const gchar        *interface_name,
Packit Service 1d8f1c
                                               const gchar        *method_name,
Packit Service 1d8f1c
                                               GVariant           *parameters,
Packit Service 1d8f1c
                                               GDBusMethodInvocation
Packit Service 1d8f1c
                                                                  *invocation);
Packit Service 1d8f1c
static GVariant *ibus_factory_service_get_property
Packit Service 1d8f1c
                                             (IBusService        *service,
Packit Service 1d8f1c
                                              GDBusConnection    *connection,
Packit Service 1d8f1c
                                              const gchar        *sender,
Packit Service 1d8f1c
                                              const gchar        *object_path,
Packit Service 1d8f1c
                                              const gchar        *interface_name,
Packit Service 1d8f1c
                                              const gchar        *property_name,
Packit Service 1d8f1c
                                              GError            **error);
Packit Service 1d8f1c
static gboolean  ibus_factory_service_set_property
Packit Service 1d8f1c
                                             (IBusService        *service,
Packit Service 1d8f1c
                                              GDBusConnection    *connection,
Packit Service 1d8f1c
                                              const gchar        *sender,
Packit Service 1d8f1c
                                              const gchar        *object_path,
Packit Service 1d8f1c
                                              const gchar        *interface_name,
Packit Service 1d8f1c
                                              const gchar        *property_name,
Packit Service 1d8f1c
                                              GVariant           *value,
Packit Service 1d8f1c
                                              GError            **error);
Packit Service 1d8f1c
static void      ibus_factory_engine_destroy_cb
Packit Service 1d8f1c
                                             (IBusEngine         *engine,
Packit Service 1d8f1c
                                              IBusFactory        *factory);
Packit Service 1d8f1c
Packit Service 1d8f1c
G_DEFINE_TYPE (IBusFactory, ibus_factory, IBUS_TYPE_SERVICE)
Packit Service 1d8f1c
Packit Service 1d8f1c
static const gchar introspection_xml[] =
Packit Service 1d8f1c
    "<node>"
Packit Service 1d8f1c
    "  <interface name='org.freedesktop.IBus.Factory'>"
Packit Service 1d8f1c
    "    <method name='CreateEngine'>"
Packit Service 1d8f1c
    "      <arg direction='in'  type='s' name='name' />"
Packit Service 1d8f1c
    "      <arg direction='out' type='o' />"
Packit Service 1d8f1c
    "    </method>"
Packit Service 1d8f1c
    "  </interface>"
Packit Service 1d8f1c
    "</node>";
Packit Service 1d8f1c
Packit Service 1d8f1c
static IBusEngine *
Packit Service 1d8f1c
ibus_factory_real_create_engine (IBusFactory    *factory,
Packit Service 1d8f1c
                                 const gchar    *engine_name)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GType engine_type;
Packit Service 1d8f1c
    gchar *object_path = NULL;
Packit Service 1d8f1c
    IBusEngine *engine = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    engine_type = (GType) g_hash_table_lookup (factory->priv->engine_table,
Packit Service 1d8f1c
                                               engine_name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_return_val_if_fail (engine_type != G_TYPE_INVALID, NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    object_path = g_strdup_printf ("/org/freedesktop/IBus/Engine/%d",
Packit Service 1d8f1c
                                   ++factory->priv->id);
Packit Service 1d8f1c
    engine = ibus_engine_new_with_type (engine_type,
Packit Service 1d8f1c
                                        engine_name,
Packit Service 1d8f1c
                                        object_path,
Packit Service 1d8f1c
                                        ibus_service_get_connection ((IBusService *)factory));
Packit Service 1d8f1c
    g_free (object_path);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return engine;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
_ibus_factory_create_engine_accumulator (GSignalInvocationHint *ihint,
Packit Service 1d8f1c
                                         GValue                *return_accu,
Packit Service 1d8f1c
                                         const GValue          *handler_return,
Packit Service 1d8f1c
                                         gpointer               dummy)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    gboolean retval = TRUE;
Packit Service 1d8f1c
    GObject *object = g_value_get_object (handler_return);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (object != NULL) {
Packit Service 1d8f1c
        g_value_copy (handler_return, return_accu);
Packit Service 1d8f1c
        retval = FALSE;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    return retval;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_factory_class_init (IBusFactoryClass *class)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GObjectClass *gobject_class = G_OBJECT_CLASS (class);
Packit Service 1d8f1c
    IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (class);
Packit Service 1d8f1c
Packit Service 1d8f1c
    gobject_class->set_property = (GObjectSetPropertyFunc) ibus_factory_set_property;
Packit Service 1d8f1c
    gobject_class->get_property = (GObjectGetPropertyFunc) ibus_factory_get_property;
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_factory_destroy;
Packit Service 1d8f1c
Packit Service 1d8f1c
    IBUS_SERVICE_CLASS (class)->service_method_call  = ibus_factory_service_method_call;
Packit Service 1d8f1c
    IBUS_SERVICE_CLASS (class)->service_get_property = ibus_factory_service_get_property;
Packit Service 1d8f1c
    IBUS_SERVICE_CLASS (class)->service_set_property = ibus_factory_service_set_property;
Packit Service 1d8f1c
    class->create_engine = ibus_factory_real_create_engine;
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_type_class_add_private (class, sizeof (IBusFactoryPrivate));
Packit Service 1d8f1c
Packit Service 1d8f1c
    /**
Packit Service 1d8f1c
     * IBusFactory::create-engine:
Packit Service 1d8f1c
     * @factory: the factory which received the signal
Packit Service 1d8f1c
     * @engine_name: the engine_name which received the signal
Packit Service 1d8f1c
     * @returns: (nullable) (transfer full): An IBusEngine
Packit Service 1d8f1c
     *
Packit Service 1d8f1c
     * The ::create-engine signal is a signal to create IBusEngine
Packit Service 1d8f1c
     * with @engine_name, which gets emitted when IBusFactory
Packit Service 1d8f1c
     * received CreateEngine dbus method. The callback functions
Packit Service 1d8f1c
     * will be called until a callback returns a non-null object
Packit Service 1d8f1c
     * of IBusEngine.
Packit Service 1d8f1c
     */
Packit Service 1d8f1c
    factory_signals[CREATE_ENGINE] =
Packit Service 1d8f1c
        g_signal_new (I_("create-engine"),
Packit Service 1d8f1c
            G_TYPE_FROM_CLASS (gobject_class),
Packit Service 1d8f1c
            G_SIGNAL_RUN_LAST,
Packit Service 1d8f1c
            G_STRUCT_OFFSET (IBusFactoryClass, create_engine),
Packit Service 1d8f1c
            _ibus_factory_create_engine_accumulator,
Packit Service 1d8f1c
            NULL,
Packit Service 1d8f1c
            _ibus_marshal_OBJECT__STRING,
Packit Service 1d8f1c
            IBUS_TYPE_ENGINE,
Packit Service 1d8f1c
            1,
Packit Service 1d8f1c
            G_TYPE_STRING);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_factory_init (IBusFactory *factory)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    factory->priv = IBUS_FACTORY_GET_PRIVATE (factory);
Packit Service 1d8f1c
    factory->priv->engine_table =
Packit Service 1d8f1c
        g_hash_table_new_full (g_str_hash,
Packit Service 1d8f1c
                               g_str_equal,
Packit Service 1d8f1c
                               g_free,
Packit Service 1d8f1c
                               NULL);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_factory_destroy (IBusFactory *factory)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GList *list;
Packit Service 1d8f1c
Packit Service 1d8f1c
    list = g_list_copy (factory->priv->engine_list);
Packit Service 1d8f1c
    g_list_free_full (list, (GDestroyNotify)ibus_object_destroy);
Packit Service 1d8f1c
    g_list_free(factory->priv->engine_list);
Packit Service 1d8f1c
    factory->priv->engine_list = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (factory->priv->engine_table) {
Packit Service 1d8f1c
        g_hash_table_destroy (factory->priv->engine_table);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    IBUS_OBJECT_CLASS(ibus_factory_parent_class)->destroy (IBUS_OBJECT (factory));
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_factory_set_property (IBusFactory  *factory,
Packit Service 1d8f1c
                           guint         prop_id,
Packit Service 1d8f1c
                           const GValue *value,
Packit Service 1d8f1c
                           GParamSpec   *pspec)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    switch (prop_id) {
Packit Service 1d8f1c
    default:
Packit Service 1d8f1c
        G_OBJECT_WARN_INVALID_PROPERTY_ID (factory, prop_id, pspec);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_factory_get_property (IBusFactory *factory,
Packit Service 1d8f1c
                           guint        prop_id,
Packit Service 1d8f1c
                           GValue      *value,
Packit Service 1d8f1c
                           GParamSpec  *pspec)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    switch (prop_id) {
Packit Service 1d8f1c
    default:
Packit Service 1d8f1c
        G_OBJECT_WARN_INVALID_PROPERTY_ID (factory, prop_id, pspec);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_factory_engine_destroy_cb (IBusEngine  *engine,
Packit Service 1d8f1c
                                IBusFactory *factory)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    factory->priv->engine_list = g_list_remove (factory->priv->engine_list, engine);
Packit Service 1d8f1c
    g_object_unref (engine);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_factory_service_method_call (IBusService           *service,
Packit Service 1d8f1c
                                  GDBusConnection       *connection,
Packit Service 1d8f1c
                                  const gchar           *sender,
Packit Service 1d8f1c
                                  const gchar           *object_path,
Packit Service 1d8f1c
                                  const gchar           *interface_name,
Packit Service 1d8f1c
                                  const gchar           *method_name,
Packit Service 1d8f1c
                                  GVariant              *parameters,
Packit Service 1d8f1c
                                  GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IBusFactory *factory = IBUS_FACTORY (service);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_strcmp0 (method_name, "CreateEngine") == 0) {
Packit Service 1d8f1c
        gchar *engine_name = NULL;
Packit Service 1d8f1c
        IBusEngine *engine = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
        g_variant_get (parameters, "(&s)", &engine_name);
Packit Service 1d8f1c
        g_signal_emit (factory, factory_signals[CREATE_ENGINE],
Packit Service 1d8f1c
                       0, engine_name, &engine);
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (engine != NULL) {
Packit Service 1d8f1c
            gchar *object_path = NULL;
Packit Service 1d8f1c
            GValue value = { 0, };
Packit Service 1d8f1c
Packit Service 1d8f1c
            g_value_init (&value, G_TYPE_STRING);
Packit Service 1d8f1c
            g_object_get_property (G_OBJECT (engine), "object-path", &value);
Packit Service 1d8f1c
            object_path = g_value_dup_string (&value);
Packit Service 1d8f1c
            g_value_unset (&value);
Packit Service 1d8f1c
Packit Service 1d8f1c
            g_assert (engine != NULL);
Packit Service 1d8f1c
            g_assert (object_path != NULL);
Packit Service 1d8f1c
            g_object_ref_sink (engine);
Packit Service 1d8f1c
            factory->priv->engine_list = g_list_append (factory->priv->engine_list, engine);
Packit Service 1d8f1c
            g_signal_connect (engine,
Packit Service 1d8f1c
                              "destroy",
Packit Service 1d8f1c
                              G_CALLBACK (ibus_factory_engine_destroy_cb),
Packit Service 1d8f1c
                              factory);
Packit Service 1d8f1c
            g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                                                   g_variant_new ("(o)", object_path));
Packit Service 1d8f1c
            g_free (object_path);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        else {
Packit Service 1d8f1c
            g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                                                   G_DBUS_ERROR,
Packit Service 1d8f1c
                                                   G_DBUS_ERROR_FAILED,
Packit Service 1d8f1c
                                                   "Cannot find engine %s",
Packit Service 1d8f1c
                                                   engine_name);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    IBUS_SERVICE_CLASS (ibus_factory_parent_class)->
Packit Service 1d8f1c
            service_method_call (service,
Packit Service 1d8f1c
                                 connection,
Packit Service 1d8f1c
                                 sender,
Packit Service 1d8f1c
                                 object_path,
Packit Service 1d8f1c
                                 interface_name,
Packit Service 1d8f1c
                                 method_name,
Packit Service 1d8f1c
                                 parameters,
Packit Service 1d8f1c
                                 invocation);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static GVariant *
Packit Service 1d8f1c
ibus_factory_service_get_property (IBusService        *service,
Packit Service 1d8f1c
                                   GDBusConnection    *connection,
Packit Service 1d8f1c
                                   const gchar        *sender,
Packit Service 1d8f1c
                                   const gchar        *object_path,
Packit Service 1d8f1c
                                   const gchar        *interface_name,
Packit Service 1d8f1c
                                   const gchar        *property_name,
Packit Service 1d8f1c
                                   GError            **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return IBUS_SERVICE_CLASS (ibus_factory_parent_class)->
Packit Service 1d8f1c
                service_get_property (service,
Packit Service 1d8f1c
                                      connection,
Packit Service 1d8f1c
                                      sender,
Packit Service 1d8f1c
                                      object_path,
Packit Service 1d8f1c
                                      interface_name,
Packit Service 1d8f1c
                                      property_name,
Packit Service 1d8f1c
                                      error);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_factory_service_set_property (IBusService        *service,
Packit Service 1d8f1c
                                   GDBusConnection    *connection,
Packit Service 1d8f1c
                                   const gchar        *sender,
Packit Service 1d8f1c
                                   const gchar        *object_path,
Packit Service 1d8f1c
                                   const gchar        *interface_name,
Packit Service 1d8f1c
                                   const gchar        *property_name,
Packit Service 1d8f1c
                                   GVariant           *value,
Packit Service 1d8f1c
                                   GError            **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return IBUS_SERVICE_CLASS (ibus_factory_parent_class)->
Packit Service 1d8f1c
                service_set_property (service,
Packit Service 1d8f1c
                                      connection,
Packit Service 1d8f1c
                                      sender,
Packit Service 1d8f1c
                                      object_path,
Packit Service 1d8f1c
                                      interface_name,
Packit Service 1d8f1c
                                      property_name,
Packit Service 1d8f1c
                                      value,
Packit Service 1d8f1c
                                      error);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
IBusFactory *
Packit Service 1d8f1c
ibus_factory_new (GDBusConnection *connection)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    IBusFactory *object = g_object_new (IBUS_TYPE_FACTORY,
Packit Service 1d8f1c
                                        "object-path", IBUS_PATH_FACTORY,
Packit Service 1d8f1c
                                        "connection", connection,
Packit Service 1d8f1c
                                        NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return IBUS_FACTORY (object);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
void
Packit Service 1d8f1c
ibus_factory_add_engine (IBusFactory *factory,
Packit Service 1d8f1c
                         const gchar *engine_name,
Packit Service 1d8f1c
                         GType        engine_type)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_if_fail (IBUS_IS_FACTORY (factory));
Packit Service 1d8f1c
    g_return_if_fail (engine_name != NULL);
Packit Service 1d8f1c
    g_return_if_fail (g_type_is_a (engine_type, IBUS_TYPE_ENGINE));
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_hash_table_insert (factory->priv->engine_table, g_strdup (engine_name), (gpointer) engine_type);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
IBusEngine *
Packit Service 1d8f1c
ibus_factory_create_engine (IBusFactory    *factory,
Packit Service 1d8f1c
                            const gchar    *engine_name)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IBusEngine *engine = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_assert (engine_name != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_emit (factory, factory_signals[CREATE_ENGINE],
Packit Service 1d8f1c
                   0, engine_name, &engine);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return engine;
Packit Service 1d8f1c
}