Add Ctrl+space customization.
[platform/upstream/ibus.git] / src / ibusfactory.c
1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 /* vim:set et sts=4: */
3 /* ibus - The Input Bus
4  * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
5  * Copyright (C) 2008-2010 Red Hat, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22 #include "ibusfactory.h"
23 #include "ibusengine.h"
24 #include "ibusmarshalers.h"
25 #include "ibusshare.h"
26 #include "ibusinternal.h"
27
28 #define IBUS_FACTORY_GET_PRIVATE(o)  \
29    (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_FACTORY, IBusFactoryPrivate))
30
31 enum {
32     CREATE_ENGINE,
33     LAST_SIGNAL,
34 };
35
36 enum {
37     PROP_0,
38 };
39
40 /* IBusFactoryPriv */
41 struct _IBusFactoryPrivate {
42     guint id;
43     GList          *engine_list;
44     GHashTable     *engine_table;
45 };
46
47 static guint            factory_signals[LAST_SIGNAL] = { 0 };
48
49 /* functions prototype */
50 static void      ibus_factory_destroy        (IBusFactory        *factory);
51 static void      ibus_factory_set_property   (IBusFactory        *engine,
52                                               guint               prop_id,
53                                               const GValue       *value,
54                                               GParamSpec         *pspec);
55 static void      ibus_factory_get_property   (IBusFactory        *factory,
56                                               guint               prop_id,
57                                               GValue             *value,
58                                               GParamSpec         *pspec);
59 static void      ibus_factory_service_method_call
60                                               (IBusService        *service,
61                                                GDBusConnection    *connection,
62                                                const gchar        *sender,
63                                                const gchar        *object_path,
64                                                const gchar        *interface_name,
65                                                const gchar        *method_name,
66                                                GVariant           *parameters,
67                                                GDBusMethodInvocation
68                                                                   *invocation);
69 static GVariant *ibus_factory_service_get_property
70                                              (IBusService        *service,
71                                               GDBusConnection    *connection,
72                                               const gchar        *sender,
73                                               const gchar        *object_path,
74                                               const gchar        *interface_name,
75                                               const gchar        *property_name,
76                                               GError            **error);
77 static gboolean  ibus_factory_service_set_property
78                                              (IBusService        *service,
79                                               GDBusConnection    *connection,
80                                               const gchar        *sender,
81                                               const gchar        *object_path,
82                                               const gchar        *interface_name,
83                                               const gchar        *property_name,
84                                               GVariant           *value,
85                                               GError            **error);
86 static void      ibus_factory_engine_destroy_cb
87                                              (IBusEngine         *engine,
88                                               IBusFactory        *factory);
89
90 G_DEFINE_TYPE (IBusFactory, ibus_factory, IBUS_TYPE_SERVICE)
91
92 static const gchar introspection_xml[] =
93     "<node>"
94     "  <interface name='org.freedesktop.IBus.Factory'>"
95     "    <method name='CreateEngine'>"
96     "      <arg direction='in'  type='s' name='name' />"
97     "      <arg direction='out' type='o' />"
98     "    </method>"
99     "  </interface>"
100     "</node>";
101
102 static IBusEngine *
103 ibus_factory_real_create_engine (IBusFactory    *factory,
104                                  const gchar    *engine_name)
105 {
106     GType engine_type;
107     gchar *object_path = NULL;
108     IBusEngine *engine = NULL;
109
110     engine_type = (GType) g_hash_table_lookup (factory->priv->engine_table,
111                                                engine_name);
112
113     g_return_val_if_fail (engine_type != G_TYPE_INVALID, NULL);
114
115     object_path = g_strdup_printf ("/org/freedesktop/IBus/Engine/%d",
116                                    ++factory->priv->id);
117     engine = ibus_engine_new_with_type (engine_type,
118                                         engine_name,
119                                         object_path,
120                                         ibus_service_get_connection ((IBusService *)factory));
121     g_free (object_path);
122
123     return engine;
124 }
125
126 static gboolean
127 _ibus_factory_create_engine_accumulator (GSignalInvocationHint *ihint,
128                                          GValue                *return_accu,
129                                          const GValue          *handler_return,
130                                          gpointer               dummy)
131 {
132     gboolean retval = TRUE;
133     GObject *object = g_value_get_object (handler_return);
134
135     if (object != NULL) {
136         g_value_copy (handler_return, return_accu);
137         retval = FALSE;
138     }
139
140     return retval;
141 }
142
143 static void
144 ibus_factory_class_init (IBusFactoryClass *class)
145 {
146     GObjectClass *gobject_class = G_OBJECT_CLASS (class);
147     IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (class);
148
149     gobject_class->set_property = (GObjectSetPropertyFunc) ibus_factory_set_property;
150     gobject_class->get_property = (GObjectGetPropertyFunc) ibus_factory_get_property;
151
152     ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_factory_destroy;
153
154     IBUS_SERVICE_CLASS (class)->service_method_call  = ibus_factory_service_method_call;
155     IBUS_SERVICE_CLASS (class)->service_get_property = ibus_factory_service_get_property;
156     IBUS_SERVICE_CLASS (class)->service_set_property = ibus_factory_service_set_property;
157     class->create_engine = ibus_factory_real_create_engine;
158
159     ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml);
160
161     g_type_class_add_private (class, sizeof (IBusFactoryPrivate));
162
163     /**
164      * IBusFactory::create-engine:
165      * @factory: the factory which received the signal
166      * @engine_name: the engine_name which received the signal
167      * @returns: (transfer full): An IBusEngine
168      *
169      * The ::create-engine signal is a signal to create IBusEngine
170      * with @engine_name, which gets emitted when IBusFactory
171      * received CreateEngine dbus method. The callback functions
172      * will be called until a callback returns a non-null object
173      * of IBusEngine.
174      */
175     factory_signals[CREATE_ENGINE] =
176         g_signal_new (I_("create-engine"),
177             G_TYPE_FROM_CLASS (gobject_class),
178             G_SIGNAL_RUN_LAST,
179             G_STRUCT_OFFSET (IBusFactoryClass, create_engine),
180             _ibus_factory_create_engine_accumulator,
181             NULL,
182             _ibus_marshal_OBJECT__STRING,
183             IBUS_TYPE_ENGINE,
184             1,
185             G_TYPE_STRING);
186 }
187
188 static void
189 ibus_factory_init (IBusFactory *factory)
190 {
191     factory->priv = IBUS_FACTORY_GET_PRIVATE (factory);
192     factory->priv->engine_table =
193         g_hash_table_new_full (g_str_hash,
194                                g_str_equal,
195                                g_free,
196                                NULL);
197 }
198
199 static void
200 ibus_factory_destroy (IBusFactory *factory)
201 {
202     GList *list;
203
204     list = g_list_copy (factory->priv->engine_list);
205     g_list_free_full (list, (GDestroyNotify)ibus_object_destroy);
206     g_list_free(factory->priv->engine_list);
207     factory->priv->engine_list = NULL;
208
209     if (factory->priv->engine_table) {
210         g_hash_table_destroy (factory->priv->engine_table);
211     }
212
213     IBUS_OBJECT_CLASS(ibus_factory_parent_class)->destroy (IBUS_OBJECT (factory));
214 }
215
216 static void
217 ibus_factory_set_property (IBusFactory  *factory,
218                            guint         prop_id,
219                            const GValue *value,
220                            GParamSpec   *pspec)
221 {
222     switch (prop_id) {
223     default:
224         G_OBJECT_WARN_INVALID_PROPERTY_ID (factory, prop_id, pspec);
225     }
226 }
227
228 static void
229 ibus_factory_get_property (IBusFactory *factory,
230                            guint        prop_id,
231                            GValue      *value,
232                            GParamSpec  *pspec)
233 {
234     switch (prop_id) {
235     default:
236         G_OBJECT_WARN_INVALID_PROPERTY_ID (factory, prop_id, pspec);
237     }
238 }
239
240 static void
241 ibus_factory_engine_destroy_cb (IBusEngine  *engine,
242                                 IBusFactory *factory)
243 {
244     factory->priv->engine_list = g_list_remove (factory->priv->engine_list, engine);
245     g_object_unref (engine);
246 }
247
248 static void
249 ibus_factory_service_method_call (IBusService           *service,
250                                   GDBusConnection       *connection,
251                                   const gchar           *sender,
252                                   const gchar           *object_path,
253                                   const gchar           *interface_name,
254                                   const gchar           *method_name,
255                                   GVariant              *parameters,
256                                   GDBusMethodInvocation *invocation)
257 {
258     IBusFactory *factory = IBUS_FACTORY (service);
259
260     if (g_strcmp0 (method_name, "CreateEngine") == 0) {
261         gchar *engine_name = NULL;
262         IBusEngine *engine = NULL;
263
264         g_variant_get (parameters, "(&s)", &engine_name);
265         g_signal_emit (factory, factory_signals[CREATE_ENGINE],
266                        0, engine_name, &engine);
267
268         if (engine != NULL) {
269             gchar *object_path = NULL;
270             GValue value = { 0, };
271
272             g_value_init (&value, G_TYPE_STRING);
273             g_object_get_property (G_OBJECT (engine), "object-path", &value);
274             object_path = g_value_dup_string (&value);
275             g_value_unset (&value);
276
277             g_assert (engine != NULL);
278             g_assert (object_path != NULL);
279             g_object_ref_sink (engine);
280             factory->priv->engine_list = g_list_append (factory->priv->engine_list, engine);
281             g_signal_connect (engine,
282                               "destroy",
283                               G_CALLBACK (ibus_factory_engine_destroy_cb),
284                               factory);
285             g_dbus_method_invocation_return_value (invocation,
286                                                    g_variant_new ("(o)", object_path));
287             g_free (object_path);
288         }
289         else {
290             gchar *error_message = g_strdup_printf ("Can not fond engine %s", engine_name);
291             g_dbus_method_invocation_return_error (invocation,
292                                                    G_DBUS_ERROR,
293                                                    G_DBUS_ERROR_FAILED,
294                                                    error_message);
295             g_free (error_message);
296         }
297         return;
298     }
299
300     IBUS_SERVICE_CLASS (ibus_factory_parent_class)->
301             service_method_call (service,
302                                  connection,
303                                  sender,
304                                  object_path,
305                                  interface_name,
306                                  method_name,
307                                  parameters,
308                                  invocation);
309 }
310
311 static GVariant *
312 ibus_factory_service_get_property (IBusService        *service,
313                                    GDBusConnection    *connection,
314                                    const gchar        *sender,
315                                    const gchar        *object_path,
316                                    const gchar        *interface_name,
317                                    const gchar        *property_name,
318                                    GError            **error)
319 {
320     return IBUS_SERVICE_CLASS (ibus_factory_parent_class)->
321                 service_get_property (service,
322                                       connection,
323                                       sender,
324                                       object_path,
325                                       interface_name,
326                                       property_name,
327                                       error);
328 }
329
330 static gboolean
331 ibus_factory_service_set_property (IBusService        *service,
332                                    GDBusConnection    *connection,
333                                    const gchar        *sender,
334                                    const gchar        *object_path,
335                                    const gchar        *interface_name,
336                                    const gchar        *property_name,
337                                    GVariant           *value,
338                                    GError            **error)
339 {
340     return IBUS_SERVICE_CLASS (ibus_factory_parent_class)->
341                 service_set_property (service,
342                                       connection,
343                                       sender,
344                                       object_path,
345                                       interface_name,
346                                       property_name,
347                                       value,
348                                       error);
349 }
350
351 IBusFactory *
352 ibus_factory_new (GDBusConnection *connection)
353 {
354     g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
355
356     IBusFactory *object = g_object_new (IBUS_TYPE_FACTORY,
357                                         "object-path", IBUS_PATH_FACTORY,
358                                         "connection", connection,
359                                         NULL);
360
361     return IBUS_FACTORY (object);
362 }
363
364 void
365 ibus_factory_add_engine (IBusFactory *factory,
366                          const gchar *engine_name,
367                          GType        engine_type)
368 {
369     g_return_if_fail (IBUS_IS_FACTORY (factory));
370     g_return_if_fail (engine_name != NULL);
371     g_return_if_fail (g_type_is_a (engine_type, IBUS_TYPE_ENGINE));
372
373     g_hash_table_insert (factory->priv->engine_table, g_strdup (engine_name), (gpointer) engine_type);
374 }
375
376 IBusEngine *
377 ibus_factory_create_engine (IBusFactory    *factory,
378                             const gchar    *engine_name)
379 {
380     IBusEngine *engine = NULL;
381
382     g_assert (engine_name != NULL);
383
384     g_signal_emit (factory, factory_signals[CREATE_ENGINE],
385                    0, engine_name, &engine);
386
387     return engine;
388 }