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

« back to all changes in this revision

Viewing changes to bus/engineproxy.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:
19
19
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20
20
 * Boston, MA 02111-1307, USA.
21
21
 */
22
 
#include <dbus/dbus.h>
23
 
#include <ibusinternal.h>
24
 
#include <ibusmarshalers.h>
 
22
#include "engineproxy.h"
 
23
#include "types.h"
 
24
#include "marshalers.h"
25
25
#include "ibusimpl.h"
26
 
#include "engineproxy.h"
27
26
#include "option.h"
28
27
 
 
28
struct _BusEngineProxy {
 
29
    IBusProxy parent;
 
30
 
 
31
    /* instance members */
 
32
    /* TRUE if the engine has a focus (local copy of the engine's status.) */
 
33
    gboolean has_focus;
 
34
    /* TRUE if the engine is enabled (local copy of the engine's status.) */
 
35
    gboolean enabled;
 
36
    /* A set of capabilities the current client supports (local copy of the engine's flag.) */
 
37
    guint capabilities;
 
38
    /* The current cursor location that are sent to the engine. */
 
39
    gint x;
 
40
    gint y;
 
41
    gint w;
 
42
    gint h;
 
43
 
 
44
    /* an engine desc used to create the proxy. */
 
45
    IBusEngineDesc *desc;
 
46
 
 
47
    /* a key mapping for the engine that converts keycode into keysym. the mapping is used only when use_sys_layout is FALSE. */
 
48
    IBusKeymap     *keymap;
 
49
    /* private member */
 
50
 
 
51
    /* cached surrounding text (see also IBusEnginePrivate and
 
52
       IBusInputContextPrivate) */
 
53
    IBusText *surrounding_text;
 
54
    guint     surrounding_cursor_pos;
 
55
};
 
56
 
 
57
struct _BusEngineProxyClass {
 
58
    IBusProxyClass parent;
 
59
    /* class members */
 
60
};
 
61
 
29
62
enum {
30
63
    COMMIT_TEXT,
31
64
    FORWARD_KEY_EVENT,
32
65
    DELETE_SURROUNDING_TEXT,
 
66
    REQUIRE_SURROUNDING_TEXT,
33
67
    UPDATE_PREEDIT_TEXT,
34
68
    SHOW_PREEDIT_TEXT,
35
69
    HIDE_PREEDIT_TEXT,
48
82
    LAST_SIGNAL,
49
83
};
50
84
 
 
85
enum {
 
86
    PROP_0 = 0,
 
87
    PROP_ENGINE_DESC,
 
88
};
51
89
 
52
90
static guint    engine_signals[LAST_SIGNAL] = { 0 };
53
 
// static guint            engine_signals[LAST_SIGNAL] = { 0 };
 
91
 
 
92
static IBusText *text_empty = NULL;
54
93
 
55
94
/* functions prototype */
56
 
static void     bus_engine_proxy_real_destroy   (BusEngineProxy         *engine);
57
 
 
58
 
static gboolean bus_engine_proxy_ibus_signal    (IBusProxy              *proxy,
59
 
                                                 IBusMessage            *message);
60
 
 
61
 
G_DEFINE_TYPE (BusEngineProxy, bus_engine_proxy, IBUS_TYPE_PROXY)
62
 
 
63
 
BusEngineProxy *
64
 
bus_engine_proxy_new (const gchar    *path,
65
 
                      IBusEngineDesc *desc,
66
 
                      BusConnection  *connection)
67
 
{
68
 
    g_assert (path);
69
 
    g_assert (IBUS_IS_ENGINE_DESC (desc));
70
 
    g_assert (BUS_IS_CONNECTION (connection));
71
 
 
72
 
    BusEngineProxy *engine;
73
 
 
74
 
    engine = (BusEngineProxy *) g_object_new (BUS_TYPE_ENGINE_PROXY,
75
 
                                              "name", NULL,
76
 
                                              "path", path,
77
 
                                              "connection", connection,
78
 
                                              NULL);
79
 
 
80
 
    engine->desc = desc;
81
 
    g_object_ref_sink (desc);
82
 
    if (desc->layout != NULL && desc->layout[0] != '\0') {
83
 
        engine->keymap = ibus_keymap_get (desc->layout);
84
 
    }
85
 
 
86
 
    if (engine->keymap == NULL) {
87
 
        engine->keymap = ibus_keymap_get ("us");
88
 
    }
89
 
 
90
 
    return engine;
91
 
}
 
95
static void     bus_engine_proxy_set_property   (BusEngineProxy      *engine,
 
96
                                                 guint                prop_id,
 
97
                                                 const GValue        *value,
 
98
                                                 GParamSpec          *pspec);
 
99
static void     bus_engine_proxy_get_property   (BusEngineProxy      *engine,
 
100
                                                 guint                prop_id,
 
101
                                                 GValue              *value,
 
102
                                                 GParamSpec          *pspec);
 
103
static void     bus_engine_proxy_real_destroy   (IBusProxy           *proxy);
 
104
static void     bus_engine_proxy_g_signal       (GDBusProxy          *proxy,
 
105
                                                 const gchar         *sender_name,
 
106
                                                 const gchar         *signal_name,
 
107
                                                 GVariant            *parameters);
 
108
static void     bus_engine_proxy_initable_iface_init
 
109
                                                (GInitableIface      *initable_iface);
 
110
 
 
111
G_DEFINE_TYPE_WITH_CODE (BusEngineProxy, bus_engine_proxy, IBUS_TYPE_PROXY,
 
112
                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, bus_engine_proxy_initable_iface_init)
 
113
                        );
 
114
 
 
115
static GInitableIface *parent_initable_iface = NULL;
92
116
 
93
117
static void
94
 
bus_engine_proxy_class_init (BusEngineProxyClass *klass)
 
118
bus_engine_proxy_class_init (BusEngineProxyClass *class)
95
119
{
96
 
    IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
97
 
    IBusProxyClass *proxy_class = IBUS_PROXY_CLASS (klass);
98
 
 
99
 
 
100
 
    bus_engine_proxy_parent_class = (IBusProxyClass *) g_type_class_peek_parent (klass);
101
 
 
102
 
    ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_engine_proxy_real_destroy;
103
 
 
104
 
    proxy_class->ibus_signal = bus_engine_proxy_ibus_signal;
105
 
 
106
 
    /* install signals */
 
120
    GObjectClass *gobject_class = G_OBJECT_CLASS (class);
 
121
 
 
122
    gobject_class->set_property = (GObjectSetPropertyFunc)bus_engine_proxy_set_property;
 
123
    gobject_class->get_property = (GObjectGetPropertyFunc)bus_engine_proxy_get_property;
 
124
 
 
125
    IBUS_PROXY_CLASS (class)->destroy = bus_engine_proxy_real_destroy;
 
126
    G_DBUS_PROXY_CLASS (class)->g_signal = bus_engine_proxy_g_signal;
 
127
 
 
128
    parent_initable_iface =
 
129
            (GInitableIface *)g_type_interface_peek (bus_engine_proxy_parent_class, G_TYPE_INITABLE);
 
130
 
 
131
    /* install properties */
 
132
    g_object_class_install_property (gobject_class,
 
133
                    PROP_ENGINE_DESC,
 
134
                    g_param_spec_object ("desc",
 
135
                        "desc",
 
136
                        "desc",
 
137
                        IBUS_TYPE_ENGINE_DESC,
 
138
                        G_PARAM_READWRITE |
 
139
                        G_PARAM_CONSTRUCT_ONLY |
 
140
                        G_PARAM_STATIC_NAME |
 
141
                        G_PARAM_STATIC_BLURB |
 
142
                        G_PARAM_STATIC_NICK
 
143
                        ));
 
144
 
 
145
    /* install glib signals that will be sent when corresponding D-Bus signals are sent from an engine process. */
107
146
    engine_signals[COMMIT_TEXT] =
108
147
        g_signal_new (I_("commit-text"),
109
 
            G_TYPE_FROM_CLASS (klass),
 
148
            G_TYPE_FROM_CLASS (class),
110
149
            G_SIGNAL_RUN_LAST,
111
150
            0,
112
151
            NULL, NULL,
113
 
            ibus_marshal_VOID__OBJECT,
 
152
            bus_marshal_VOID__OBJECT,
114
153
            G_TYPE_NONE,
115
154
            1,
116
155
            IBUS_TYPE_TEXT);
117
156
 
118
157
    engine_signals[FORWARD_KEY_EVENT] =
119
158
        g_signal_new (I_("forward-key-event"),
120
 
            G_TYPE_FROM_CLASS (klass),
 
159
            G_TYPE_FROM_CLASS (class),
121
160
            G_SIGNAL_RUN_LAST,
122
161
            0,
123
162
            NULL, NULL,
124
 
            ibus_marshal_VOID__UINT_UINT_UINT,
 
163
            bus_marshal_VOID__UINT_UINT_UINT,
125
164
            G_TYPE_NONE,
126
165
            3,
127
166
            G_TYPE_UINT,
130
169
 
131
170
    engine_signals[DELETE_SURROUNDING_TEXT] =
132
171
        g_signal_new (I_("delete-surrounding-text"),
133
 
            G_TYPE_FROM_CLASS (klass),
 
172
            G_TYPE_FROM_CLASS (class),
134
173
            G_SIGNAL_RUN_LAST,
135
174
            0,
136
175
            NULL, NULL,
137
 
            ibus_marshal_VOID__INT_UINT,
 
176
            bus_marshal_VOID__INT_UINT,
138
177
            G_TYPE_NONE,
139
178
            2,
140
179
            G_TYPE_INT,
141
180
            G_TYPE_UINT);
142
181
 
 
182
    engine_signals[REQUIRE_SURROUNDING_TEXT] =
 
183
        g_signal_new (I_("require-surrounding-text"),
 
184
            G_TYPE_FROM_CLASS (class),
 
185
            G_SIGNAL_RUN_LAST,
 
186
            0,
 
187
            NULL, NULL,
 
188
            bus_marshal_VOID__VOID,
 
189
            G_TYPE_NONE,
 
190
            0);
 
191
 
143
192
    engine_signals[UPDATE_PREEDIT_TEXT] =
144
193
        g_signal_new (I_("update-preedit-text"),
145
 
            G_TYPE_FROM_CLASS (klass),
 
194
            G_TYPE_FROM_CLASS (class),
146
195
            G_SIGNAL_RUN_LAST,
147
196
            0,
148
197
            NULL, NULL,
149
 
            ibus_marshal_VOID__OBJECT_UINT_BOOLEAN_UINT,
 
198
            bus_marshal_VOID__OBJECT_UINT_BOOLEAN_UINT,
150
199
            G_TYPE_NONE,
151
200
            4,
152
201
            IBUS_TYPE_TEXT,
156
205
 
157
206
    engine_signals[SHOW_PREEDIT_TEXT] =
158
207
        g_signal_new (I_("show-preedit-text"),
159
 
            G_TYPE_FROM_CLASS (klass),
 
208
            G_TYPE_FROM_CLASS (class),
160
209
            G_SIGNAL_RUN_LAST,
161
210
            0,
162
211
            NULL, NULL,
163
 
            ibus_marshal_VOID__VOID,
 
212
            bus_marshal_VOID__VOID,
164
213
            G_TYPE_NONE,
165
214
            0);
166
215
 
167
216
    engine_signals[HIDE_PREEDIT_TEXT] =
168
217
        g_signal_new (I_("hide-preedit-text"),
169
 
            G_TYPE_FROM_CLASS (klass),
 
218
            G_TYPE_FROM_CLASS (class),
170
219
            G_SIGNAL_RUN_LAST,
171
220
            0,
172
221
            NULL, NULL,
173
 
            ibus_marshal_VOID__VOID,
 
222
            bus_marshal_VOID__VOID,
174
223
            G_TYPE_NONE,
175
224
            0);
176
225
 
177
226
    engine_signals[UPDATE_AUXILIARY_TEXT] =
178
227
        g_signal_new (I_("update-auxiliary-text"),
179
 
            G_TYPE_FROM_CLASS (klass),
 
228
            G_TYPE_FROM_CLASS (class),
180
229
            G_SIGNAL_RUN_LAST,
181
230
            0,
182
231
            NULL, NULL,
183
 
            ibus_marshal_VOID__OBJECT_BOOLEAN,
 
232
            bus_marshal_VOID__OBJECT_BOOLEAN,
184
233
            G_TYPE_NONE,
185
234
            2,
186
235
            IBUS_TYPE_TEXT,
188
237
 
189
238
    engine_signals[SHOW_AUXILIARY_TEXT] =
190
239
        g_signal_new (I_("show-auxiliary-text"),
191
 
            G_TYPE_FROM_CLASS (klass),
 
240
            G_TYPE_FROM_CLASS (class),
192
241
            G_SIGNAL_RUN_LAST,
193
242
            0,
194
243
            NULL, NULL,
195
 
            ibus_marshal_VOID__VOID,
 
244
            bus_marshal_VOID__VOID,
196
245
            G_TYPE_NONE,
197
246
            0);
198
247
 
199
248
    engine_signals[HIDE_AUXILIARY_TEXT] =
200
249
        g_signal_new (I_("hide-auxiliary-text"),
201
 
            G_TYPE_FROM_CLASS (klass),
 
250
            G_TYPE_FROM_CLASS (class),
202
251
            G_SIGNAL_RUN_LAST,
203
252
            0,
204
253
            NULL, NULL,
205
 
            ibus_marshal_VOID__VOID,
 
254
            bus_marshal_VOID__VOID,
206
255
            G_TYPE_NONE,
207
256
            0);
208
257
 
209
258
    engine_signals[UPDATE_LOOKUP_TABLE] =
210
259
        g_signal_new (I_("update-lookup-table"),
211
 
            G_TYPE_FROM_CLASS (klass),
 
260
            G_TYPE_FROM_CLASS (class),
212
261
            G_SIGNAL_RUN_LAST,
213
262
            0,
214
263
            NULL, NULL,
215
 
            ibus_marshal_VOID__BOXED_BOOLEAN,
 
264
            bus_marshal_VOID__OBJECT_BOOLEAN,
216
265
            G_TYPE_NONE,
217
266
            2,
218
267
            IBUS_TYPE_LOOKUP_TABLE,
220
269
 
221
270
    engine_signals[SHOW_LOOKUP_TABLE] =
222
271
        g_signal_new (I_("show-lookup-table"),
223
 
            G_TYPE_FROM_CLASS (klass),
 
272
            G_TYPE_FROM_CLASS (class),
224
273
            G_SIGNAL_RUN_LAST,
225
274
            0,
226
275
            NULL, NULL,
227
 
            ibus_marshal_VOID__VOID,
 
276
            bus_marshal_VOID__VOID,
228
277
            G_TYPE_NONE,
229
278
            0);
230
279
 
231
280
    engine_signals[HIDE_LOOKUP_TABLE] =
232
281
        g_signal_new (I_("hide-lookup-table"),
233
 
            G_TYPE_FROM_CLASS (klass),
 
282
            G_TYPE_FROM_CLASS (class),
234
283
            G_SIGNAL_RUN_LAST,
235
284
            0,
236
285
            NULL, NULL,
237
 
            ibus_marshal_VOID__VOID,
 
286
            bus_marshal_VOID__VOID,
238
287
            G_TYPE_NONE,
239
288
            0);
240
289
 
241
290
    engine_signals[PAGE_UP_LOOKUP_TABLE] =
242
291
        g_signal_new (I_("page-up-lookup-table"),
243
 
            G_TYPE_FROM_CLASS (klass),
 
292
            G_TYPE_FROM_CLASS (class),
244
293
            G_SIGNAL_RUN_LAST,
245
294
            0,
246
295
            NULL, NULL,
247
 
            ibus_marshal_VOID__VOID,
 
296
            bus_marshal_VOID__VOID,
248
297
            G_TYPE_NONE,
249
298
            0);
250
299
 
251
300
    engine_signals[PAGE_DOWN_LOOKUP_TABLE] =
252
301
        g_signal_new (I_("page-down-lookup-table"),
253
 
            G_TYPE_FROM_CLASS (klass),
 
302
            G_TYPE_FROM_CLASS (class),
254
303
            G_SIGNAL_RUN_LAST,
255
304
            0,
256
305
            NULL, NULL,
257
 
            ibus_marshal_VOID__VOID,
 
306
            bus_marshal_VOID__VOID,
258
307
            G_TYPE_NONE,
259
308
            0);
260
309
 
261
310
    engine_signals[CURSOR_UP_LOOKUP_TABLE] =
262
311
        g_signal_new (I_("cursor-up-lookup-table"),
263
 
            G_TYPE_FROM_CLASS (klass),
 
312
            G_TYPE_FROM_CLASS (class),
264
313
            G_SIGNAL_RUN_LAST,
265
314
            0,
266
315
            NULL, NULL,
267
 
            ibus_marshal_VOID__VOID,
 
316
            bus_marshal_VOID__VOID,
268
317
            G_TYPE_NONE,
269
318
            0);
270
319
 
271
320
    engine_signals[CURSOR_DOWN_LOOKUP_TABLE] =
272
321
        g_signal_new (I_("cursor-down-lookup-table"),
273
 
            G_TYPE_FROM_CLASS (klass),
 
322
            G_TYPE_FROM_CLASS (class),
274
323
            G_SIGNAL_RUN_LAST,
275
324
            0,
276
325
            NULL, NULL,
277
 
            ibus_marshal_VOID__VOID,
 
326
            bus_marshal_VOID__VOID,
278
327
            G_TYPE_NONE,
279
328
            0);
280
329
 
281
330
    engine_signals[REGISTER_PROPERTIES] =
282
331
        g_signal_new (I_("register-properties"),
283
 
            G_TYPE_FROM_CLASS (klass),
 
332
            G_TYPE_FROM_CLASS (class),
284
333
            G_SIGNAL_RUN_LAST,
285
334
            0,
286
335
            NULL, NULL,
287
 
            ibus_marshal_VOID__OBJECT,
 
336
            bus_marshal_VOID__OBJECT,
288
337
            G_TYPE_NONE,
289
338
            1,
290
339
            IBUS_TYPE_PROP_LIST);
291
340
 
292
341
    engine_signals[UPDATE_PROPERTY] =
293
342
        g_signal_new (I_("update-property"),
294
 
            G_TYPE_FROM_CLASS (klass),
 
343
            G_TYPE_FROM_CLASS (class),
295
344
            G_SIGNAL_RUN_LAST,
296
345
            0,
297
346
            NULL, NULL,
298
 
            ibus_marshal_VOID__OBJECT,
 
347
            bus_marshal_VOID__OBJECT,
299
348
            G_TYPE_NONE,
300
349
            1,
301
350
            IBUS_TYPE_PROPERTY);
302
351
 
 
352
    text_empty = ibus_text_new_from_static_string ("");
 
353
    g_object_ref_sink (text_empty);
303
354
}
304
355
 
305
356
static void
306
357
bus_engine_proxy_init (BusEngineProxy *engine)
307
358
{
308
 
    engine->has_focus = FALSE;
309
 
    engine->enabled = FALSE;
310
 
    engine->x = 0;
311
 
    engine->y = 0;
312
 
    engine->w = 0;
313
 
    engine->h = 0;
314
 
    engine->enabled = FALSE;
315
 
    engine->desc = NULL;
316
 
    engine->keymap = NULL;
317
 
}
318
 
 
319
 
static void
320
 
bus_engine_proxy_real_destroy (BusEngineProxy *engine)
321
 
{
322
 
    if (ibus_proxy_get_connection ((IBusProxy *) engine)) {
323
 
        ibus_proxy_call ((IBusProxy *) engine,
324
 
                         "Destroy",
325
 
                         G_TYPE_INVALID);
326
 
    }
 
359
    engine->surrounding_text = g_object_ref_sink (text_empty);
 
360
    engine->surrounding_cursor_pos = 0;
 
361
}
 
362
 
 
363
static void
 
364
bus_engine_proxy_set_property (BusEngineProxy *engine,
 
365
                               guint           prop_id,
 
366
                               const GValue   *value,
 
367
                               GParamSpec     *pspec)
 
368
{
 
369
    switch (prop_id) {
 
370
    case PROP_ENGINE_DESC:
 
371
        g_assert (engine->desc == NULL);
 
372
        engine->desc = g_value_dup_object (value);
 
373
        break;
 
374
    default:
 
375
        G_OBJECT_WARN_INVALID_PROPERTY_ID (engine, prop_id, pspec);
 
376
    }
 
377
}
 
378
 
 
379
static void
 
380
bus_engine_proxy_get_property (BusEngineProxy *engine,
 
381
                               guint           prop_id,
 
382
                               GValue         *value,
 
383
                               GParamSpec     *pspec)
 
384
{
 
385
    switch (prop_id) {
 
386
    case PROP_ENGINE_DESC:
 
387
        g_value_set_object (value, bus_engine_proxy_get_desc (engine));
 
388
        break;
 
389
    default:
 
390
        G_OBJECT_WARN_INVALID_PROPERTY_ID (engine, prop_id, pspec);
 
391
    }
 
392
 
 
393
}
 
394
 
 
395
static void
 
396
bus_engine_proxy_real_destroy (IBusProxy *proxy)
 
397
{
 
398
    BusEngineProxy *engine = (BusEngineProxy *)proxy;
 
399
 
 
400
    g_dbus_proxy_call ((GDBusProxy *)proxy,
 
401
                       "org.freedesktop.IBus.Service.Destroy",
 
402
                       NULL,
 
403
                       G_DBUS_CALL_FLAGS_NONE,
 
404
                       -1,
 
405
                       NULL,
 
406
                       NULL,
 
407
                       NULL);
327
408
 
328
409
    if (engine->desc) {
329
410
        g_object_unref (engine->desc);
335
416
        engine->keymap = NULL;
336
417
    }
337
418
 
338
 
    IBUS_OBJECT_CLASS(bus_engine_proxy_parent_class)->destroy (IBUS_OBJECT (engine));
339
 
}
340
 
 
341
 
static gboolean
342
 
bus_engine_proxy_ibus_signal (IBusProxy     *proxy,
343
 
                              IBusMessage   *message)
344
 
{
345
 
    g_assert (BUS_IS_ENGINE_PROXY (proxy));
346
 
    g_assert (message != NULL);
347
 
    g_assert (ibus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL);
348
 
 
349
 
    const gchar *interface;
350
 
    const gchar *name;
351
 
    BusEngineProxy *engine;
352
 
    IBusError *error;
353
 
    gint i;
354
 
 
 
419
    if (engine->surrounding_text) {
 
420
        g_object_unref (engine->surrounding_text);
 
421
        engine->surrounding_text = NULL;
 
422
    }
 
423
 
 
424
    IBUS_PROXY_CLASS (bus_engine_proxy_parent_class)->destroy ((IBusProxy *)engine);
 
425
}
 
426
 
 
427
static void
 
428
_g_object_unref_if_floating (gpointer instance)
 
429
{
 
430
    if (g_object_is_floating (instance))
 
431
        g_object_unref (instance);
 
432
}
 
433
 
 
434
/**
 
435
 * bus_engine_proxy_g_signal:
 
436
 *
 
437
 * Handle all D-Bus signals from the engine process. This function emits corresponding glib signal for the D-Bus signal.
 
438
 */
 
439
static void
 
440
bus_engine_proxy_g_signal (GDBusProxy  *proxy,
 
441
                           const gchar *sender_name,
 
442
                           const gchar *signal_name,
 
443
                           GVariant    *parameters)
 
444
{
 
445
    BusEngineProxy *engine = (BusEngineProxy *)proxy;
 
446
 
 
447
    /* The list of nullary D-Bus signals. */
355
448
    static const struct {
356
 
        const gchar *member;
357
 
        const guint signal_id;
 
449
        const gchar *signal_name;
 
450
        const guint  signal_id;
358
451
    } signals [] = {
359
452
        { "ShowPreeditText",        SHOW_PREEDIT_TEXT },
360
453
        { "HidePreeditText",        HIDE_PREEDIT_TEXT },
366
459
        { "PageDownLookupTable",    PAGE_DOWN_LOOKUP_TABLE },
367
460
        { "CursorUpLookupTable",    CURSOR_UP_LOOKUP_TABLE },
368
461
        { "CursorDownLookupTable",  CURSOR_DOWN_LOOKUP_TABLE },
 
462
        { "RequireSurroundingText", REQUIRE_SURROUNDING_TEXT },
369
463
    };
370
464
 
371
 
    engine = BUS_ENGINE_PROXY (proxy);
372
 
    interface = ibus_message_get_interface (message);
373
 
    name = ibus_message_get_member (message);
374
 
 
375
 
    if (interface != NULL && g_strcmp0 (interface, IBUS_INTERFACE_ENGINE) != 0)
376
 
        return FALSE;
377
 
 
 
465
    gint i;
378
466
    for (i = 0; i < G_N_ELEMENTS (signals); i++) {
379
 
        if (g_strcmp0 (name, signals[i].member) == 0) {
 
467
        if (g_strcmp0 (signal_name, signals[i].signal_name) == 0) {
380
468
            g_signal_emit (engine, engine_signals[signals[i].signal_id], 0);
381
 
            goto handled;
 
469
            return;
382
470
        }
383
471
    }
384
472
 
385
 
    if (g_strcmp0 (name, "CommitText") == 0) {
386
 
        IBusText *text;
387
 
        gboolean retval;
 
473
    /* Handle D-Bus signals with parameters. Deserialize them and emit a glib signal. */
 
474
    if (g_strcmp0 (signal_name, "CommitText") == 0) {
 
475
        GVariant *arg0 = NULL;
 
476
        g_variant_get (parameters, "(v)", &arg0);
 
477
        g_return_if_fail (arg0 != NULL);
388
478
 
389
 
        retval = ibus_message_get_args (message,
390
 
                                        &error,
391
 
                                        IBUS_TYPE_TEXT, &text,
392
 
                                        G_TYPE_INVALID);
393
 
        if (!retval)
394
 
            goto failed;
 
479
        IBusText *text = IBUS_TEXT (ibus_serializable_deserialize (arg0));
 
480
        g_variant_unref (arg0);
 
481
        g_return_if_fail (text != NULL);
395
482
        g_signal_emit (engine, engine_signals[COMMIT_TEXT], 0, text);
396
 
        g_object_unref (text);
 
483
        _g_object_unref_if_floating (text);
 
484
        return;
397
485
    }
398
 
    else if (g_strcmp0 (name, "ForwardKeyEvent") == 0) {
399
 
        guint32 keyval;
400
 
        guint32 keycode;
401
 
        guint32 states;
402
 
        gboolean retval;
403
 
 
404
 
        retval = ibus_message_get_args (message,
405
 
                                        &error,
406
 
                                        G_TYPE_UINT, &keyval,
407
 
                                        G_TYPE_UINT, &keycode,
408
 
                                        G_TYPE_UINT, &states,
409
 
                                        G_TYPE_INVALID);
410
 
 
411
 
        if (!retval)
412
 
            goto failed;
 
486
 
 
487
    if (g_strcmp0 (signal_name, "ForwardKeyEvent") == 0) {
 
488
        guint32 keyval = 0;
 
489
        guint32 keycode = 0;
 
490
        guint32 states = 0;
 
491
        g_variant_get (parameters, "(uuu)", &keyval, &keycode, &states);
 
492
 
413
493
        g_signal_emit (engine,
414
494
                       engine_signals[FORWARD_KEY_EVENT],
415
495
                       0,
416
496
                       keyval,
417
497
                       keycode,
418
498
                       states);
419
 
    }
420
 
    else if (g_strcmp0 (name, "DeleteSurroundingText") == 0) {
421
 
        gint  offset_from_cursor;
422
 
        guint nchars;
423
 
        gboolean retval;
424
 
 
425
 
        retval = ibus_message_get_args (message,
426
 
                                        &error,
427
 
                                        G_TYPE_INT,  &offset_from_cursor,
428
 
                                        G_TYPE_UINT, &nchars,
429
 
                                        G_TYPE_INVALID);
430
 
 
431
 
        if (!retval)
432
 
            goto failed;
433
 
        g_signal_emit (engine, engine_signals[DELETE_SURROUNDING_TEXT], 0, offset_from_cursor, nchars);
434
 
    }
435
 
    else if (g_strcmp0 (name, "UpdatePreeditText") == 0) {
436
 
        IBusText *text;
437
 
        gint cursor_pos;
438
 
        gboolean visible;
439
 
        gboolean retval;
440
 
        guint mode;
441
 
 
442
 
        retval = ibus_message_get_args (message,
443
 
                                        &error,
444
 
                                        IBUS_TYPE_TEXT, &text,
445
 
                                        G_TYPE_UINT, &cursor_pos,
446
 
                                        G_TYPE_BOOLEAN, &visible,
447
 
                                        G_TYPE_UINT, &mode,
448
 
                                        G_TYPE_INVALID);
449
 
 
450
 
        if (!retval)
451
 
            goto failed;
452
 
 
453
 
        g_signal_emit (engine, engine_signals[UPDATE_PREEDIT_TEXT], 0,
454
 
                        text, cursor_pos, visible, mode);
455
 
        if (g_object_is_floating (text))
456
 
            g_object_unref (text);
457
 
    }
458
 
    else if (g_strcmp0 (name, "UpdateAuxiliaryText") == 0) {
459
 
        IBusText *text;
460
 
        gboolean visible;
461
 
        gboolean retval;
462
 
 
463
 
        retval = ibus_message_get_args (message,
464
 
                                        &error,
465
 
                                        IBUS_TYPE_TEXT, &text,
466
 
                                        G_TYPE_BOOLEAN, &visible,
467
 
                                        G_TYPE_INVALID);
468
 
 
469
 
        if (!retval)
470
 
            goto failed;
 
499
        return;
 
500
    }
 
501
 
 
502
    if (g_strcmp0 (signal_name, "DeleteSurroundingText") == 0) {
 
503
        gint  offset_from_cursor = 0;
 
504
        guint nchars = 0;
 
505
        g_variant_get (parameters, "(iu)", &offset_from_cursor, &nchars);
 
506
 
 
507
        g_signal_emit (engine,
 
508
                       engine_signals[DELETE_SURROUNDING_TEXT],
 
509
                       0, offset_from_cursor, nchars);
 
510
        return;
 
511
    }
 
512
 
 
513
    if (g_strcmp0 (signal_name, "UpdatePreeditText") == 0) {
 
514
        GVariant *arg0 = NULL;
 
515
        guint cursor_pos = 0;
 
516
        gboolean visible = FALSE;
 
517
        guint mode = 0;
 
518
 
 
519
        g_variant_get (parameters, "(vubu)", &arg0, &cursor_pos, &visible, &mode);
 
520
        g_return_if_fail (arg0 != NULL);
 
521
 
 
522
        IBusText *text = IBUS_TEXT (ibus_serializable_deserialize (arg0));
 
523
        g_variant_unref (arg0);
 
524
        g_return_if_fail (text != NULL);
 
525
 
 
526
        g_signal_emit (engine,
 
527
                       engine_signals[UPDATE_PREEDIT_TEXT],
 
528
                       0, text, cursor_pos, visible, mode);
 
529
 
 
530
        _g_object_unref_if_floating (text);
 
531
        return;
 
532
    }
 
533
 
 
534
    if (g_strcmp0 (signal_name, "UpdateAuxiliaryText") == 0) {
 
535
        GVariant *arg0 = NULL;
 
536
        gboolean visible = FALSE;
 
537
 
 
538
        g_variant_get (parameters, "(vb)", &arg0, &visible);
 
539
        g_return_if_fail (arg0 != NULL);
 
540
 
 
541
        IBusText *text = IBUS_TEXT (ibus_serializable_deserialize (arg0));
 
542
        g_variant_unref (arg0);
 
543
        g_return_if_fail (text != NULL);
471
544
 
472
545
        g_signal_emit (engine, engine_signals[UPDATE_AUXILIARY_TEXT], 0, text, visible);
473
 
        if (g_object_is_floating (text))
474
 
            g_object_unref (text);
 
546
        _g_object_unref_if_floating (text);
 
547
        return;
475
548
    }
476
 
    else if (g_strcmp0 (name, "UpdateLookupTable") == 0) {
477
 
        IBusLookupTable *table;
478
 
        gboolean visible;
479
 
        gboolean retval;
480
 
 
481
 
        retval = ibus_message_get_args (message,
482
 
                                        &error,
483
 
                                        IBUS_TYPE_LOOKUP_TABLE, &table,
484
 
                                        G_TYPE_BOOLEAN, &visible,
485
 
                                        G_TYPE_INVALID);
486
 
 
487
 
        if (!retval)
488
 
            goto failed;
 
549
 
 
550
    if (g_strcmp0 (signal_name, "UpdateLookupTable") == 0) {
 
551
        GVariant *arg0 = NULL;
 
552
        gboolean visible = FALSE;
 
553
 
 
554
        g_variant_get (parameters, "(vb)", &arg0, &visible);
 
555
        g_return_if_fail (arg0 != NULL);
 
556
 
 
557
        IBusLookupTable *table = IBUS_LOOKUP_TABLE (ibus_serializable_deserialize (arg0));
 
558
        g_variant_unref (arg0);
 
559
        g_return_if_fail (table != NULL);
489
560
 
490
561
        g_signal_emit (engine, engine_signals[UPDATE_LOOKUP_TABLE], 0, table, visible);
491
 
        if (g_object_is_floating (table))
492
 
            g_object_unref (table);
 
562
        _g_object_unref_if_floating (table);
 
563
        return;
493
564
    }
494
 
    else if (g_strcmp0 (name, "RegisterProperties") == 0) {
495
 
        gboolean retval;
496
 
        IBusPropList *prop_list;
497
 
 
498
 
        retval = ibus_message_get_args (message,
499
 
                                        &error,
500
 
                                        IBUS_TYPE_PROP_LIST, &prop_list,
501
 
                                        G_TYPE_INVALID);
502
 
        if (!retval) {
503
 
            goto failed;
504
 
        }
 
565
 
 
566
    if (g_strcmp0 (signal_name, "RegisterProperties") == 0) {
 
567
        GVariant *arg0 = NULL;
 
568
        g_variant_get (parameters, "(v)", &arg0);
 
569
        g_return_if_fail (arg0 != NULL);
 
570
 
 
571
        IBusPropList *prop_list = IBUS_PROP_LIST (ibus_serializable_deserialize (arg0));
 
572
        g_variant_unref (arg0);
 
573
        g_return_if_fail (prop_list != NULL);
 
574
 
505
575
        g_signal_emit (engine, engine_signals[REGISTER_PROPERTIES], 0, prop_list);
506
 
 
507
 
        if (g_object_is_floating (prop_list))
508
 
            g_object_unref (prop_list);
509
 
 
 
576
        _g_object_unref_if_floating (prop_list);
 
577
        return;
510
578
    }
511
 
    else if (g_strcmp0 (name, "UpdateProperty") == 0) {
512
 
        IBusProperty *prop;
513
 
        gboolean retval;
514
 
 
515
 
        retval = ibus_message_get_args (message,
516
 
                                        &error,
517
 
                                        IBUS_TYPE_PROPERTY, &prop,
518
 
                                        G_TYPE_INVALID);
519
 
 
520
 
        if (!retval)
521
 
            goto failed;
 
579
 
 
580
    if (g_strcmp0 (signal_name, "UpdateProperty") == 0) {
 
581
        GVariant *arg0 = NULL;
 
582
        g_variant_get (parameters, "(v)", &arg0);
 
583
        g_return_if_fail (arg0 != NULL);
 
584
 
 
585
        IBusProperty *prop = IBUS_PROPERTY (ibus_serializable_deserialize (arg0));
 
586
        g_variant_unref (arg0);
 
587
        g_return_if_fail (prop != NULL);
522
588
 
523
589
        g_signal_emit (engine, engine_signals[UPDATE_PROPERTY], 0, prop);
524
 
        if (g_object_is_floating (prop))
525
 
            g_object_unref (prop);
526
 
    }
527
 
    else
528
 
        return FALSE;
529
 
 
530
 
handled:
531
 
    g_signal_stop_emission_by_name (engine, "ibus-signal");
532
 
    return TRUE;
533
 
 
534
 
failed:
535
 
    g_warning ("%s: %s", error->name, error->message);
536
 
    ibus_error_free (error);
537
 
    return FALSE;
 
590
        _g_object_unref_if_floating (prop);
 
591
        return;
 
592
    }
 
593
 
 
594
    g_return_if_reached ();
 
595
}
 
596
 
 
597
static BusEngineProxy *
 
598
bus_engine_proxy_new_internal (const gchar     *path,
 
599
                               IBusEngineDesc  *desc,
 
600
                               GDBusConnection *connection)
 
601
{
 
602
    g_assert (path);
 
603
    g_assert (IBUS_IS_ENGINE_DESC (desc));
 
604
    g_assert (G_IS_DBUS_CONNECTION (connection));
 
605
 
 
606
 
 
607
    BusEngineProxy *engine =
 
608
        (BusEngineProxy *) g_initable_new (BUS_TYPE_ENGINE_PROXY,
 
609
                                           NULL,
 
610
                                           NULL,
 
611
                                           "desc",              desc,
 
612
                                           "g-connection",      connection,
 
613
                                           "g-interface-name",  IBUS_INTERFACE_ENGINE,
 
614
                                           "g-object-path",     path,
 
615
                                           "g-default-timeout", g_gdbus_timeout,
 
616
                                           "g-flags",           G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
 
617
                                           NULL);
 
618
    const gchar *layout = ibus_engine_desc_get_layout (desc);
 
619
    if (layout != NULL && layout[0] != '\0') {
 
620
        engine->keymap = ibus_keymap_get (layout);
 
621
    }
 
622
    return engine;
538
623
}
539
624
 
540
625
typedef struct {
541
 
    GFunc    func;
542
 
    gpointer user_data;
543
 
    BusEngineProxy *engine;
544
 
} CallData;
545
 
 
546
 
static void
547
 
bus_engine_proxy_process_key_event_reply_cb (IBusPendingCall *pending,
548
 
                                             CallData        *call_data)
549
 
{
550
 
    IBusMessage *reply_message;
551
 
    IBusError *error;
552
 
    gboolean retval = FALSE;
553
 
 
554
 
    reply_message = dbus_pending_call_steal_reply (pending);
555
 
 
556
 
    if (reply_message == NULL) {
557
 
        /* reply timeout */
558
 
        IBusObject *connection;
559
 
        connection = (IBusObject *) ibus_proxy_get_connection ((IBusProxy *)call_data->engine);
560
 
        ibus_object_destroy (connection);
561
 
        goto _out;
562
 
    }
563
 
    else if ((error = ibus_error_new_from_message (reply_message)) != NULL) {
564
 
        if (g_strcmp0 (error->name, DBUS_ERROR_NO_REPLY) == 0) {
565
 
            /* reply timeout */
566
 
            IBusObject *connection;
567
 
            connection = (IBusObject *) ibus_proxy_get_connection ((IBusProxy *)call_data->engine);
568
 
            if (connection) {
569
 
                ibus_object_destroy (connection);
 
626
    GSimpleAsyncResult *simple;
 
627
    IBusEngineDesc  *desc;
 
628
    BusComponent    *component;
 
629
    BusFactoryProxy *factory;
 
630
    GCancellable *cancellable;
 
631
    gulong cancelled_handler_id;
 
632
    guint handler_id;
 
633
    guint timeout_id;
 
634
    gint timeout;
 
635
} EngineProxyNewData;
 
636
 
 
637
static void
 
638
engine_proxy_new_data_free (EngineProxyNewData *data)
 
639
{
 
640
    if (data->simple != NULL) {
 
641
        if (data->handler_id != 0)
 
642
            g_signal_handler_disconnect (data->component, data->handler_id);
 
643
        g_object_unref (data->simple);
 
644
    }
 
645
 
 
646
    if (data->component != NULL)
 
647
        g_object_unref (data->component);
 
648
 
 
649
    if (data->factory != NULL)
 
650
        g_object_unref (data->factory);
 
651
 
 
652
    if (data->timeout_id != 0)
 
653
        g_source_remove (data->timeout_id);
 
654
 
 
655
    if (data->cancellable != NULL) {
 
656
        if (data->cancelled_handler_id != 0)
 
657
            g_cancellable_disconnect (data->cancellable,
 
658
                data->cancelled_handler_id);
 
659
        g_object_unref (data->cancellable);
 
660
    }
 
661
 
 
662
    g_slice_free (EngineProxyNewData, data);
 
663
}
 
664
 
 
665
/**
 
666
 * create_engine_ready_cb:
 
667
 *
 
668
 * A callback function to be called when bus_factory_proxy_create_engine finishes.
 
669
 * Create an BusEngineProxy object and call the GAsyncReadyCallback.
 
670
 */
 
671
static void
 
672
create_engine_ready_cb (BusFactoryProxy    *factory,
 
673
                        GAsyncResult       *res,
 
674
                        EngineProxyNewData *data)
 
675
{
 
676
    g_return_if_fail (data->simple != NULL);
 
677
 
 
678
    GError *error = NULL;
 
679
    gchar *path = bus_factory_proxy_create_engine_finish (factory,
 
680
                                                          res,
 
681
                                                          &error);
 
682
    if (path == NULL) {
 
683
        g_simple_async_result_set_from_error (data->simple, error);
 
684
        g_simple_async_result_complete_in_idle (data->simple);
 
685
        engine_proxy_new_data_free (data);
 
686
        return;
 
687
    }
 
688
 
 
689
    BusEngineProxy *engine =
 
690
            bus_engine_proxy_new_internal (path,
 
691
                                           data->desc,
 
692
                                           g_dbus_proxy_get_connection ((GDBusProxy *)data->factory));
 
693
    g_free (path);
 
694
 
 
695
    /* FIXME: set destroy callback ? */
 
696
    g_simple_async_result_set_op_res_gpointer (data->simple, engine, NULL);
 
697
    g_simple_async_result_complete_in_idle (data->simple);
 
698
 
 
699
    engine_proxy_new_data_free (data);
 
700
}
 
701
 
 
702
/**
 
703
 * notify_factory_cb:
 
704
 *
 
705
 * A callback function to be called when bus_component_start() emits "notify::factory" signal within 5 seconds.
 
706
 * Call bus_factory_proxy_create_engine to create the engine proxy asynchronously.
 
707
 */
 
708
static void
 
709
notify_factory_cb (BusComponent       *component,
 
710
                   GParamSpec         *spec,
 
711
                   EngineProxyNewData *data)
 
712
{
 
713
    data->factory = bus_component_get_factory (data->component);
 
714
 
 
715
    if (data->factory != NULL) {
 
716
        g_object_ref (data->factory);
 
717
        /* Timeout should be removed */
 
718
        if (data->timeout_id != 0) {
 
719
            g_source_remove (data->timeout_id);
 
720
            data->timeout_id = 0;
 
721
        }
 
722
        /* Handler of notify::factory should be removed. */
 
723
        if (data->handler_id != 0) {
 
724
            g_signal_handler_disconnect (data->component, data->handler_id);
 
725
            data->handler_id = 0;
 
726
        }
 
727
 
 
728
        /* We *have to* disconnect the cancelled_cb here, since g_dbus_proxy_call
 
729
         * calls create_engine_ready_cb even if the proxy call is cancelled, and
 
730
         * in this case, create_engine_ready_cb itself will return error using
 
731
         * g_simple_async_result_set_from_error and g_simple_async_result_complete.
 
732
         * Otherwise, g_simple_async_result_complete might be called twice for a
 
733
         * single data->simple twice (first in cancelled_cb and later in
 
734
         * create_engine_ready_cb). */
 
735
        if (data->cancellable && data->cancelled_handler_id != 0) {
 
736
            g_cancellable_disconnect (data->cancellable, data->cancelled_handler_id);
 
737
            data->cancelled_handler_id = 0;
 
738
        }
 
739
 
 
740
        /* Create engine from factory. */
 
741
        bus_factory_proxy_create_engine (data->factory,
 
742
                                         data->desc,
 
743
                                         data->timeout,
 
744
                                         data->cancellable,
 
745
                                         (GAsyncReadyCallback) create_engine_ready_cb,
 
746
                                         data);
 
747
    }
 
748
    /* If factory is NULL, we will continue wait for
 
749
     * factory notify signal or timeout */
 
750
}
 
751
 
 
752
/**
 
753
 * timeout_cb:
 
754
 *
 
755
 * A callback function to be called when bus_component_start() does not emit "notify::factory" signal within 5 seconds.
 
756
 * Call the GAsyncReadyCallback and stop the 5 sec timer.
 
757
 */
 
758
static gboolean
 
759
timeout_cb (EngineProxyNewData *data)
 
760
{
 
761
    g_simple_async_result_set_error (data->simple,
 
762
                                     G_DBUS_ERROR,
 
763
                                     G_DBUS_ERROR_FAILED,
 
764
                                     "Timeout was reached");
 
765
    g_simple_async_result_complete_in_idle (data->simple);
 
766
 
 
767
    engine_proxy_new_data_free (data);
 
768
 
 
769
    return FALSE;
 
770
}
 
771
 
 
772
/**
 
773
 * cancelled_cb:
 
774
 *
 
775
 * A callback function to be called when someone calls g_cancellable_cancel() for the cancellable object for bus_engine_proxy_new.
 
776
 * Call the GAsyncReadyCallback.
 
777
 */
 
778
static gboolean
 
779
cancelled_idle_cb (EngineProxyNewData *data)
 
780
{
 
781
    g_simple_async_result_set_error (data->simple,
 
782
                                     G_DBUS_ERROR,
 
783
                                     G_DBUS_ERROR_FAILED,
 
784
                                     "Operation was cancelled");
 
785
    g_simple_async_result_complete_in_idle (data->simple);
 
786
 
 
787
    engine_proxy_new_data_free (data);
 
788
 
 
789
    return FALSE;
 
790
}
 
791
 
 
792
static void
 
793
cancelled_cb (GCancellable       *cancellable,
 
794
              EngineProxyNewData *data)
 
795
{
 
796
    /* Cancel the bus_engine_proxy_new() in idle to avoid deadlock */
 
797
    g_idle_add ((GSourceFunc) cancelled_idle_cb, data);
 
798
}
 
799
 
 
800
void
 
801
bus_engine_proxy_new (IBusEngineDesc      *desc,
 
802
                      gint                 timeout,
 
803
                      GCancellable        *cancellable,
 
804
                      GAsyncReadyCallback  callback,
 
805
                      gpointer             user_data)
 
806
{
 
807
    g_assert (IBUS_IS_ENGINE_DESC (desc));
 
808
    g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
 
809
    g_assert (callback);
 
810
 
 
811
    GSimpleAsyncResult *simple =
 
812
        g_simple_async_result_new (NULL,
 
813
                                   callback,
 
814
                                   user_data,
 
815
                                   bus_engine_proxy_new);
 
816
 
 
817
    if (g_cancellable_is_cancelled (cancellable)) {
 
818
        g_simple_async_result_set_error (simple,
 
819
                                         G_DBUS_ERROR,
 
820
                                         G_DBUS_ERROR_FAILED,
 
821
                                         "Operation was cancelled");
 
822
        g_simple_async_result_complete_in_idle (simple);
 
823
        g_object_unref (simple);
 
824
        return;
 
825
    }
 
826
 
 
827
    EngineProxyNewData *data = g_slice_new0 (EngineProxyNewData);
 
828
    data->desc = g_object_ref (desc);
 
829
    data->component = bus_component_from_engine_desc (desc);
 
830
    g_object_ref (data->component);
 
831
    data->simple = simple;
 
832
    data->timeout = timeout;
 
833
 
 
834
    g_object_set_data ((GObject *)data->simple, "EngineProxyNewData", data);
 
835
 
 
836
    data->factory = bus_component_get_factory (data->component);
 
837
 
 
838
    if (data->factory == NULL) {
 
839
        /* The factory is not ready yet. Create the factory first, and wait for the "notify::factory" signal.
 
840
         * In the handler of "notify::factory", we'll create the engine proxy. */
 
841
        data->handler_id = g_signal_connect (data->component,
 
842
                                             "notify::factory",
 
843
                                             G_CALLBACK (notify_factory_cb),
 
844
                                             data);
 
845
        data->timeout_id = g_timeout_add (timeout,
 
846
                                          (GSourceFunc) timeout_cb,
 
847
                                          data);
 
848
        if (cancellable) {
 
849
            data->cancellable = (GCancellable *) g_object_ref (cancellable);
 
850
            data->cancelled_handler_id = g_cancellable_connect (cancellable,
 
851
                                                                (GCallback) cancelled_cb,
 
852
                                                                data,
 
853
                                                                NULL);
 
854
        }
 
855
        bus_component_start (data->component, g_verbose);
 
856
    }
 
857
    else {
 
858
        /* The factory is ready. We'll create the engine proxy directly. */
 
859
        g_object_ref (data->factory);
 
860
 
 
861
        /* We don't have to connect to cancelled_cb here, since g_dbus_proxy_call
 
862
         * calls create_engine_ready_cb even if the proxy call is cancelled, and
 
863
         * in this case, create_engine_ready_cb itself can return error using
 
864
         * g_simple_async_result_set_from_error and g_simple_async_result_complete. */
 
865
        bus_factory_proxy_create_engine (data->factory,
 
866
                                         data->desc,
 
867
                                         timeout,
 
868
                                         cancellable,
 
869
                                         (GAsyncReadyCallback) create_engine_ready_cb,
 
870
                                         data);
 
871
    }
 
872
}
 
873
 
 
874
BusEngineProxy *
 
875
bus_engine_proxy_new_finish (GAsyncResult   *res,
 
876
                             GError       **error)
 
877
{
 
878
    GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
 
879
 
 
880
    g_assert (error == NULL || *error == NULL);
 
881
    g_assert (g_simple_async_result_get_source_tag (simple) == bus_engine_proxy_new);
 
882
 
 
883
    if (g_simple_async_result_propagate_error (simple, error))
 
884
        return NULL;
 
885
 
 
886
    return (BusEngineProxy *) g_simple_async_result_get_op_res_gpointer(simple);
 
887
}
 
888
 
 
889
void
 
890
bus_engine_proxy_process_key_event (BusEngineProxy      *engine,
 
891
                                    guint                keyval,
 
892
                                    guint                keycode,
 
893
                                    guint                state,
 
894
                                    GAsyncReadyCallback  callback,
 
895
                                    gpointer             user_data)
 
896
{
 
897
    g_assert (BUS_IS_ENGINE_PROXY (engine));
 
898
 
 
899
    if (keycode != 0 && bus_ibus_impl_is_use_sys_layout (BUS_DEFAULT_IBUS) == FALSE) {
 
900
        /* Since use_sys_layout is false, we don't rely on XKB. Try to convert keyval from keycode by using our own mapping. */
 
901
        IBusKeymap *keymap = engine->keymap;
 
902
        if (keymap == NULL)
 
903
            keymap = BUS_DEFAULT_KEYMAP;
 
904
        if (keymap != NULL) {
 
905
            guint t = ibus_keymap_lookup_keysym (engine->keymap, keycode, state);
 
906
            if (t != IBUS_VoidSymbol) {
 
907
                keyval = t;
570
908
            }
571
909
        }
572
 
        g_warning ("%s: %s", error->name, error->message);
573
 
        ibus_error_free (error);
574
 
        goto _out;
575
 
    }
576
 
 
577
 
    if (!ibus_message_get_args (reply_message,
578
 
                                &error,
579
 
                                G_TYPE_BOOLEAN, &retval,
580
 
                                G_TYPE_INVALID)) {
581
 
        g_warning ("%s: %s", error->name, error->message);
582
 
        ibus_error_free (error);
583
 
        goto _out;
584
 
    }
585
 
 
586
 
_out:
587
 
    if (reply_message) {
588
 
        ibus_message_unref (reply_message);
589
 
    }
590
 
    g_object_unref (call_data->engine);
591
 
    call_data->func (GINT_TO_POINTER (retval), call_data->user_data);
592
 
    g_slice_free (CallData, call_data);
593
 
}
594
 
 
595
 
void
596
 
bus_engine_proxy_process_key_event (BusEngineProxy *engine,
597
 
                                    guint           keyval,
598
 
                                    guint           keycode,
599
 
                                    guint           state,
600
 
                                    GFunc           return_cb,
601
 
                                    gpointer        user_data)
602
 
{
603
 
    g_assert (BUS_IS_ENGINE_PROXY (engine));
604
 
    g_assert (return_cb);
605
 
 
606
 
    IBusPendingCall *pending = NULL;
607
 
    CallData *call_data;
608
 
    IBusError *error;
609
 
    gboolean retval;
610
 
 
611
 
    if (keycode != 0 && !BUS_DEFAULT_IBUS->use_sys_layout && engine->keymap != NULL) {
612
 
        guint t = ibus_keymap_lookup_keysym (engine->keymap, keycode, state);
613
 
        if (t != IBUS_VoidSymbol) {
614
 
            keyval = t;
615
 
        }
616
 
    }
617
 
 
618
 
    retval = ibus_proxy_call_with_reply ((IBusProxy *) engine,
619
 
                                         "ProcessKeyEvent",
620
 
                                         &pending,
621
 
                                         g_dbus_timeout,
622
 
                                         &error,
623
 
                                         G_TYPE_UINT, &keyval,
624
 
                                         G_TYPE_UINT, &keycode,
625
 
                                         G_TYPE_UINT, &state,
626
 
                                         G_TYPE_INVALID);
627
 
    if (!retval) {
628
 
        g_warning ("%s: %s", error->name, error->message);
629
 
        ibus_error_free (error);
630
 
        return_cb (GINT_TO_POINTER (FALSE), user_data);
631
 
        return;
632
 
    }
633
 
 
634
 
    call_data = g_slice_new0 (CallData);
635
 
    call_data->func = return_cb;
636
 
    call_data->user_data = user_data;
637
 
    g_object_ref (engine);
638
 
    call_data->engine = engine;
639
 
 
640
 
    retval = ibus_pending_call_set_notify (pending,
641
 
                                           (IBusPendingCallNotifyFunction) bus_engine_proxy_process_key_event_reply_cb,
642
 
                                           call_data,
643
 
                                           NULL);
644
 
    ibus_pending_call_unref (pending);
645
 
 
646
 
    if (!retval) {
647
 
        g_object_unref (call_data->engine);
648
 
        g_slice_free (CallData, call_data);
649
 
        g_warning ("%s : ProcessKeyEvent", DBUS_ERROR_NO_MEMORY);
650
 
        return_cb (GINT_TO_POINTER (FALSE), user_data);
651
 
        return;
652
 
    }
 
910
    }
 
911
 
 
912
    g_dbus_proxy_call ((GDBusProxy *)engine,
 
913
                       "ProcessKeyEvent",
 
914
                       g_variant_new ("(uuu)", keyval, keycode, state),
 
915
                       G_DBUS_CALL_FLAGS_NONE,
 
916
                       -1,
 
917
                       NULL,
 
918
                       callback,
 
919
                       user_data);
653
920
}
654
921
 
655
922
void
666
933
        engine->y = y;
667
934
        engine->w = w;
668
935
        engine->h = h;
669
 
        ibus_proxy_call ((IBusProxy *) engine,
670
 
                         "SetCursorLocation",
671
 
                         G_TYPE_INT, &x,
672
 
                         G_TYPE_INT, &y,
673
 
                         G_TYPE_INT, &w,
674
 
                         G_TYPE_INT, &h,
675
 
                         G_TYPE_INVALID);
 
936
        g_dbus_proxy_call ((GDBusProxy *)engine,
 
937
                           "SetCursorLocation",
 
938
                           g_variant_new ("(iiii)", x, y, w, h),
 
939
                           G_DBUS_CALL_FLAGS_NONE,
 
940
                           -1,
 
941
                           NULL,
 
942
                           NULL,
 
943
                           NULL);
676
944
    }
677
945
}
678
946
 
684
952
 
685
953
    if (engine->capabilities != caps) {
686
954
        engine->capabilities = caps;
687
 
        ibus_proxy_call ((IBusProxy *) engine,
688
 
                         "SetCapabilities",
689
 
                         G_TYPE_UINT, &caps,
690
 
                         G_TYPE_INVALID);
 
955
        g_dbus_proxy_call ((GDBusProxy *)engine,
 
956
                           "SetCapabilities",
 
957
                           g_variant_new ("(u)", caps),
 
958
                           G_DBUS_CALL_FLAGS_NONE,
 
959
                           -1,
 
960
                           NULL,
 
961
                           NULL,
 
962
                           NULL);
691
963
    }
692
964
}
693
965
 
699
971
    g_assert (BUS_IS_ENGINE_PROXY (engine));
700
972
    g_assert (prop_name != NULL);
701
973
 
702
 
    ibus_proxy_call ((IBusProxy *) engine,
703
 
                     "PropertyActivate",
704
 
                     G_TYPE_STRING, &prop_name,
705
 
                     G_TYPE_UINT, &prop_state,
706
 
                     G_TYPE_INVALID);
 
974
    g_dbus_proxy_call ((GDBusProxy *)engine,
 
975
                       "PropertyActivate",
 
976
                       g_variant_new ("(su)", prop_name, prop_state),
 
977
                       G_DBUS_CALL_FLAGS_NONE,
 
978
                       -1,
 
979
                       NULL,
 
980
                       NULL,
 
981
                       NULL);
707
982
}
708
983
 
709
984
void
713
988
    g_assert (BUS_IS_ENGINE_PROXY (engine));
714
989
    g_assert (prop_name != NULL);
715
990
 
716
 
    ibus_proxy_call ((IBusProxy *) engine,
717
 
                     "PropertyShow",
718
 
                     G_TYPE_STRING, &prop_name,
719
 
                     G_TYPE_INVALID);
 
991
    g_dbus_proxy_call ((GDBusProxy *)engine,
 
992
                       "PropertyShow",
 
993
                       g_variant_new ("(s)", prop_name),
 
994
                       G_DBUS_CALL_FLAGS_NONE,
 
995
                       -1,
 
996
                       NULL,
 
997
                       NULL,
 
998
                       NULL);
720
999
}
721
1000
 
722
1001
void bus_engine_proxy_property_hide (BusEngineProxy *engine,
725
1004
    g_assert (BUS_IS_ENGINE_PROXY (engine));
726
1005
    g_assert (prop_name != NULL);
727
1006
 
728
 
    ibus_proxy_call ((IBusProxy *) engine,
729
 
                     "PropertyHide",
730
 
                     G_TYPE_STRING, &prop_name,
731
 
                     G_TYPE_INVALID);
732
 
}
733
 
 
 
1007
    g_dbus_proxy_call ((GDBusProxy *)engine,
 
1008
                       "PropertyHide",
 
1009
                       g_variant_new ("(s)", prop_name),
 
1010
                       G_DBUS_CALL_FLAGS_NONE,
 
1011
                       -1,
 
1012
                       NULL,
 
1013
                       NULL,
 
1014
                       NULL);
 
1015
}
 
1016
 
 
1017
void bus_engine_proxy_set_surrounding_text (BusEngineProxy *engine,
 
1018
                                            IBusText       *text,
 
1019
                                            guint           cursor_pos)
 
1020
{
 
1021
    g_assert (BUS_IS_ENGINE_PROXY (engine));
 
1022
    g_assert (text != NULL);
 
1023
 
 
1024
    if (!engine->surrounding_text ||
 
1025
        g_strcmp0 (text->text, engine->surrounding_text->text) != 0 ||
 
1026
        cursor_pos != engine->surrounding_cursor_pos) {
 
1027
        GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)text);
 
1028
        if (engine->surrounding_text)
 
1029
            g_object_unref (engine->surrounding_text);
 
1030
        engine->surrounding_text = (IBusText *) g_object_ref_sink (text);
 
1031
        engine->surrounding_cursor_pos = cursor_pos;
 
1032
 
 
1033
        g_dbus_proxy_call ((GDBusProxy *)engine,
 
1034
                           "SetSurroundingText",
 
1035
                           g_variant_new ("(vu)", variant, cursor_pos),
 
1036
                           G_DBUS_CALL_FLAGS_NONE,
 
1037
                           -1,
 
1038
                           NULL,
 
1039
                           NULL,
 
1040
                           NULL);
 
1041
    }
 
1042
}
 
1043
 
 
1044
/* a macro to generate a function to call a nullary D-Bus method. */
734
1045
#define DEFINE_FUNCTION(Name, name)                         \
735
1046
    void                                                    \
736
1047
    bus_engine_proxy_##name (BusEngineProxy *engine)        \
737
1048
    {                                                       \
738
1049
        g_assert (BUS_IS_ENGINE_PROXY (engine));            \
739
 
        ibus_proxy_call ((IBusProxy *) engine,              \
740
 
                     #Name,                                 \
741
 
                     G_TYPE_INVALID);                       \
 
1050
        g_dbus_proxy_call ((GDBusProxy *)engine,            \
 
1051
                           #Name,                           \
 
1052
                           NULL,                            \
 
1053
                           G_DBUS_CALL_FLAGS_NONE,          \
 
1054
                           -1, NULL, NULL, NULL);           \
742
1055
    }
743
1056
 
744
1057
DEFINE_FUNCTION (Reset, reset)
755
1068
    g_assert (BUS_IS_ENGINE_PROXY (engine));
756
1069
    if (!engine->has_focus) {
757
1070
        engine->has_focus = TRUE;
758
 
        ibus_proxy_call ((IBusProxy *) engine,
759
 
                         "FocusIn",
760
 
                         G_TYPE_INVALID);
 
1071
        g_dbus_proxy_call ((GDBusProxy *)engine,
 
1072
                           "FocusIn",
 
1073
                           NULL,
 
1074
                           G_DBUS_CALL_FLAGS_NONE,
 
1075
                           -1,
 
1076
                           NULL,
 
1077
                           NULL,
 
1078
                           NULL);
761
1079
    }
762
1080
}
763
1081
 
767
1085
    g_assert (BUS_IS_ENGINE_PROXY (engine));
768
1086
    if (engine->has_focus) {
769
1087
        engine->has_focus = FALSE;
770
 
        ibus_proxy_call ((IBusProxy *) engine,
771
 
                         "FocusOut",
772
 
                         G_TYPE_INVALID);
 
1088
        g_dbus_proxy_call ((GDBusProxy *)engine,
 
1089
                           "FocusOut",
 
1090
                           NULL,
 
1091
                           G_DBUS_CALL_FLAGS_NONE,
 
1092
                           -1,
 
1093
                           NULL,
 
1094
                           NULL,
 
1095
                           NULL);
773
1096
    }
774
1097
}
775
1098
 
779
1102
    g_assert (BUS_IS_ENGINE_PROXY (engine));
780
1103
    if (!engine->enabled) {
781
1104
        engine->enabled = TRUE;
782
 
        ibus_proxy_call ((IBusProxy *) engine,
783
 
                         "Enable",
784
 
                         G_TYPE_INVALID);
 
1105
        g_dbus_proxy_call ((GDBusProxy *)engine,
 
1106
                           "Enable",
 
1107
                           NULL,
 
1108
                           G_DBUS_CALL_FLAGS_NONE,
 
1109
                           -1,
 
1110
                           NULL,
 
1111
                           NULL,
 
1112
                           NULL);
785
1113
    }
786
1114
}
787
1115
 
791
1119
    g_assert (BUS_IS_ENGINE_PROXY (engine));
792
1120
    if (engine->enabled) {
793
1121
        engine->enabled = FALSE;
794
 
        ibus_proxy_call ((IBusProxy *) engine,
795
 
                         "Disable",
796
 
                         G_TYPE_INVALID);
 
1122
        g_dbus_proxy_call ((GDBusProxy *)engine,
 
1123
                           "Disable",
 
1124
                           NULL,
 
1125
                           G_DBUS_CALL_FLAGS_NONE,
 
1126
                           -1,
 
1127
                           NULL,
 
1128
                           NULL,
 
1129
                           NULL);
797
1130
    }
798
1131
}
799
1132
 
805
1138
{
806
1139
    g_assert (BUS_IS_ENGINE_PROXY (engine));
807
1140
 
808
 
    ibus_proxy_call ((IBusProxy *) engine,
809
 
                     "CandidateClicked",
810
 
                     G_TYPE_UINT, &index,
811
 
                     G_TYPE_UINT, &button,
812
 
                     G_TYPE_UINT, &state,
813
 
                     G_TYPE_INVALID);
 
1141
    g_dbus_proxy_call ((GDBusProxy *)engine,
 
1142
                       "CandidateClicked",
 
1143
                       g_variant_new ("(uuu)", index, button, state),
 
1144
                       G_DBUS_CALL_FLAGS_NONE,
 
1145
                       -1,
 
1146
                       NULL,
 
1147
                       NULL,
 
1148
                       NULL);
814
1149
}
815
1150
 
816
1151
IBusEngineDesc *
828
1163
 
829
1164
    return engine->enabled;
830
1165
}
 
1166
 
 
1167
static gboolean
 
1168
initable_init (GInitable     *initable,
 
1169
               GCancellable  *cancellable,
 
1170
               GError       **error)
 
1171
{
 
1172
    BusEngineProxy *engine = BUS_ENGINE_PROXY (initable);
 
1173
    if (engine->desc == NULL) {
 
1174
        *error = g_error_new (G_DBUS_ERROR,
 
1175
                              G_DBUS_ERROR_FAILED,
 
1176
                              "Desc is NULL");
 
1177
        return FALSE;
 
1178
    }
 
1179
 
 
1180
    return parent_initable_iface->init (initable,
 
1181
                                        cancellable,
 
1182
                                        error);
 
1183
}
 
1184
 
 
1185
static void
 
1186
bus_engine_proxy_initable_iface_init (GInitableIface *initable_iface)
 
1187
{
 
1188
    initable_iface->init = initable_init;
 
1189
}