Use GInitiallyUnowned correctly
[platform/upstream/ibus.git] / src / ibusfactory.c
1 /* vim:set et sts=4: */
2 /* ibus - The Input Bus
3  * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
4  * Copyright (C) 2008-2010 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include "ibusfactory.h"
23 #include "ibusengine.h"
24 #include "ibusshare.h"
25 #include "ibusinternal.h"
26
27 #define IBUS_FACTORY_GET_PRIVATE(o)  \
28    (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_FACTORY, IBusFactoryPrivate))
29
30 enum {
31     LAST_SIGNAL,
32 };
33
34 /* IBusFactoryPriv */
35 struct _IBusFactoryPrivate {
36     guint id;
37     IBusConnection *connection;
38     GList          *engine_list;
39     GHashTable     *engine_table;
40 };
41 typedef struct _IBusFactoryPrivate IBusFactoryPrivate;
42
43 /* functions prototype */
44 static void     ibus_factory_class_init     (IBusFactoryClass   *klass);
45 static void     ibus_factory_init           (IBusFactory        *factory);
46 static void     ibus_factory_destroy        (IBusFactory        *factory);
47 static gboolean ibus_factory_ibus_message   (IBusFactory        *factory,
48                                              IBusConnection     *connection,
49                                              IBusMessage        *message);
50
51 static void     _engine_destroy_cb          (IBusEngine         *engine,
52                                              IBusFactory        *factory);
53
54 static IBusServiceClass *factory_parent_class = NULL;
55
56 GType
57 ibus_factory_get_type (void)
58 {
59     static GType type = 0;
60
61     static const GTypeInfo type_info = {
62         sizeof (IBusFactoryClass),
63         (GBaseInitFunc)     NULL,
64         (GBaseFinalizeFunc) NULL,
65         (GClassInitFunc)    ibus_factory_class_init,
66         NULL,               /* class finalize */
67         NULL,               /* class data */
68         sizeof (IBusFactory),
69         0,
70         (GInstanceInitFunc) ibus_factory_init,
71     };
72
73     if (type == 0) {
74         type = g_type_register_static (IBUS_TYPE_SERVICE,
75                     "IBusFactory",
76                     &type_info,
77                     (GTypeFlags) 0);
78     }
79     return type;
80 }
81
82 IBusFactory *
83 ibus_factory_new (IBusConnection *connection)
84 {
85     g_assert (IBUS_IS_CONNECTION (connection));
86
87     IBusFactory *factory;
88     IBusFactoryPrivate *priv;
89
90     factory = (IBusFactory *) g_object_new (IBUS_TYPE_FACTORY,
91                                             "path", IBUS_PATH_FACTORY,
92                                             NULL);
93     priv = IBUS_FACTORY_GET_PRIVATE (factory);
94
95     priv->connection = g_object_ref_sink (connection);
96     ibus_service_add_to_connection ((IBusService *)factory, connection);
97
98     return factory;
99 }
100
101 static void
102 ibus_factory_class_init (IBusFactoryClass *klass)
103 {
104     // GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
105     IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
106
107     factory_parent_class = (IBusServiceClass *) g_type_class_peek_parent (klass);
108
109     g_type_class_add_private (klass, sizeof (IBusFactoryPrivate));
110
111     ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_factory_destroy;
112
113     IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) ibus_factory_ibus_message;
114
115 }
116
117 static void
118 ibus_factory_init (IBusFactory *factory)
119 {
120     IBusFactoryPrivate *priv;
121     priv = IBUS_FACTORY_GET_PRIVATE (factory);
122
123     priv->id = 0;
124     priv->connection = NULL;
125     priv->engine_table = g_hash_table_new_full (g_str_hash,
126                                                 g_str_equal,
127                                                 g_free,
128                                                 NULL);
129     priv->engine_list =  NULL;
130 }
131
132 static void
133 ibus_factory_destroy (IBusFactory *factory)
134 {
135     GList *list;
136     IBusFactoryPrivate *priv;
137     priv = IBUS_FACTORY_GET_PRIVATE (factory);
138
139     list = g_list_copy (priv->engine_list);
140     g_list_foreach (list, (GFunc) ibus_object_destroy, NULL);
141     g_list_free (priv->engine_list);
142     g_list_free (list);
143     priv->engine_list = NULL;
144
145     if (priv->engine_table) {
146         g_hash_table_destroy (priv->engine_table);
147     }
148
149     if (priv->connection) {
150         ibus_service_remove_from_connection ((IBusService *)factory,
151                                              priv->connection);
152         g_object_unref (priv->connection);
153     }
154
155     IBUS_OBJECT_CLASS(factory_parent_class)->destroy (IBUS_OBJECT (factory));
156 }
157
158 static void
159 _engine_destroy_cb (IBusEngine  *engine,
160                     IBusFactory *factory)
161 {
162     IBusFactoryPrivate *priv;
163     priv = IBUS_FACTORY_GET_PRIVATE (factory);
164
165     priv->engine_list = g_list_remove (priv->engine_list, engine);
166     g_object_unref (engine);
167 }
168
169 static gboolean
170 ibus_factory_ibus_message (IBusFactory    *factory,
171                            IBusConnection *connection,
172                            IBusMessage    *message)
173 {
174     g_assert (IBUS_IS_FACTORY (factory));
175     g_assert (IBUS_IS_CONNECTION (connection));
176     g_assert (message != NULL);
177
178     IBusMessage *reply_message;
179     IBusFactoryPrivate *priv;
180     priv = IBUS_FACTORY_GET_PRIVATE (factory);
181
182     g_assert (priv->connection == connection);
183
184     if (ibus_message_is_method_call (message,
185                                      IBUS_INTERFACE_FACTORY,
186                                      "CreateEngine")) {
187         gchar *engine_name;
188         gchar *path;
189         IBusError *error;
190         IBusEngine *engine;
191         gboolean retval;
192         GType engine_type;
193
194         retval = ibus_message_get_args (message,
195                                         &error,
196                                         G_TYPE_STRING, &engine_name,
197                                         G_TYPE_INVALID);
198
199         if (!retval) {
200             reply_message = ibus_message_new_error_printf (message,
201                                         DBUS_ERROR_INVALID_ARGS,
202                                         "The 1st arg should be engine name");
203             ibus_connection_send (connection, reply_message);
204             ibus_message_unref (reply_message);
205             return TRUE;
206         }
207
208         engine_type = (GType )g_hash_table_lookup (priv->engine_table, engine_name);
209
210         if (engine_type == G_TYPE_INVALID) {
211              reply_message = ibus_message_new_error_printf (message,
212                                         DBUS_ERROR_FAILED,
213                                         "Can not create engine %s", engine_name);
214             ibus_connection_send (connection, reply_message);
215             ibus_message_unref (reply_message);
216             return TRUE;
217
218         }
219
220         path = g_strdup_printf ("/org/freedesktop/IBus/Engine/%d", ++priv->id);
221
222         engine = g_object_new (engine_type,
223                                "name", engine_name,
224                                "path", path,
225                                "connection", priv->connection,
226                                NULL);
227
228         priv->engine_list = g_list_append (priv->engine_list, engine);
229         g_signal_connect (engine,
230                           "destroy",
231                           G_CALLBACK (_engine_destroy_cb),
232                           factory);
233
234         reply_message = ibus_message_new_method_return (message);
235         ibus_message_append_args (reply_message,
236                                   IBUS_TYPE_OBJECT_PATH, &path,
237                                   G_TYPE_INVALID);
238         g_free (path);
239         ibus_connection_send (connection, reply_message);
240         ibus_message_unref (reply_message);
241         return TRUE;
242     }
243
244     return factory_parent_class->ibus_message ((IBusService *)factory,
245                                                connection,
246                                                message);
247 }
248
249 void
250 ibus_factory_add_engine (IBusFactory *factory,
251                          const gchar *engine_name,
252                          GType        engine_type)
253 {
254     g_assert (IBUS_IS_FACTORY (factory));
255     g_assert (engine_name);
256     g_assert (g_type_is_a (engine_type, IBUS_TYPE_ENGINE));
257
258     IBusFactoryPrivate *priv;
259     priv = IBUS_FACTORY_GET_PRIVATE (factory);
260
261     g_hash_table_insert (priv->engine_table, g_strdup (engine_name), (gpointer) engine_type);
262 }