~ubuntu-branches/ubuntu/quantal/ibus/quantal

« back to all changes in this revision

Viewing changes to bus/component.c

  • Committer: Bazaar Package Importer
  • Author(s): Barry Warsaw
  • Date: 2011-08-11 17:00:57 UTC
  • mfrom: (6.2.14 sid)
  • Revision ID: james.westby@ubuntu.com-20110811170057-6dmbfs4s3cchzl7x
Tags: 1.3.99.20110419-1ubuntu1
* Merge with Debian unstable.  Remaining Ubuntu changes:
  - Indicator support:
    + Add 05_appindicator.patch: Use an indicator rather than a notification
      icon.
    + debian/control: Recommend python-appindicator.
  - debian/control: Install im-switch instead of im-config by default.
  - debian/README.source: Removed, it was outdated and no longer correct
  - debian/patches/01_ubuntu_desktop: Fix "Desktop entry needs the
    X-Ubuntu-Gettext-Domain key"  (LP: #457632)
  - debian/patches/02_title_update.patch: Rename "IBus Preferences" to
    "Keyboard Input Methods"
  - debian/patches/06_locale_parser.patch: Cherry-picked from upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 
2
/* vim:set et sts=4: */
 
3
/* bus - The Input Bus
 
4
 * Copyright (C) 2010 Peng Huang <shawn.p.huang@gmail.com>
 
5
 * Copyright (C) 2010 Google 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 "component.h"
 
23
#include <glib/gstdio.h>
 
24
#include <gio/gio.h>
 
25
#include <stdlib.h>
 
26
#include <string.h>
 
27
#include "types.h"
 
28
#include "option.h"
 
29
#include "marshalers.h"
 
30
 
 
31
enum {
 
32
    LAST_SIGNAL,
 
33
};
 
34
 
 
35
enum {
 
36
    PROP_0 = 0,
 
37
    PROP_COMPONENT,
 
38
    PROP_FACTORY,
 
39
};
 
40
 
 
41
struct _BusComponent {
 
42
    IBusObject parent;
 
43
 
 
44
    /* instance members */
 
45
 
 
46
    /* an object which represents one XML file in the ibus/component/ directory. */
 
47
    IBusComponent *component;
 
48
    /* a proxy object which starts an engine. */
 
49
    BusFactoryProxy *factory;
 
50
 
 
51
    /* TRUE if the component started in the verbose mode. */
 
52
    gboolean verbose;
 
53
    /* TRUE if the component needs to be restarted when it dies. */
 
54
    gboolean restart;
 
55
    /* TRUE if the component will be destroyed with factory. */
 
56
    gboolean destroy_with_factory;
 
57
 
 
58
    /* process id of the process (e.g. ibus-config, ibus-engine-*, ..) of the component. */
 
59
    GPid     pid;
 
60
    guint    child_source_id;
 
61
};
 
62
 
 
63
struct _BusComponentClass {
 
64
    IBusObjectClass parent;
 
65
    /* class members */
 
66
};
 
67
 
 
68
/* functions prototype */
 
69
static GObject* bus_component_constructor   (GType                  type,
 
70
                                             guint                  n_construct_params,
 
71
                                             GObjectConstructParam *construct_params);
 
72
static void     bus_component_set_property  (BusComponent          *component,
 
73
                                             guint                  prop_id,
 
74
                                             const GValue          *value,
 
75
                                             GParamSpec            *pspec);
 
76
static void     bus_component_get_property  (BusComponent          *component,
 
77
                                             guint                  prop_id,
 
78
                                             GValue                *value,
 
79
                                             GParamSpec            *pspec);
 
80
static void     bus_component_destroy       (BusComponent          *component);
 
81
 
 
82
G_DEFINE_TYPE (BusComponent, bus_component, IBUS_TYPE_OBJECT)
 
83
 
 
84
static void
 
85
bus_component_class_init (BusComponentClass *class)
 
86
{
 
87
    GObjectClass *gobject_class = G_OBJECT_CLASS (class);
 
88
    IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (class);
 
89
 
 
90
    gobject_class->constructor  = bus_component_constructor;
 
91
    gobject_class->set_property = (GObjectSetPropertyFunc) bus_component_set_property;
 
92
    gobject_class->get_property = (GObjectGetPropertyFunc) bus_component_get_property;
 
93
    ibus_object_class->destroy  = (IBusObjectDestroyFunc) bus_component_destroy;
 
94
 
 
95
    /* install properties */
 
96
    g_object_class_install_property (gobject_class,
 
97
                    PROP_COMPONENT,
 
98
                    g_param_spec_object ("component", /* canonical name of the property */
 
99
                        "component", /* nick name */
 
100
                        "component", /* description */
 
101
                        IBUS_TYPE_COMPONENT, /* object type */
 
102
                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
103
 
 
104
    g_object_class_install_property (gobject_class,
 
105
                    PROP_FACTORY,
 
106
                    g_param_spec_object ("factory",
 
107
                        "factory",
 
108
                        "factory",
 
109
                        BUS_TYPE_FACTORY_PROXY,
 
110
                        G_PARAM_READWRITE));
 
111
}
 
112
 
 
113
static void
 
114
bus_component_init (BusComponent *component)
 
115
{
 
116
}
 
117
 
 
118
/**
 
119
 * bus_component_constructor:
 
120
 *
 
121
 * A constructor method which is called after bus_component_init is called.
 
122
 */
 
123
static GObject*
 
124
bus_component_constructor (GType                  type,
 
125
                           guint                  n_construct_params,
 
126
                           GObjectConstructParam *construct_params)
 
127
{
 
128
    GObject *object;
 
129
    object = G_OBJECT_CLASS (bus_component_parent_class)->constructor (type,
 
130
                                                                       n_construct_params,
 
131
                                                                       construct_params);
 
132
    BusComponent *component = (BusComponent *) object;
 
133
    /* we have to override the _constructor method since in _init method, the component->component property is not set yet. */
 
134
    g_assert (IBUS_IS_COMPONENT (component->component));
 
135
 
 
136
    static GQuark quark = 0;
 
137
    if (quark == 0) {
 
138
        quark = g_quark_from_static_string ("BusComponent");
 
139
    }
 
140
 
 
141
    /* associate each engine with BusComponent. a component might have one or more components. For example, ibus-engine-pinyin would
 
142
     * have two - 'pinyin' and 'bopomofo' and ibus-engine-m17n has many. On the other hand, the gtkpanel component does not have an
 
143
     * engine, of course. */
 
144
    GList *engines = ibus_component_get_engines (component->component);
 
145
    GList *p;
 
146
    for (p = engines; p != NULL; p = p->next) {
 
147
        g_object_set_qdata ((GObject *) p->data, quark, component);
 
148
    }
 
149
    g_list_free (engines);
 
150
 
 
151
    return object;
 
152
}
 
153
 
 
154
static void
 
155
bus_component_set_property (BusComponent *component,
 
156
                            guint         prop_id,
 
157
                            const GValue *value,
 
158
                            GParamSpec   *pspec)
 
159
{
 
160
    switch (prop_id) {
 
161
    case PROP_COMPONENT:
 
162
        g_assert (component->component == NULL);
 
163
        component->component = g_value_dup_object (value);
 
164
        break;
 
165
    case PROP_FACTORY:
 
166
        bus_component_set_factory (component, (BusFactoryProxy *) g_value_get_object (value));
 
167
        break;
 
168
    default:
 
169
        G_OBJECT_WARN_INVALID_PROPERTY_ID (component, prop_id, pspec);
 
170
    }
 
171
}
 
172
 
 
173
static void
 
174
bus_component_get_property (BusComponent *component,
 
175
                            guint         prop_id,
 
176
                            GValue       *value,
 
177
                            GParamSpec   *pspec)
 
178
{
 
179
    switch (prop_id) {
 
180
    case PROP_COMPONENT:
 
181
        g_value_set_object (value, bus_component_get_component (component));
 
182
        break;
 
183
    case PROP_FACTORY:
 
184
        g_value_set_object (value, bus_component_get_factory (component));
 
185
        break;
 
186
    default:
 
187
        G_OBJECT_WARN_INVALID_PROPERTY_ID (component, prop_id, pspec);
 
188
    }
 
189
}
 
190
 
 
191
static void
 
192
bus_component_destroy (BusComponent *component)
 
193
{
 
194
    if (component->pid != 0) {
 
195
        bus_component_stop (component);
 
196
        g_spawn_close_pid (component->pid);
 
197
        component->pid = 0;
 
198
    }
 
199
 
 
200
    if (component->child_source_id != 0) {
 
201
        g_source_remove (component->child_source_id);
 
202
        component->child_source_id = 0;
 
203
    }
 
204
 
 
205
    if (component->component != NULL) {
 
206
        g_object_unref (component->component);
 
207
        component->component = NULL;
 
208
    }
 
209
 
 
210
    IBUS_OBJECT_CLASS (bus_component_parent_class)->destroy (IBUS_OBJECT (component));
 
211
}
 
212
 
 
213
BusComponent *
 
214
bus_component_new (IBusComponent   *component,
 
215
                   BusFactoryProxy *factory)
 
216
{
 
217
    g_assert (IBUS_IS_COMPONENT (component));
 
218
 
 
219
    return (BusComponent *) g_object_new (BUS_TYPE_COMPONENT,
 
220
                                          /* properties below will be set via the bus_component_set_property function. */
 
221
                                          "component", component,
 
222
                                          "factory", factory,
 
223
                                          NULL);
 
224
}
 
225
 
 
226
static void
 
227
bus_component_factory_destroy_cb (BusFactoryProxy *factory,
 
228
                                  BusComponent    *component)
 
229
{
 
230
    g_return_if_fail (component->factory == factory);
 
231
 
 
232
    g_object_unref (component->factory);
 
233
    component->factory = NULL;
 
234
    /* emit the "notify" signal for the factory property on component. */
 
235
    g_object_notify ((GObject *) component, "factory");
 
236
 
 
237
    if (component->destroy_with_factory)
 
238
        ibus_object_destroy ((IBusObject *) component);
 
239
}
 
240
 
 
241
IBusComponent *
 
242
bus_component_get_component (BusComponent *component)
 
243
{
 
244
    g_assert (BUS_IS_COMPONENT (component));
 
245
    return component->component;
 
246
}
 
247
 
 
248
void
 
249
bus_component_set_factory (BusComponent    *component,
 
250
                           BusFactoryProxy *factory)
 
251
{
 
252
    g_assert (BUS_IS_COMPONENT (component));
 
253
 
 
254
    if (component->factory == factory) {
 
255
        return;
 
256
    }
 
257
 
 
258
    if (component->factory) {
 
259
        g_signal_handlers_disconnect_by_func (component->factory,
 
260
                                              bus_component_factory_destroy_cb,
 
261
                                              component);
 
262
        g_object_unref (component->factory);
 
263
        component->factory = NULL;
 
264
    }
 
265
 
 
266
    if (factory) {
 
267
        g_assert (BUS_IS_FACTORY_PROXY (factory));
 
268
        component->factory = (BusFactoryProxy *) g_object_ref (factory);
 
269
        g_signal_connect (factory, "destroy",
 
270
                          G_CALLBACK (bus_component_factory_destroy_cb), component);
 
271
    }
 
272
 
 
273
    /* emit the "notify" signal for the factory property on component. */
 
274
    g_object_notify ((GObject*) component, "factory");
 
275
}
 
276
 
 
277
BusFactoryProxy *
 
278
bus_component_get_factory (BusComponent *component)
 
279
{
 
280
    g_assert (BUS_IS_COMPONENT (component));
 
281
    return component->factory;
 
282
}
 
283
 
 
284
const gchar *
 
285
bus_component_get_name (BusComponent *component)
 
286
{
 
287
    g_assert (BUS_IS_COMPONENT (component));
 
288
 
 
289
    return ibus_component_get_name (component->component);
 
290
}
 
291
 
 
292
GList *
 
293
bus_component_get_engines (BusComponent *component)
 
294
{
 
295
    g_assert (BUS_IS_COMPONENT (component));
 
296
 
 
297
    return ibus_component_get_engines (component->component);
 
298
}
 
299
 
 
300
void
 
301
bus_component_set_destroy_with_factory (BusComponent *component,
 
302
                                        gboolean      with_factory)
 
303
{
 
304
    g_assert (BUS_IS_COMPONENT (component));
 
305
 
 
306
    component->destroy_with_factory = with_factory;
 
307
}
 
308
 
 
309
void
 
310
bus_component_set_restart (BusComponent *component,
 
311
                           gboolean      restart)
 
312
{
 
313
    g_assert (BUS_IS_COMPONENT (component));
 
314
    component->restart = restart;
 
315
}
 
316
 
 
317
/**
 
318
 * bus_component_child_cb:
 
319
 *
 
320
 * A callback function to be called when the child process is terminated.
 
321
 */
 
322
static void
 
323
bus_component_child_cb (GPid          pid,
 
324
                        gint          status,
 
325
                        BusComponent *component)
 
326
{
 
327
    g_assert (BUS_IS_COMPONENT (component));
 
328
    g_assert (component->pid == pid);
 
329
    g_spawn_close_pid (pid);
 
330
    component->pid = 0;
 
331
    component->child_source_id = 0;
 
332
 
 
333
    if (component->restart) {
 
334
        bus_component_start (component, component->verbose);
 
335
    }
 
336
}
 
337
 
 
338
gboolean
 
339
bus_component_start (BusComponent *component,
 
340
                     gboolean      verbose)
 
341
{
 
342
    g_assert (BUS_IS_COMPONENT (component));
 
343
 
 
344
    if (component->pid != 0)
 
345
        return TRUE;
 
346
 
 
347
    component->verbose = verbose;
 
348
 
 
349
    gint argc;
 
350
    gchar **argv;
 
351
    gboolean retval;
 
352
 
 
353
    GError *error = NULL;
 
354
    if (!g_shell_parse_argv (ibus_component_get_exec (component->component),
 
355
                             &argc,
 
356
                             &argv,
 
357
                             &error)) {
 
358
        g_warning ("Can not parse component %s exec: %s",
 
359
                   ibus_component_get_name (component->component),
 
360
                   error->message);
 
361
        g_error_free (error);
 
362
        return FALSE;
 
363
    }
 
364
 
 
365
    error = NULL;
 
366
    GSpawnFlags flags = G_SPAWN_DO_NOT_REAP_CHILD;
 
367
    if (!verbose) {
 
368
        flags |= G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL;
 
369
    }
 
370
    retval = g_spawn_async (NULL, argv, NULL,
 
371
                            flags,
 
372
                            NULL, NULL,
 
373
                            &(component->pid), &error);
 
374
    g_strfreev (argv);
 
375
    if (!retval) {
 
376
        g_warning ("Can not execute component %s: %s",
 
377
                   ibus_component_get_name (component->component),
 
378
                   error->message);
 
379
        g_error_free (error);
 
380
        return FALSE;
 
381
    }
 
382
 
 
383
    component->child_source_id =
 
384
        g_child_watch_add (component->pid,
 
385
                           (GChildWatchFunc) bus_component_child_cb,
 
386
                           component);
 
387
 
 
388
    return TRUE;
 
389
}
 
390
 
 
391
gboolean
 
392
bus_component_stop (BusComponent *component)
 
393
{
 
394
    g_assert (BUS_IS_COMPONENT (component));
 
395
 
 
396
    if (component->pid == 0)
 
397
        return TRUE;
 
398
 
 
399
    kill (component->pid, SIGTERM);
 
400
    return TRUE;
 
401
}
 
402
 
 
403
gboolean
 
404
bus_component_is_running (BusComponent *component)
 
405
{
 
406
    g_assert (BUS_IS_COMPONENT (component));
 
407
 
 
408
    return (component->pid != 0);
 
409
}
 
410
 
 
411
BusComponent *
 
412
bus_component_from_engine_desc (IBusEngineDesc *engine)
 
413
{
 
414
    g_assert (IBUS_IS_ENGINE_DESC (engine));
 
415
 
 
416
    static GQuark quark = 0;
 
417
    if (quark == 0) {
 
418
        quark = g_quark_from_static_string ("BusComponent");
 
419
    }
 
420
 
 
421
    return (BusComponent *) g_object_get_qdata ((GObject *) engine, quark);
 
422
}