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

« back to all changes in this revision

Viewing changes to bus/inputcontext.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>
25
 
#include "ibusimpl.h"
26
22
#include "inputcontext.h"
 
23
 
 
24
#include <string.h>
 
25
 
27
26
#include "engineproxy.h"
28
27
#include "factoryproxy.h"
 
28
#include "ibusimpl.h"
 
29
#include "marshalers.h"
 
30
#include "option.h"
 
31
#include "types.h"
 
32
 
 
33
struct _SetEngineByDescData {
 
34
    /* context related to the data */
 
35
    BusInputContext *context;
 
36
    /* set engine by desc result, cancellable */
 
37
    GSimpleAsyncResult *simple;
 
38
    /* a object to cancel bus_engine_proxy_new call */
 
39
    GCancellable *cancellable;
 
40
    /* a object being passed to the bus_input_context_set_engine_by_desc function. if origin_cancellable is cancelled by someone,
 
41
     * we cancel the cancellable above as well. */
 
42
    GCancellable *origin_cancellable;
 
43
    gulong cancelled_handler_id;
 
44
};
 
45
typedef struct _SetEngineByDescData SetEngineByDescData;
 
46
 
 
47
struct _BusInputContext {
 
48
    IBusService parent;
 
49
 
 
50
    /* instance members */
 
51
    BusConnection *connection;
 
52
    BusEngineProxy *engine;
 
53
    gchar *client;
 
54
 
 
55
    gboolean has_focus;
 
56
    gboolean enabled;
 
57
 
 
58
    /* client capabilities */
 
59
    guint capabilities;
 
60
 
 
61
    /* cursor location */
 
62
    gint x;
 
63
    gint y;
 
64
    gint w;
 
65
    gint h;
 
66
 
 
67
    /* prev key event that are used for handling hot-keys */
 
68
    guint prev_keyval;
 
69
    guint prev_modifiers;
 
70
 
 
71
    /* preedit text */
 
72
    IBusText *preedit_text;
 
73
    guint     preedit_cursor_pos;
 
74
    gboolean  preedit_visible;
 
75
    guint     preedit_mode;
 
76
 
 
77
    /* auxiliary text */
 
78
    IBusText *auxiliary_text;
 
79
    gboolean  auxiliary_visible;
 
80
 
 
81
    /* lookup table */
 
82
    IBusLookupTable *lookup_table;
 
83
    gboolean lookup_table_visible;
 
84
 
 
85
    /* filter release */
 
86
    gboolean filter_release;
 
87
 
 
88
    /* is fake context */
 
89
    gboolean fake;
 
90
 
 
91
    /* incompleted set engine by desc request */
 
92
    SetEngineByDescData *data;
 
93
};
 
94
 
 
95
struct _BusInputContextClass {
 
96
    IBusServiceClass parent;
 
97
 
 
98
    /* class members */
 
99
};
29
100
 
30
101
enum {
31
102
    PROCESS_KEY_EVENT,
64
135
 
65
136
/* functions prototype */
66
137
static void     bus_input_context_destroy       (BusInputContext        *context);
67
 
static gboolean bus_input_context_ibus_message  (BusInputContext        *context,
68
 
                                                 BusConnection          *connection,
69
 
                                                 IBusMessage            *message);
 
138
static void     bus_input_context_service_method_call
 
139
                                                (IBusService            *service,
 
140
                                                 GDBusConnection        *connection,
 
141
                                                 const gchar            *sender,
 
142
                                                 const gchar            *object_path,
 
143
                                                 const gchar            *interface_name,
 
144
                                                 const gchar            *method_name,
 
145
                                                 GVariant               *parameters,
 
146
                                                 GDBusMethodInvocation  *invocation);
 
147
/*
 
148
static GVariant *bus_input_context_service_get_property
 
149
                                                (IBusService            *service,
 
150
                                                 GDBusConnection        *connection,
 
151
                                                 const gchar            *sender,
 
152
                                                 const gchar            *object_path,
 
153
                                                 const gchar            *interface_name,
 
154
                                                 const gchar            *property_name,
 
155
                                                 GError                **error);
 
156
static gboolean bus_input_context_service_set_property
 
157
                                                (IBusService            *service,
 
158
                                                 GDBusConnection        *connection,
 
159
                                                 const gchar            *sender,
 
160
                                                 const gchar            *object_path,
 
161
                                                 const gchar            *interface_name,
 
162
                                                 const gchar            *property_name,
 
163
                                                 GVariant               *value,
 
164
                                                 GError                **error);
 
165
*/
70
166
static gboolean bus_input_context_filter_keyboard_shortcuts
71
167
                                                (BusInputContext        *context,
72
168
                                                 guint                   keyval,
73
169
                                                 guint                   keycode,
74
170
                                                 guint                   modifiers);
75
 
static gboolean bus_input_context_send_signal   (BusInputContext        *context,
76
 
                                                 const gchar            *signal_name,
77
 
                                                 GType                   first_arg_type,
78
 
                                                 ...);
79
171
 
80
172
static void     bus_input_context_unset_engine  (BusInputContext        *context);
81
173
static void     bus_input_context_commit_text   (BusInputContext        *context,
123
215
static void     _engine_destroy_cb              (BusEngineProxy         *factory,
124
216
                                                 BusInputContext        *context);
125
217
 
126
 
static guint id = 0;
127
218
static IBusText *text_empty = NULL;
128
219
static IBusLookupTable *lookup_table_empty = NULL;
129
220
static IBusPropList    *props_empty = NULL;
130
221
 
 
222
/* The interfaces available in this class, which consists of a list of methods this class implements and
 
223
 * a list of signals this class may emit. Method calls to the interface that are not defined in this XML
 
224
 * will be automatically rejected by the GDBus library (see src/ibusservice.c for details.) */
 
225
static const gchar introspection_xml[] =
 
226
    "<node>"
 
227
    "  <interface name='org.freedesktop.IBus.InputContext'>"
 
228
    /* methods */
 
229
    "    <method name='ProcessKeyEvent'>"
 
230
    "      <arg direction='in'  type='u' name='keyval' />"
 
231
    "      <arg direction='in'  type='u' name='keycode' />"
 
232
    "      <arg direction='in'  type='u' name='state' />"
 
233
    "      <arg direction='out' type='b' name='handled' />"
 
234
    "    </method>"
 
235
    "    <method name='SetCursorLocation'>"
 
236
    "      <arg direction='in' type='i' name='x' />"
 
237
    "      <arg direction='in' type='i' name='y' />"
 
238
    "      <arg direction='in' type='i' name='w' />"
 
239
    "      <arg direction='in' type='i' name='h' />"
 
240
    "    </method>"
 
241
    "    <method name='FocusIn' />"
 
242
    "    <method name='FocusOut' />"
 
243
    "    <method name='Reset' />"
 
244
    "    <method name='Enable' />"
 
245
    "    <method name='Disable' />"
 
246
    "    <method name='IsEnabled'>"
 
247
    "      <arg direction='out' type='b' name='enable' />"
 
248
    "    </method>"
 
249
    "    <method name='SetCapabilities'>"
 
250
    "      <arg direction='in' type='u' name='caps' />"
 
251
    "    </method>"
 
252
    "    <method name='PropertyActivate'>"
 
253
    "      <arg direction='in' type='s' name='name' />"
 
254
    "      <arg direction='in' type='u' name='state' />"
 
255
    "    </method>"
 
256
    "    <method name='SetEngine'>"
 
257
    "      <arg direction='in' type='s' name='name' />"
 
258
    "    </method>"
 
259
    "    <method name='GetEngine'>"
 
260
    "      <arg direction='out' type='v' name='desc' />"
 
261
    "    </method>"
 
262
    "    <method name='SetSurroundingText'>"
 
263
    "      <arg direction='in' type='v' name='text' />"
 
264
    "      <arg direction='in' type='u' name='cursor_pos' />"
 
265
    "    </method>"
 
266
 
 
267
    /* signals */
 
268
    "    <signal name='CommitText'>"
 
269
    "      <arg type='v' name='text' />"
 
270
    "    </signal>"
 
271
    "    <signal name='Enabled'/>"
 
272
    "    <signal name='Disabled'/>"
 
273
    "    <signal name='ForwardKeyEvent'>"
 
274
    "      <arg type='u' name='keyval' />"
 
275
    "      <arg type='u' name='keycode' />"
 
276
    "      <arg type='u' name='state' />"
 
277
    "    </signal>"
 
278
    "    <signal name='UpdatePreeditText'>"
 
279
    "      <arg type='v' name='text' />"
 
280
    "      <arg type='u' name='cursor_pos' />"
 
281
    "      <arg type='b' name='visible' />"
 
282
    "    </signal>"
 
283
    "    <signal name='ShowPreeditText'/>"
 
284
    "    <signal name='HidePreeditText'/>"
 
285
    "    <signal name='UpdateAuxiliaryText'>"
 
286
    "      <arg type='v' name='text' />"
 
287
    "      <arg type='b' name='visible' />"
 
288
    "    </signal>"
 
289
    "    <signal name='ShowAuxiliaryText'/>"
 
290
    "    <signal name='HideAuxiliaryText'/>"
 
291
    "    <signal name='UpdateLookupTable'>"
 
292
    "      <arg type='v' name='table' />"
 
293
    "      <arg type='b' name='visible' />"
 
294
    "    </signal>"
 
295
    "    <signal name='ShowLookupTable'/>"
 
296
    "    <signal name='HideLookupTable'/>"
 
297
    "    <signal name='PageUpLookupTable'/>"
 
298
    "    <signal name='PageDownLookupTable'/>"
 
299
    "    <signal name='CursorUpLookupTable'/>"
 
300
    "    <signal name='CursorDownLookupTable'/>"
 
301
    "    <signal name='RegisterProperties'>"
 
302
    "      <arg type='v' name='props' />"
 
303
    "    </signal>"
 
304
    "    <signal name='UpdateProperty'>"
 
305
    "      <arg type='v' name='prop' />"
 
306
    "    </signal>"
 
307
    "  </interface>"
 
308
    "</node>";
 
309
 
131
310
G_DEFINE_TYPE (BusInputContext, bus_input_context, IBUS_TYPE_SERVICE)
132
311
 
133
 
/* when send preedit to client */
 
312
/* TRUE if we can send preedit text to client. FALSE if the panel has to handle it. Note that we check IBUS_CAP_FOCUS here since
 
313
 * when the capability is not set, the client has to handle a preedit text regardless of the embed_preedit_text config. */
134
314
#define PREEDIT_CONDITION  \
135
315
    ((context->capabilities & IBUS_CAP_PREEDIT_TEXT) && \
136
 
    (BUS_DEFAULT_IBUS->embed_preedit_text || (context->capabilities & IBUS_CAP_FOCUS) == 0))
 
316
     (bus_ibus_impl_is_embed_preedit_text (BUS_DEFAULT_IBUS) || (context->capabilities & IBUS_CAP_FOCUS) == 0))
137
317
 
138
318
static void
139
319
_connection_destroy_cb (BusConnection   *connection,
140
320
                        BusInputContext *context)
141
321
{
142
 
    BUS_IS_CONNECTION (connection);
143
 
    BUS_IS_INPUT_CONTEXT (context);
 
322
    g_assert (BUS_IS_CONNECTION (connection));
 
323
    g_assert (BUS_IS_INPUT_CONTEXT (context));
144
324
 
145
325
    ibus_object_destroy (IBUS_OBJECT (context));
146
326
}
147
327
 
148
 
 
149
 
BusInputContext *
150
 
bus_input_context_new (BusConnection    *connection,
151
 
                       const gchar      *client)
152
 
{
153
 
    g_assert (BUS_IS_CONNECTION (connection));
154
 
    g_assert (client != NULL);
155
 
 
156
 
    BusInputContext *context;
157
 
    gchar *path;
158
 
 
159
 
    path = g_strdup_printf (IBUS_PATH_INPUT_CONTEXT, ++id);
160
 
 
161
 
    context = (BusInputContext *) g_object_new (BUS_TYPE_INPUT_CONTEXT,
162
 
                                                "path", path,
163
 
                                                NULL);
164
 
    g_free (path);
165
 
 
166
 
#if 0
167
 
    ibus_service_add_to_connection (IBUS_SERVICE (context),
168
 
                                 IBUS_CONNECTION (connection));
169
 
#endif
170
 
 
171
 
    g_object_ref_sink (connection);
172
 
    context->connection = connection;
173
 
    context->client = g_strdup (client);
174
 
 
175
 
    /* it is a fake input context, just need process hotkey */
176
 
    context->fake = (g_strcmp0 (client, "fake") == 0);
177
 
 
178
 
    g_signal_connect (context->connection,
179
 
                      "destroy",
180
 
                      (GCallback) _connection_destroy_cb,
181
 
                      context);
182
 
 
183
 
    return context;
184
 
}
185
 
 
186
328
static void
187
 
bus_input_context_class_init (BusInputContextClass *klass)
 
329
bus_input_context_class_init (BusInputContextClass *class)
188
330
{
189
 
    IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
 
331
    IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (class);
190
332
 
191
333
    ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_input_context_destroy;
192
334
 
193
 
    IBUS_SERVICE_CLASS (klass)->ibus_message =
194
 
            (ServiceIBusMessageFunc) bus_input_context_ibus_message;
 
335
    /* override the parent class's implementation. */
 
336
    IBUS_SERVICE_CLASS (class)->service_method_call = bus_input_context_service_method_call;
 
337
    /* register the xml so that bus_ibus_impl_service_method_call will be called on a method call defined in the xml (e.g. 'FocusIn'.) */
 
338
    ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml);
195
339
 
196
 
    /* install signals */
 
340
    /* install glib signals that would be handled by other classes like ibusimpl.c and panelproxy.c. */
197
341
    context_signals[PROCESS_KEY_EVENT] =
198
342
        g_signal_new (I_("process-key-event"),
199
 
            G_TYPE_FROM_CLASS (klass),
 
343
            G_TYPE_FROM_CLASS (class),
200
344
            G_SIGNAL_RUN_LAST,
201
345
            0,
202
346
            NULL, NULL,
203
 
            ibus_marshal_BOOL__UINT_UINT,
 
347
            bus_marshal_BOOL__UINT_UINT_UINT,
204
348
            G_TYPE_BOOLEAN,
205
 
            2,
 
349
            3,
 
350
            G_TYPE_UINT,
206
351
            G_TYPE_UINT,
207
352
            G_TYPE_UINT);
208
353
 
209
354
    context_signals[SET_CURSOR_LOCATION] =
210
355
        g_signal_new (I_("set-cursor-location"),
211
 
            G_TYPE_FROM_CLASS (klass),
 
356
            G_TYPE_FROM_CLASS (class),
212
357
            G_SIGNAL_RUN_LAST,
213
358
            0,
214
359
            NULL, NULL,
215
 
            ibus_marshal_VOID__INT_INT_INT_INT,
 
360
            bus_marshal_VOID__INT_INT_INT_INT,
216
361
            G_TYPE_NONE,
217
362
            4,
218
363
            G_TYPE_INT,
222
367
 
223
368
    context_signals[FOCUS_IN] =
224
369
        g_signal_new (I_("focus-in"),
225
 
            G_TYPE_FROM_CLASS (klass),
 
370
            G_TYPE_FROM_CLASS (class),
226
371
            G_SIGNAL_RUN_LAST,
227
372
            0,
228
373
            NULL, NULL,
229
 
            ibus_marshal_VOID__VOID,
 
374
            bus_marshal_VOID__VOID,
230
375
            G_TYPE_NONE, 0);
231
376
 
232
377
    context_signals[FOCUS_OUT] =
233
378
        g_signal_new (I_("focus-out"),
234
 
            G_TYPE_FROM_CLASS (klass),
 
379
            G_TYPE_FROM_CLASS (class),
235
380
            G_SIGNAL_RUN_LAST,
236
381
            0,
237
382
            NULL, NULL,
238
 
            ibus_marshal_VOID__VOID,
 
383
            bus_marshal_VOID__VOID,
239
384
            G_TYPE_NONE, 0);
240
385
 
241
386
    context_signals[UPDATE_PREEDIT_TEXT] =
242
387
        g_signal_new (I_("update-preedit-text"),
243
 
            G_TYPE_FROM_CLASS (klass),
 
388
            G_TYPE_FROM_CLASS (class),
244
389
            G_SIGNAL_RUN_LAST,
245
390
            0,
246
391
            NULL, NULL,
247
 
            ibus_marshal_VOID__OBJECT_UINT_BOOLEAN,
 
392
            bus_marshal_VOID__OBJECT_UINT_BOOLEAN,
248
393
            G_TYPE_NONE,
249
394
            3,
250
395
            IBUS_TYPE_TEXT,
253
398
 
254
399
    context_signals[SHOW_PREEDIT_TEXT] =
255
400
        g_signal_new (I_("show-preedit-text"),
256
 
            G_TYPE_FROM_CLASS (klass),
 
401
            G_TYPE_FROM_CLASS (class),
257
402
            G_SIGNAL_RUN_LAST,
258
403
            0,
259
404
            NULL, NULL,
260
 
            ibus_marshal_VOID__VOID,
 
405
            bus_marshal_VOID__VOID,
261
406
            G_TYPE_NONE,
262
407
            0);
263
408
 
264
409
    context_signals[HIDE_PREEDIT_TEXT] =
265
410
        g_signal_new (I_("hide-preedit-text"),
266
 
            G_TYPE_FROM_CLASS (klass),
 
411
            G_TYPE_FROM_CLASS (class),
267
412
            G_SIGNAL_RUN_LAST,
268
413
            0,
269
414
            NULL, NULL,
270
 
            ibus_marshal_VOID__VOID,
 
415
            bus_marshal_VOID__VOID,
271
416
            G_TYPE_NONE,
272
417
            0);
273
418
 
274
419
    context_signals[UPDATE_AUXILIARY_TEXT] =
275
420
        g_signal_new (I_("update-auxiliary-text"),
276
 
            G_TYPE_FROM_CLASS (klass),
 
421
            G_TYPE_FROM_CLASS (class),
277
422
            G_SIGNAL_RUN_LAST,
278
423
            0,
279
424
            NULL, NULL,
280
 
            ibus_marshal_VOID__OBJECT_BOOLEAN,
 
425
            bus_marshal_VOID__OBJECT_BOOLEAN,
281
426
            G_TYPE_NONE,
282
427
            2,
283
428
            IBUS_TYPE_TEXT,
285
430
 
286
431
    context_signals[SHOW_AUXILIARY_TEXT] =
287
432
        g_signal_new (I_("show-auxiliary-text"),
288
 
            G_TYPE_FROM_CLASS (klass),
 
433
            G_TYPE_FROM_CLASS (class),
289
434
            G_SIGNAL_RUN_LAST,
290
435
            0,
291
436
            NULL, NULL,
292
 
            ibus_marshal_VOID__VOID,
 
437
            bus_marshal_VOID__VOID,
293
438
            G_TYPE_NONE,
294
439
            0);
295
440
 
296
441
    context_signals[HIDE_AUXILIARY_TEXT] =
297
442
        g_signal_new (I_("hide-auxiliary-text"),
298
 
            G_TYPE_FROM_CLASS (klass),
 
443
            G_TYPE_FROM_CLASS (class),
299
444
            G_SIGNAL_RUN_LAST,
300
445
            0,
301
446
            NULL, NULL,
302
 
            ibus_marshal_VOID__VOID,
 
447
            bus_marshal_VOID__VOID,
303
448
            G_TYPE_NONE,
304
449
            0);
305
450
 
306
451
    context_signals[UPDATE_LOOKUP_TABLE] =
307
452
        g_signal_new (I_("update-lookup-table"),
308
 
            G_TYPE_FROM_CLASS (klass),
 
453
            G_TYPE_FROM_CLASS (class),
309
454
            G_SIGNAL_RUN_LAST,
310
455
            0,
311
456
            NULL, NULL,
312
 
            ibus_marshal_VOID__OBJECT_BOOLEAN,
 
457
            bus_marshal_VOID__OBJECT_BOOLEAN,
313
458
            G_TYPE_NONE,
314
459
            2,
315
460
            IBUS_TYPE_LOOKUP_TABLE,
317
462
 
318
463
    context_signals[SHOW_LOOKUP_TABLE] =
319
464
        g_signal_new (I_("show-lookup-table"),
320
 
            G_TYPE_FROM_CLASS (klass),
 
465
            G_TYPE_FROM_CLASS (class),
321
466
            G_SIGNAL_RUN_LAST,
322
467
            0,
323
468
            NULL, NULL,
324
 
            ibus_marshal_VOID__VOID,
 
469
            bus_marshal_VOID__VOID,
325
470
            G_TYPE_NONE, 0);
326
471
 
327
472
    context_signals[HIDE_LOOKUP_TABLE] =
328
473
        g_signal_new (I_("hide-lookup-table"),
329
 
            G_TYPE_FROM_CLASS (klass),
 
474
            G_TYPE_FROM_CLASS (class),
330
475
            G_SIGNAL_RUN_LAST,
331
476
            0,
332
477
            NULL, NULL,
333
 
            ibus_marshal_VOID__VOID,
 
478
            bus_marshal_VOID__VOID,
334
479
            G_TYPE_NONE, 0);
335
480
 
336
481
    context_signals[PAGE_UP_LOOKUP_TABLE] =
337
482
        g_signal_new (I_("page-up-lookup-table"),
338
 
            G_TYPE_FROM_CLASS (klass),
 
483
            G_TYPE_FROM_CLASS (class),
339
484
            G_SIGNAL_RUN_LAST,
340
485
            0,
341
486
            NULL, NULL,
342
 
            ibus_marshal_VOID__VOID,
 
487
            bus_marshal_VOID__VOID,
343
488
            G_TYPE_NONE, 0);
344
489
 
345
490
    context_signals[PAGE_DOWN_LOOKUP_TABLE] =
346
491
        g_signal_new (I_("page-down-lookup-table"),
347
 
            G_TYPE_FROM_CLASS (klass),
 
492
            G_TYPE_FROM_CLASS (class),
348
493
            G_SIGNAL_RUN_LAST,
349
494
            0,
350
495
            NULL, NULL,
351
 
            ibus_marshal_VOID__VOID,
 
496
            bus_marshal_VOID__VOID,
352
497
            G_TYPE_NONE, 0);
353
498
 
354
499
    context_signals[CURSOR_UP_LOOKUP_TABLE] =
355
500
        g_signal_new (I_("cursor-up-lookup-table"),
356
 
            G_TYPE_FROM_CLASS (klass),
 
501
            G_TYPE_FROM_CLASS (class),
357
502
            G_SIGNAL_RUN_LAST,
358
503
            0,
359
504
            NULL, NULL,
360
 
            ibus_marshal_VOID__VOID,
 
505
            bus_marshal_VOID__VOID,
361
506
            G_TYPE_NONE, 0);
362
507
 
363
508
    context_signals[CURSOR_DOWN_LOOKUP_TABLE] =
364
509
        g_signal_new (I_("cursor-down-lookup-table"),
365
 
            G_TYPE_FROM_CLASS (klass),
 
510
            G_TYPE_FROM_CLASS (class),
366
511
            G_SIGNAL_RUN_LAST,
367
512
            0,
368
513
            NULL, NULL,
369
 
            ibus_marshal_VOID__VOID,
 
514
            bus_marshal_VOID__VOID,
370
515
            G_TYPE_NONE, 0);
371
516
 
372
517
    context_signals[REGISTER_PROPERTIES] =
373
518
        g_signal_new (I_("register-properties"),
374
 
            G_TYPE_FROM_CLASS (klass),
 
519
            G_TYPE_FROM_CLASS (class),
375
520
            G_SIGNAL_RUN_LAST,
376
521
            0,
377
522
            NULL, NULL,
378
 
            ibus_marshal_VOID__OBJECT,
 
523
            bus_marshal_VOID__OBJECT,
379
524
            G_TYPE_NONE,
380
525
            1,
381
526
            IBUS_TYPE_PROP_LIST);
382
527
 
383
528
    context_signals[UPDATE_PROPERTY] =
384
529
        g_signal_new (I_("update-property"),
385
 
            G_TYPE_FROM_CLASS (klass),
 
530
            G_TYPE_FROM_CLASS (class),
386
531
            G_SIGNAL_RUN_LAST,
387
532
            0,
388
533
            NULL, NULL,
389
 
            ibus_marshal_VOID__OBJECT,
 
534
            bus_marshal_VOID__OBJECT,
390
535
            G_TYPE_NONE,
391
536
            1,
392
537
            IBUS_TYPE_PROPERTY);
393
538
 
394
539
    context_signals[ENABLED] =
395
540
        g_signal_new (I_("enabled"),
396
 
            G_TYPE_FROM_CLASS (klass),
 
541
            G_TYPE_FROM_CLASS (class),
397
542
            G_SIGNAL_RUN_LAST,
398
543
            0,
399
544
            NULL, NULL,
400
 
            ibus_marshal_VOID__VOID,
 
545
            bus_marshal_VOID__VOID,
401
546
            G_TYPE_NONE,
402
547
            0);
403
548
 
404
549
    context_signals[DISABLED] =
405
550
        g_signal_new (I_("disabled"),
406
 
            G_TYPE_FROM_CLASS (klass),
 
551
            G_TYPE_FROM_CLASS (class),
407
552
            G_SIGNAL_RUN_LAST,
408
553
            0,
409
554
            NULL, NULL,
410
 
            ibus_marshal_VOID__VOID,
 
555
            bus_marshal_VOID__VOID,
411
556
            G_TYPE_NONE,
412
557
            0);
413
558
 
414
559
    context_signals[ENGINE_CHANGED] =
415
560
        g_signal_new (I_("engine-changed"),
416
 
            G_TYPE_FROM_CLASS (klass),
 
561
            G_TYPE_FROM_CLASS (class),
417
562
            G_SIGNAL_RUN_LAST,
418
563
            0,
419
564
            NULL, NULL,
420
 
            ibus_marshal_VOID__VOID,
 
565
            bus_marshal_VOID__VOID,
421
566
            G_TYPE_NONE,
422
567
            0);
423
568
 
 
569
    /* This signal is not for notifying an event on this object, but is for requesting an engine as the name shows.
 
570
     * On the signal emission, ibusimpl.c will immediately update the context->engine variable. */
424
571
    context_signals[REQUEST_ENGINE] =
425
572
        g_signal_new (I_("request-engine"),
426
 
            G_TYPE_FROM_CLASS (klass),
 
573
            G_TYPE_FROM_CLASS (class),
427
574
            G_SIGNAL_RUN_LAST,
428
575
            0,
429
576
            NULL, NULL,
430
 
            ibus_marshal_VOID__STRING,
431
 
            G_TYPE_NONE,
 
577
            bus_marshal_OBJECT__STRING,
 
578
            IBUS_TYPE_ENGINE_DESC,
432
579
            1,
433
580
            G_TYPE_STRING);
434
581
 
435
582
    text_empty = ibus_text_new_from_string ("");
436
583
    g_object_ref_sink (text_empty);
437
 
    lookup_table_empty = ibus_lookup_table_new (9, 0, FALSE, FALSE);
 
584
    lookup_table_empty = ibus_lookup_table_new (9 /* page size */, 0, FALSE, FALSE);
438
585
    g_object_ref_sink (lookup_table_empty);
439
586
    props_empty = ibus_prop_list_new ();
440
587
    g_object_ref_sink (props_empty);
443
590
static void
444
591
bus_input_context_init (BusInputContext *context)
445
592
{
446
 
    context->connection = NULL;
447
 
    context->client = NULL;
448
 
    context->engine = NULL;
449
 
    context->has_focus = FALSE;
450
 
    context->enabled = FALSE;
451
 
 
452
593
    context->prev_keyval = IBUS_VoidSymbol;
453
 
    context->prev_modifiers = 0;
454
 
 
455
 
    context->capabilities = 0;
456
 
 
457
 
    context->x = 0;
458
 
    context->y = 0;
459
 
    context->w = 0;
460
 
    context->h = 0;
461
 
 
462
594
    g_object_ref_sink (text_empty);
463
595
    context->preedit_text = text_empty;
464
 
    context->preedit_cursor_pos = 0;
465
 
    context->preedit_visible = FALSE;
466
596
    context->preedit_mode = IBUS_ENGINE_PREEDIT_CLEAR;
467
 
 
468
597
    g_object_ref_sink (text_empty);
469
598
    context->auxiliary_text = text_empty;
470
 
    context->auxiliary_visible = FALSE;
471
 
 
472
599
    g_object_ref_sink (lookup_table_empty);
473
600
    context->lookup_table = lookup_table_empty;
474
 
    context->lookup_table_visible = FALSE;
475
 
 
 
601
    /* other member variables will automatically be zero-cleared. */
476
602
}
477
603
 
478
604
static void
515
641
        context->client = NULL;
516
642
    }
517
643
 
518
 
    IBUS_OBJECT_CLASS(bus_input_context_parent_class)->destroy (IBUS_OBJECT (context));
519
 
}
520
 
 
521
 
/* introspectable interface */
522
 
static IBusMessage *
523
 
_ibus_introspect (BusInputContext   *context,
524
 
                  IBusMessage       *message,
525
 
                  BusConnection     *connection)
526
 
{
527
 
    static const gchar *introspect =
528
 
        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
529
 
        "<node>\n"
530
 
        "  <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
531
 
        "    <method name=\"Introspect\">\n"
532
 
        "      <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
533
 
        "    </method>\n"
534
 
        "  </interface>\n"
535
 
        "  <interface name=\"org.freedesktop.IBus.InputContext\">\n"
536
 
 
537
 
        /* methods */
538
 
        "    <method name=\"ProcessKeyEvent\">\n"
539
 
        "      <arg name=\"keyval\" direction=\"in\" type=\"u\"/>\n"
540
 
        "      <arg name=\"keycode\" direction=\"in\" type=\"u\"/>\n"
541
 
        "      <arg name=\"state\" direction=\"in\" type=\"u\"/>\n"
542
 
        "      <arg name=\"handled\" direction=\"out\" type=\"b\"/>\n"
543
 
        "    </method>\n"
544
 
        "    <method name=\"SetCursorLocation\">\n"
545
 
        "      <arg name=\"x\" direction=\"in\" type=\"i\"/>\n"
546
 
        "      <arg name=\"y\" direction=\"in\" type=\"i\"/>\n"
547
 
        "      <arg name=\"w\" direction=\"in\" type=\"i\"/>\n"
548
 
        "      <arg name=\"h\" direction=\"in\" type=\"i\"/>\n"
549
 
        "    </method>\n"
550
 
        "    <method name=\"FocusIn\"/>\n"
551
 
        "    <method name=\"FocusOut\"/>\n"
552
 
        "    <method name=\"Reset\"/>\n"
553
 
        "    <method name=\"Enable\"/>\n"
554
 
        "    <method name=\"Disable\"/>\n"
555
 
        "    <method name=\"IsEnabled\">\n"
556
 
        "      <arg name=\"enable\" direction=\"out\" type=\"b\"/>\n"
557
 
        "    </method>\n"
558
 
        "    <method name=\"SetCapabilities\">\n"
559
 
        "      <arg name=\"caps\" direction=\"in\" type=\"u\"/>\n"
560
 
        "    </method>\n"
561
 
        "    <method name=\"PropertyActivate\">\n"
562
 
        "      <arg name=\"name\" direction=\"in\" type=\"s\"/>\n"
563
 
        "      <arg name=\"state\" direction=\"in\" type=\"i\"/>\n"
564
 
        "    </method>\n"
565
 
        "    <method name=\"SetEngine\">\n"
566
 
        "      <arg name=\"name\" direction=\"in\" type=\"s\"/>\n"
567
 
        "    </method>\n"
568
 
        "    <method name=\"GetEngine\">\n"
569
 
        "      <arg name=\"desc\" direction=\"out\" type=\"v\"/>\n"
570
 
        "    </method>\n"
571
 
        "    <method name=\"Destroy\"/>\n"
572
 
 
573
 
        /* signals */
574
 
        "    <signal name=\"CommitText\">\n"
575
 
        "      <arg name=\"text\" type=\"v\"/>\n"
576
 
        "    </signal>\n"
577
 
        "    <signal name=\"Enabled\"/>\n"
578
 
        "    <signal name=\"Disabled\"/>\n"
579
 
        "    <signal name=\"ForwardKeyEvent\">\n"
580
 
        "      <arg name=\"keyval\" type=\"u\"/>\n"
581
 
        "      <arg name=\"keycode\" type=\"u\"/>\n"
582
 
        "      <arg name=\"state\" type=\"u\"/>\n"
583
 
        "    </signal>\n"
584
 
 
585
 
        "    <signal name=\"UpdatePreeditText\">\n"
586
 
        "      <arg name=\"text\" type=\"v\"/>\n"
587
 
        "      <arg name=\"cursor_pos\" type=\"u\"/>\n"
588
 
        "      <arg name=\"visible\" type=\"b\"/>\n"
589
 
        "    </signal>\n"
590
 
        "    <signal name=\"ShowPreeditText\"/>\n"
591
 
        "    <signal name=\"HidePreeditText\"/>\n"
592
 
 
593
 
        "    <signal name=\"UpdateAuxiliaryText\">\n"
594
 
        "      <arg name=\"text\" type=\"v\"/>\n"
595
 
        "      <arg name=\"visible\" type=\"b\"/>\n"
596
 
        "    </signal>\n"
597
 
        "    <signal name=\"ShowAuxiliaryText\"/>\n"
598
 
        "    <signal name=\"HideAuxiliaryText\"/>\n"
599
 
 
600
 
        "    <signal name=\"UpdateLookupTable\">\n"
601
 
        "      <arg name=\"table\" type=\"v\"/>\n"
602
 
        "      <arg name=\"visible\" type=\"b\"/>\n"
603
 
        "    </signal>\n"
604
 
        "    <signal name=\"ShowLookupTable\"/>\n"
605
 
        "    <signal name=\"HideLookupTable\"/>\n"
606
 
        "    <signal name=\"PageUpLookupTable\"/>\n"
607
 
        "    <signal name=\"PageDownLookupTable\"/>\n"
608
 
        "    <signal name=\"CursorUpLookupTable\"/>\n"
609
 
        "    <signal name=\"CursorDownLookupTable\"/>\n"
610
 
 
611
 
        "    <signal name=\"RegisterProperties\">\n"
612
 
        "      <arg name=\"props\" type=\"v\"/>\n"
613
 
        "    </signal>\n"
614
 
        "    <signal name=\"UpdateProperty\">\n"
615
 
        "      <arg name=\"prop\" type=\"v\"/>\n"
616
 
        "    </signal>\n"
617
 
 
618
 
        "  </interface>\n"
619
 
        "</node>\n";
620
 
 
621
 
    IBusMessage *reply_message;
622
 
    reply_message = ibus_message_new_method_return (message);
623
 
    ibus_message_append_args (reply_message,
624
 
                              G_TYPE_STRING, &introspect,
625
 
                              G_TYPE_INVALID);
626
 
 
627
 
    return reply_message;
628
 
}
629
 
 
630
 
typedef struct {
631
 
    BusInputContext *context;
632
 
    IBusMessage     *message;
633
 
} CallData;
634
 
 
635
 
static void
636
 
_ic_process_key_event_reply_cb (gpointer data,
637
 
                                gpointer user_data)
638
 
{
639
 
    gboolean retval;
640
 
    CallData *call_data;
641
 
 
642
 
    retval = (gboolean) GPOINTER_TO_INT (data);
643
 
    call_data = (CallData *) user_data;
644
 
 
645
 
    /* make sure the connection is alive */
646
 
    if (G_LIKELY (call_data->context->connection != NULL)) {
647
 
        IBusMessage *reply;
648
 
        reply = ibus_message_new_method_return (call_data->message);
649
 
        ibus_message_append_args (reply,
650
 
                                  G_TYPE_BOOLEAN, &retval,
651
 
                                  G_TYPE_INVALID);
652
 
 
653
 
        ibus_connection_send ((IBusConnection *)call_data->context->connection, reply);
654
 
        ibus_message_unref (reply);
655
 
    }
656
 
 
657
 
    g_object_unref (call_data->context);
658
 
    ibus_message_unref (call_data->message);
659
 
    g_slice_free (CallData, call_data);
660
 
}
661
 
 
662
 
static IBusMessage *
663
 
_ic_process_key_event  (BusInputContext *context,
664
 
                        IBusMessage     *message,
665
 
                        BusConnection   *connection)
666
 
{
667
 
    g_assert (BUS_IS_INPUT_CONTEXT (context));
668
 
    g_assert (message != NULL);
669
 
    g_assert (BUS_IS_CONNECTION (connection));
670
 
 
671
 
    IBusMessage *reply;
672
 
    guint keyval, keycode, modifiers;
673
 
    gboolean retval;
674
 
    IBusError *error;
675
 
 
676
 
    retval = ibus_message_get_args (message,
677
 
                &error,
678
 
                G_TYPE_UINT, &keyval,
679
 
                G_TYPE_UINT, &keycode,
680
 
                G_TYPE_UINT, &modifiers,
681
 
                G_TYPE_INVALID);
682
 
 
683
 
    if (!retval) {
684
 
        reply = ibus_message_new_error (message,
685
 
                                        error->name,
686
 
                                        error->message);
687
 
        ibus_error_free (error);
688
 
        return reply;
689
 
    }
690
 
 
 
644
    IBUS_OBJECT_CLASS (bus_input_context_parent_class)->destroy (IBUS_OBJECT (context));
 
645
}
 
646
 
 
647
/**
 
648
 * bus_input_context_emit_signal:
 
649
 * @signal_name: The D-Bus signal name to emit which is in the introspection_xml.
 
650
 *
 
651
 * Emit the D-Bus signal.
 
652
 */
 
653
static gboolean
 
654
bus_input_context_emit_signal (BusInputContext *context,
 
655
                               const gchar     *signal_name,
 
656
                               GVariant        *parameters,
 
657
                               GError         **error)
 
658
{
 
659
    if (context->connection == NULL)
 
660
        return TRUE;
 
661
 
 
662
    GDBusMessage *message = g_dbus_message_new_signal (ibus_service_get_object_path ((IBusService *)context),
 
663
                                                       "org.freedesktop.IBus.InputContext",
 
664
                                                       signal_name);
 
665
    g_dbus_message_set_sender (message, "org.freedesktop.IBus");
 
666
    g_dbus_message_set_destination (message, bus_connection_get_unique_name (context->connection));
 
667
    if (parameters != NULL)
 
668
        g_dbus_message_set_body (message, parameters);
 
669
 
 
670
    gboolean retval =  g_dbus_connection_send_message (bus_connection_get_dbus_connection (context->connection),
 
671
                                                       message,
 
672
                                                       G_DBUS_SEND_MESSAGE_FLAGS_NONE,
 
673
                                                       NULL, error);
 
674
    g_object_unref (message);
 
675
    return retval;
 
676
}
 
677
 
 
678
/**
 
679
 * _ic_process_key_event_reply_cb:
 
680
 *
 
681
 * A GAsyncReadyCallback function to be called when bus_engine_proxy_process_key_event() is finished.
 
682
 */
 
683
static void
 
684
_ic_process_key_event_reply_cb (GObject               *source,
 
685
                                GAsyncResult          *res,
 
686
                                GDBusMethodInvocation *invocation)
 
687
{
 
688
    GError *error = NULL;
 
689
    GVariant *value = g_dbus_proxy_call_finish ((GDBusProxy *)source,
 
690
                                                 res,
 
691
                                                 &error);
 
692
    if (value != NULL) {
 
693
        g_dbus_method_invocation_return_value (invocation, value);
 
694
        g_variant_unref (value);
 
695
    }
 
696
    else {
 
697
        g_dbus_method_invocation_return_gerror (invocation, error);
 
698
        g_error_free (error);
 
699
    }
 
700
}
 
701
 
 
702
/**
 
703
 * _ic_process_key_event:
 
704
 *
 
705
 * Implement the "ProcessKeyEvent" method call of the org.freedesktop.IBus.InputContext interface.
 
706
 */
 
707
static void
 
708
_ic_process_key_event  (BusInputContext       *context,
 
709
                        GVariant              *parameters,
 
710
                        GDBusMethodInvocation *invocation)
 
711
{
 
712
    guint keyval = IBUS_VoidSymbol;
 
713
    guint keycode = 0;
 
714
    guint modifiers = 0;
 
715
 
 
716
    g_variant_get (parameters, "(uuu)", &keyval, &keycode, &modifiers);
691
717
    if (G_UNLIKELY (!context->has_focus)) {
692
718
        /* workaround: set focus if context does not have focus */
693
 
        if (BUS_DEFAULT_IBUS->focused_context == NULL ||
694
 
            BUS_DEFAULT_IBUS->focused_context->fake == TRUE ||
 
719
        BusInputContext *focused_context = bus_ibus_impl_get_focused_input_context (BUS_DEFAULT_IBUS);
 
720
        if (focused_context == NULL ||
 
721
            focused_context->fake == TRUE ||
695
722
            context->fake == FALSE) {
696
723
            /* grab focus, if context is a real IC or current focused IC is fake */
697
724
            bus_input_context_focus_in (context);
699
726
    }
700
727
 
701
728
    if (G_LIKELY (context->has_focus)) {
702
 
        retval = bus_input_context_filter_keyboard_shortcuts (context, keyval, keycode, modifiers);
 
729
        gboolean retval = bus_input_context_filter_keyboard_shortcuts (context, keyval, keycode, modifiers);
703
730
        /* If it is keyboard shortcut, reply TRUE to client */
704
731
        if (G_UNLIKELY (retval)) {
705
 
            reply = ibus_message_new_method_return (message);
706
 
            ibus_message_append_args (reply,
707
 
                                      G_TYPE_BOOLEAN, &retval,
708
 
                                      G_TYPE_INVALID);
709
 
            return reply;
 
732
            g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
 
733
            return;
710
734
        }
711
735
    }
712
736
 
713
737
    /* ignore key events, if it is a fake input context */
714
738
    if (context->has_focus && context->enabled && context->engine && context->fake == FALSE) {
715
 
        CallData *call_data;
716
 
 
717
 
        call_data = g_slice_new (CallData);
718
 
 
719
 
        g_object_ref (context);
720
 
        ibus_message_ref (message);
721
 
 
722
 
        call_data->context = context;
723
 
        call_data->message = message;
724
 
 
725
739
        bus_engine_proxy_process_key_event (context->engine,
726
740
                                            keyval,
727
741
                                            keycode,
728
742
                                            modifiers,
729
 
                                            (GFunc) _ic_process_key_event_reply_cb,
730
 
                                            call_data);
731
 
        return NULL;
 
743
                                            (GAsyncReadyCallback) _ic_process_key_event_reply_cb,
 
744
                                            invocation);
732
745
    }
733
746
    else {
734
 
        retval = FALSE;
735
 
        reply = ibus_message_new_method_return (message);
736
 
        ibus_message_append_args (reply,
737
 
                                  G_TYPE_BOOLEAN, &retval,
738
 
                                  G_TYPE_INVALID);
739
 
        return reply;
 
747
        g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", FALSE));
740
748
    }
741
749
}
742
750
 
743
 
static IBusMessage *
744
 
_ic_set_cursor_location (BusInputContext  *context,
745
 
                         IBusMessage      *message,
746
 
                         BusConnection    *connection)
 
751
/**
 
752
 * _ic_set_cursor_location:
 
753
 *
 
754
 * Implement the "SetCursorLocation" method call of the org.freedesktop.IBus.InputContext interface.
 
755
 */
 
756
static void
 
757
_ic_set_cursor_location (BusInputContext       *context,
 
758
                         GVariant              *parameters,
 
759
                         GDBusMethodInvocation *invocation)
747
760
{
748
 
    g_assert (BUS_IS_INPUT_CONTEXT (context));
749
 
    g_assert (message != NULL);
750
 
    g_assert (BUS_IS_CONNECTION (connection));
751
 
 
752
 
    IBusMessage *reply;
753
 
    guint x, y, w, h;
754
 
    gboolean retval;
755
 
    IBusError *error;
756
 
 
757
 
    retval = ibus_message_get_args (message, &error,
758
 
                G_TYPE_INT, &x,
759
 
                G_TYPE_INT, &y,
760
 
                G_TYPE_INT, &w,
761
 
                G_TYPE_INT, &h,
762
 
                G_TYPE_INVALID);
763
 
 
764
 
    if (!retval) {
765
 
        reply = ibus_message_new_error (message,
766
 
                                        error->name,
767
 
                                        error->message);
768
 
        ibus_error_free (error);
769
 
        return reply;
770
 
    }
771
 
 
772
 
    context->x = x;
773
 
    context->y = y;
774
 
    context->h = h;
775
 
    context->w = w;
 
761
    g_dbus_method_invocation_return_value (invocation, NULL);
 
762
 
 
763
    g_variant_get (parameters, "(iiii)",
 
764
                   &context->x, &context->y, &context->w, &context->h);
776
765
 
777
766
    if (context->has_focus && context->enabled && context->engine) {
778
 
        bus_engine_proxy_set_cursor_location (context->engine, x, y, w, h);
 
767
        bus_engine_proxy_set_cursor_location (context->engine,
 
768
                        context->x, context->y, context->w, context->h);
779
769
    }
780
770
 
781
771
    if (context->capabilities & IBUS_CAP_FOCUS) {
782
772
        g_signal_emit (context,
783
773
                       context_signals[SET_CURSOR_LOCATION],
784
774
                       0,
785
 
                       x,
786
 
                       y,
787
 
                       w,
788
 
                       h);
 
775
                       context->x,
 
776
                       context->y,
 
777
                       context->w,
 
778
                       context->h);
789
779
    }
790
 
 
791
 
    reply = ibus_message_new_method_return (message);
792
 
    return reply;
793
780
}
794
781
 
795
 
static IBusMessage *
796
 
_ic_focus_in (BusInputContext  *context,
797
 
              IBusMessage      *message,
798
 
              BusConnection    *connection)
 
782
/**
 
783
 * _ic_focus_in:
 
784
 *
 
785
 * Implement the "FocusIn" method call of the org.freedesktop.IBus.InputContext interface.
 
786
 */
 
787
static void
 
788
_ic_focus_in (BusInputContext       *context,
 
789
              GVariant              *parameters,
 
790
              GDBusMethodInvocation *invocation)
799
791
{
800
 
    g_assert (BUS_IS_INPUT_CONTEXT (context));
801
 
    g_assert (message != NULL);
802
 
    g_assert (BUS_IS_CONNECTION (connection));
803
 
 
804
 
    IBusMessage *reply;
805
 
 
806
792
    if (context->capabilities & IBUS_CAP_FOCUS) {
807
793
        bus_input_context_focus_in (context);
808
 
        reply = ibus_message_new_method_return (message);
 
794
        g_dbus_method_invocation_return_value (invocation, NULL);
809
795
    }
810
796
    else {
811
 
        reply = ibus_message_new_error (message,
812
 
                                        DBUS_ERROR_FAILED,
813
 
                                        "The input context does not support focus.");
 
797
        g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
 
798
                        "The input context does not support focus.");
814
799
    }
815
 
 
816
 
    return reply;
817
800
}
818
801
 
819
 
static IBusMessage *
820
 
_ic_focus_out (BusInputContext  *context,
821
 
              IBusMessage      *message,
822
 
              BusConnection    *connection)
 
802
/**
 
803
 * _ic_focus_out:
 
804
 *
 
805
 * Implement the "FocusOut" method call of the org.freedesktop.IBus.InputContext interface.
 
806
 */
 
807
static void
 
808
_ic_focus_out (BusInputContext       *context,
 
809
               GVariant              *parameters,
 
810
               GDBusMethodInvocation *invocation)
823
811
{
824
 
    g_assert (BUS_IS_INPUT_CONTEXT (context));
825
 
    g_assert (message != NULL);
826
 
    g_assert (BUS_IS_CONNECTION (connection));
827
 
 
828
 
    IBusMessage *reply;
829
 
 
830
812
    if (context->capabilities & IBUS_CAP_FOCUS) {
831
813
        bus_input_context_focus_out (context);
832
 
        reply = ibus_message_new_method_return (message);
 
814
        g_dbus_method_invocation_return_value (invocation, NULL);
833
815
    }
834
816
    else {
835
 
        reply = ibus_message_new_error (message,
836
 
                                        DBUS_ERROR_FAILED,
837
 
                                        "The input context does not support focus.");
 
817
        g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
 
818
                        "The input context does not support focus.");
838
819
    }
839
 
 
840
 
    return reply;
841
820
}
842
821
 
843
 
static IBusMessage *
844
 
_ic_reset (BusInputContext  *context,
845
 
           IBusMessage      *message,
846
 
           BusConnection    *connection)
 
822
/**
 
823
 * _ic_reset:
 
824
 *
 
825
 * Implement the "Reset" method call of the org.freedesktop.IBus.InputContext interface.
 
826
 */
 
827
static void
 
828
_ic_reset (BusInputContext       *context,
 
829
           GVariant              *parameters,
 
830
           GDBusMethodInvocation *invocation)
847
831
{
848
 
    g_assert (BUS_IS_INPUT_CONTEXT (context));
849
 
    g_assert (message != NULL);
850
 
    g_assert (BUS_IS_CONNECTION (connection));
851
 
 
852
 
    IBusMessage *reply;
853
 
 
854
832
    if (context->enabled && context->engine) {
855
833
        bus_engine_proxy_reset (context->engine);
856
834
    }
857
 
 
858
 
    reply = ibus_message_new_method_return (message);
859
 
    return reply;
860
 
}
861
 
 
862
 
static IBusMessage *
863
 
_ic_set_capabilities (BusInputContext  *context,
864
 
                      IBusMessage      *message,
865
 
                      BusConnection    *connection)
866
 
{
867
 
    g_assert (BUS_IS_INPUT_CONTEXT (context));
868
 
    g_assert (message != NULL);
869
 
    g_assert (BUS_IS_CONNECTION (connection));
870
 
 
871
 
    IBusMessage *reply;
872
 
    guint caps;
873
 
    gboolean retval;
874
 
    IBusError *error;
875
 
 
876
 
    retval = ibus_message_get_args (message,
877
 
                &error,
878
 
                G_TYPE_UINT, &caps,
879
 
                G_TYPE_INVALID);
880
 
 
881
 
    if (!retval) {
882
 
        reply = ibus_message_new_error (message,
883
 
                                        error->name,
884
 
                                        error->message);
885
 
        ibus_error_free (error);
886
 
        return reply;
887
 
    }
888
 
 
889
 
    if (context->capabilities != caps) {
890
 
        context->capabilities = caps;
891
 
 
892
 
        /* If the context does not support IBUS_CAP_FOCUS, then we always assume
893
 
         * it has focus. */
894
 
        if ((caps & IBUS_CAP_FOCUS) == 0) {
895
 
            bus_input_context_focus_in (context);
896
 
        }
897
 
 
898
 
        if (context->engine) {
899
 
            bus_engine_proxy_set_capabilities (context->engine, caps);
900
 
        }
901
 
    }
902
 
 
903
 
    reply = ibus_message_new_method_return (message);
904
 
    return reply;
905
 
}
906
 
 
907
 
static IBusMessage *
908
 
_ic_property_activate (BusInputContext  *context,
909
 
                       IBusMessage      *message,
910
 
                       BusConnection    *connection)
911
 
{
912
 
    g_assert (BUS_IS_INPUT_CONTEXT (context));
913
 
    g_assert (message != NULL);
914
 
    g_assert (BUS_IS_CONNECTION (connection));
915
 
 
916
 
    IBusMessage *reply;
917
 
    gchar *prop_name;
918
 
    gint prop_state;
919
 
    gboolean retval;
920
 
    IBusError *error;
921
 
 
922
 
    retval = ibus_message_get_args (message,
923
 
                                    &error,
924
 
                                    G_TYPE_STRING, &prop_name,
925
 
                                    G_TYPE_INT, &prop_state,
926
 
                                    G_TYPE_INVALID);
927
 
 
928
 
    if (!retval) {
929
 
        reply = ibus_message_new_error (message,
930
 
                                        error->name,
931
 
                                        error->message);
932
 
        ibus_error_free (error);
933
 
        return reply;
934
 
    }
 
835
    g_dbus_method_invocation_return_value (invocation, NULL);
 
836
}
 
837
 
 
838
/**
 
839
 * _ic_set_capabilities:
 
840
 *
 
841
 * Implement the "SetCapabilities" method call of the org.freedesktop.IBus.InputContext interface.
 
842
 */
 
843
static void
 
844
_ic_set_capabilities (BusInputContext       *context,
 
845
                      GVariant              *parameters,
 
846
                      GDBusMethodInvocation *invocation)
 
847
{
 
848
    guint caps = 0;
 
849
    g_variant_get (parameters, "(u)", &caps);
 
850
 
 
851
    bus_input_context_set_capabilities (context, caps);
 
852
 
 
853
    g_dbus_method_invocation_return_value (invocation, NULL);
 
854
}
 
855
 
 
856
/**
 
857
 * _ic_property_activate:
 
858
 *
 
859
 * Implement the "PropertyActivate" method call of the org.freedesktop.IBus.InputContext interface.
 
860
 */
 
861
static void
 
862
_ic_property_activate (BusInputContext       *context,
 
863
                       GVariant              *parameters,
 
864
                       GDBusMethodInvocation *invocation)
 
865
{
 
866
    gchar *prop_name = NULL;
 
867
    guint prop_state = 0;
 
868
    g_variant_get (parameters, "(&su)", &prop_name, &prop_state);
935
869
 
936
870
    if (context->enabled && context->engine) {
937
871
        bus_engine_proxy_property_activate (context->engine, prop_name, prop_state);
938
872
    }
 
873
 
939
874
#ifdef OS_CHROMEOS
940
875
    /* Global engine is always enabled in chromeos,
941
876
     * so pass PropertyActivate signal to the focused context.
942
877
     */
943
 
    else {
944
 
        if (context->fake &&
945
 
            BUS_DEFAULT_IBUS->focused_context &&
946
 
            BUS_DEFAULT_IBUS->focused_context->engine) {
947
 
            bus_engine_proxy_property_activate (BUS_DEFAULT_IBUS->focused_context->engine, prop_name, prop_state);
948
 
        }
 
878
    else if (context->fake) {
 
879
        BusInputContext *focused_context = bus_ibus_impl_get_focused_input_context (BUS_DEFAULT_IBUS);
 
880
        if (focused_context && focused_context->engine)
 
881
            bus_engine_proxy_property_activate (focused_context->engine, prop_name, prop_state);
949
882
    }
950
883
#endif
951
884
 
952
 
    reply = ibus_message_new_method_return (message);
953
 
    return reply;
 
885
    g_dbus_method_invocation_return_value (invocation, NULL);
954
886
}
955
887
 
956
 
static IBusMessage *
957
 
_ic_enable (BusInputContext *context,
958
 
            IBusMessage     *message,
959
 
            BusConnection   *connection)
 
888
/**
 
889
 * _ic_enable:
 
890
 *
 
891
 * Implement the "Enable" method call of the org.freedesktop.IBus.InputContext interface.
 
892
 */
 
893
static void
 
894
_ic_enable (BusInputContext       *context,
 
895
            GVariant              *parameters,
 
896
            GDBusMethodInvocation *invocation)
960
897
{
961
 
    g_assert (BUS_IS_INPUT_CONTEXT (context));
962
 
    g_assert (message != NULL);
963
 
    g_assert (BUS_IS_CONNECTION (connection));
964
 
 
965
 
    IBusMessage *reply;
966
 
 
967
898
    bus_input_context_enable (context);
968
 
 
969
 
    reply = ibus_message_new_method_return (message);
970
 
    return reply;
 
899
    g_dbus_method_invocation_return_value (invocation, NULL);
971
900
}
972
901
 
973
 
static IBusMessage *
974
 
_ic_disable (BusInputContext *context,
975
 
            IBusMessage     *message,
976
 
            BusConnection   *connection)
 
902
/**
 
903
 * _ic_disable:
 
904
 *
 
905
 * Implement the "Disable" method call of the org.freedesktop.IBus.InputContext interface.
 
906
 */
 
907
static void
 
908
_ic_disable (BusInputContext       *context,
 
909
             GVariant              *parameters,
 
910
             GDBusMethodInvocation *invocation)
977
911
{
978
 
    g_assert (BUS_IS_INPUT_CONTEXT (context));
979
 
    g_assert (message != NULL);
980
 
    g_assert (BUS_IS_CONNECTION (connection));
981
 
 
982
 
    IBusMessage *reply;
983
 
 
984
912
    bus_input_context_disable (context);
985
 
 
986
 
    reply = ibus_message_new_method_return (message);
987
 
    return reply;
988
 
}
989
 
 
990
 
static IBusMessage *
991
 
_ic_is_enabled (BusInputContext *context,
992
 
                IBusMessage     *message,
993
 
                BusConnection   *connection)
994
 
{
995
 
    g_assert (BUS_IS_INPUT_CONTEXT (context));
996
 
    g_assert (message != NULL);
997
 
    g_assert (BUS_IS_CONNECTION (connection));
998
 
 
999
 
    IBusMessage *reply;
1000
 
 
1001
 
    reply = ibus_message_new_method_return (message);
1002
 
    ibus_message_append_args (reply,
1003
 
            G_TYPE_BOOLEAN, &context->enabled,
1004
 
            G_TYPE_INVALID);
1005
 
 
1006
 
    return reply;
1007
 
}
1008
 
 
1009
 
static IBusMessage *
1010
 
_ic_set_engine (BusInputContext  *context,
1011
 
                 IBusMessage      *message,
1012
 
                 BusConnection    *connection)
1013
 
{
1014
 
    g_assert (BUS_IS_INPUT_CONTEXT (context));
1015
 
    g_assert (message != NULL);
1016
 
    g_assert (BUS_IS_CONNECTION (connection));
1017
 
 
1018
 
    gboolean retval;
1019
 
    IBusMessage *reply;
1020
 
    IBusError *error;
1021
 
    gchar *engine_name;
1022
 
 
1023
 
    retval = ibus_message_get_args (message,
1024
 
                                    &error,
1025
 
                                    G_TYPE_STRING, &engine_name,
1026
 
                                    G_TYPE_INVALID);
1027
 
     if (!retval) {
1028
 
        reply = ibus_message_new_error (message,
1029
 
                                        error->name,
1030
 
                                        error->message);
1031
 
        ibus_error_free (error);
1032
 
        return reply;
1033
 
    }
1034
 
 
1035
 
    g_signal_emit (context, context_signals[REQUEST_ENGINE], 0, engine_name);
1036
 
 
1037
 
    if (context->engine == NULL) {
1038
 
        reply = ibus_message_new_error_printf (message,
1039
 
                                               "org.freedesktop.IBus.NoEngine",
1040
 
                                               "can not find engine with name %s",
1041
 
                                               engine_name);
1042
 
        return reply;
1043
 
    }
1044
 
 
1045
 
    bus_input_context_enable (context);
1046
 
 
1047
 
    reply = ibus_message_new_method_return (message);
1048
 
    return reply;
1049
 
}
1050
 
 
1051
 
static IBusMessage *
1052
 
_ic_get_engine (BusInputContext  *context,
1053
 
                IBusMessage      *message,
1054
 
                BusConnection    *connection)
1055
 
{
1056
 
    g_assert (BUS_IS_INPUT_CONTEXT (context));
1057
 
    g_assert (message != NULL);
1058
 
    g_assert (BUS_IS_CONNECTION (connection));
1059
 
 
1060
 
    IBusMessage *reply;
1061
 
    IBusEngineDesc *desc;
1062
 
 
 
913
    g_dbus_method_invocation_return_value (invocation, NULL);
 
914
}
 
915
 
 
916
/**
 
917
 * _ic_is_enabled:
 
918
 *
 
919
 * Implement the "IsEnabled" method call of the org.freedesktop.IBus.InputContext interface.
 
920
 */
 
921
static void
 
922
_ic_is_enabled (BusInputContext       *context,
 
923
                GVariant              *parameters,
 
924
                GDBusMethodInvocation *invocation)
 
925
{
 
926
    g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", context->enabled));
 
927
}
 
928
 
 
929
static void
 
930
_ic_set_engine_done (BusInputContext       *context,
 
931
                     GAsyncResult          *res,
 
932
                     GDBusMethodInvocation *invocation)
 
933
{
 
934
    gboolean retval = FALSE;
 
935
    GError *error = NULL;
 
936
 
 
937
    retval = bus_input_context_set_engine_by_desc_finish (context,
 
938
                    res, &error);
 
939
 
 
940
    if (!retval) {
 
941
        g_dbus_method_invocation_return_gerror (invocation, error);
 
942
        g_error_free (error);
 
943
    }
 
944
    else {
 
945
        g_dbus_method_invocation_return_value (invocation, NULL);
 
946
    }
 
947
}
 
948
 
 
949
/**
 
950
 * _ic_set_engine:
 
951
 *
 
952
 * Implement the "SetEngine" method call of the org.freedesktop.IBus.InputContext interface.
 
953
 */
 
954
static void
 
955
_ic_set_engine (BusInputContext       *context,
 
956
                GVariant              *parameters,
 
957
                GDBusMethodInvocation *invocation)
 
958
{
 
959
    gchar *engine_name = NULL;
 
960
    g_variant_get (parameters, "(&s)", &engine_name);
 
961
 
 
962
    if (!bus_input_context_has_focus (context)) {
 
963
        g_dbus_method_invocation_return_error (invocation,
 
964
                G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
 
965
                "Context which does not has focus can not change engine to %s.",
 
966
                engine_name);
 
967
        return;
 
968
    }
 
969
 
 
970
    IBusEngineDesc *desc = NULL;
 
971
    g_signal_emit (context,
 
972
                   context_signals[REQUEST_ENGINE], 0,
 
973
                   engine_name,
 
974
                   &desc);
 
975
    if (desc == NULL) {
 
976
        g_dbus_method_invocation_return_error (invocation,
 
977
                        G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
 
978
                        "Can not find engine %s.", engine_name);
 
979
        return;
 
980
    }
 
981
 
 
982
    bus_input_context_set_engine_by_desc (context,
 
983
                            desc,
 
984
                            g_gdbus_timeout,
 
985
                            NULL,
 
986
                            (GAsyncReadyCallback)_ic_set_engine_done,
 
987
                            invocation);
 
988
 
 
989
    g_object_unref (desc);
 
990
}
 
991
 
 
992
/**
 
993
 * _ic_get_engine:
 
994
 *
 
995
 * Implement the "GetEngine" method call of the org.freedesktop.IBus.InputContext interface.
 
996
 */
 
997
static void
 
998
_ic_get_engine (BusInputContext       *context,
 
999
                GVariant              *parameters,
 
1000
                GDBusMethodInvocation *invocation)
 
1001
{
1063
1002
    if (context->engine) {
1064
 
        desc = bus_engine_proxy_get_desc (context->engine);
1065
 
        if (desc != NULL) {
1066
 
            reply = ibus_message_new_method_return (message);
1067
 
            ibus_message_append_args (reply,
1068
 
                                      IBUS_TYPE_ENGINE_DESC, &desc,
1069
 
                                      G_TYPE_INVALID);
1070
 
            return reply;
1071
 
        }
1072
 
    }
1073
 
 
1074
 
    reply = ibus_message_new_error (message,
1075
 
                                    DBUS_ERROR_FAILED,
1076
 
                                    "InputContext does not have factory.");
1077
 
    return reply;
1078
 
}
1079
 
 
1080
 
static IBusMessage *
1081
 
_ic_destroy (BusInputContext  *context,
1082
 
             IBusMessage      *message,
1083
 
             BusConnection    *connection)
1084
 
{
1085
 
    g_assert (BUS_IS_INPUT_CONTEXT (context));
1086
 
    g_assert (message != NULL);
1087
 
    g_assert (BUS_IS_CONNECTION (connection));
1088
 
 
1089
 
    IBusMessage *reply;
1090
 
    reply = ibus_message_new_method_return (message);
1091
 
 
1092
 
    ibus_connection_send ((IBusConnection *) connection, reply);
1093
 
    ibus_connection_flush ((IBusConnection *) connection);
1094
 
    ibus_message_unref (reply);
1095
 
 
1096
 
    ibus_object_destroy ((IBusObject *) context);
1097
 
 
1098
 
    return NULL;
1099
 
}
1100
 
 
1101
 
static gboolean
1102
 
bus_input_context_ibus_message (BusInputContext *context,
1103
 
                                BusConnection   *connection,
1104
 
                                IBusMessage     *message)
1105
 
{
1106
 
    g_assert (BUS_IS_INPUT_CONTEXT (context));
1107
 
    g_assert (BUS_IS_CONNECTION (connection));
1108
 
    g_assert (message != NULL);
1109
 
 
1110
 
    gint i;
1111
 
    IBusMessage *reply_message = NULL;
 
1003
        IBusEngineDesc *desc = bus_engine_proxy_get_desc (context->engine);
 
1004
        g_dbus_method_invocation_return_value (invocation,
 
1005
                        g_variant_new ("(v)", ibus_serializable_serialize ((IBusSerializable *)desc)));
 
1006
    }
 
1007
    else {
 
1008
        g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
 
1009
                        "Input context does not have engine.");
 
1010
    }
 
1011
}
 
1012
 
 
1013
/**
 
1014
 * bus_input_context_service_method_call:
 
1015
 *
 
1016
 * Handle a D-Bus method call whose destination and interface name are both "org.freedesktop.IBus.InputContext"
 
1017
 */
 
1018
static void
 
1019
_ic_set_surrounding_text (BusInputContext       *context,
 
1020
                          GVariant              *parameters,
 
1021
                          GDBusMethodInvocation *invocation)
 
1022
{
 
1023
    GVariant *variant = NULL;
 
1024
    IBusText *text;
 
1025
    guint cursor_pos = 0;
 
1026
 
 
1027
    g_variant_get (parameters, "(vu)", &variant, &cursor_pos);
 
1028
    text = IBUS_TEXT (ibus_serializable_deserialize (variant));
 
1029
    g_variant_unref (variant);
 
1030
 
 
1031
    if ((context->capabilities & IBUS_CAP_SURROUNDING_TEXT) &&
 
1032
         context->has_focus && context->enabled && context->engine) {
 
1033
        bus_engine_proxy_set_surrounding_text (context->engine,
 
1034
                                               text,
 
1035
                                               cursor_pos);
 
1036
    }
 
1037
 
 
1038
    if (g_object_is_floating (text))
 
1039
        g_object_unref (text);
 
1040
 
 
1041
    g_dbus_method_invocation_return_value (invocation, NULL);
 
1042
}
 
1043
 
 
1044
static void
 
1045
bus_input_context_service_method_call (IBusService            *service,
 
1046
                                       GDBusConnection        *connection,
 
1047
                                       const gchar            *sender,
 
1048
                                       const gchar            *object_path,
 
1049
                                       const gchar            *interface_name,
 
1050
                                       const gchar            *method_name,
 
1051
                                       GVariant               *parameters,
 
1052
                                       GDBusMethodInvocation  *invocation)
 
1053
{
 
1054
    if (g_strcmp0 (interface_name, "org.freedesktop.IBus.InputContext") != 0) {
 
1055
        IBUS_SERVICE_CLASS (bus_input_context_parent_class)->service_method_call (
 
1056
                        service,
 
1057
                        connection,
 
1058
                        sender,
 
1059
                        object_path,
 
1060
                        interface_name,
 
1061
                        method_name,
 
1062
                        parameters,
 
1063
                        invocation);
 
1064
        return;
 
1065
    }
1112
1066
 
1113
1067
    static const struct {
1114
 
        const gchar *interface;
1115
 
        const gchar *name;
1116
 
        IBusMessage *(* handler) (BusInputContext *, IBusMessage *, BusConnection *);
1117
 
    } handlers[] =  {
1118
 
        /* Introspectable interface */
1119
 
        { DBUS_INTERFACE_INTROSPECTABLE,
1120
 
                               "Introspect", _ibus_introspect },
1121
 
        /* IBus interface */
1122
 
        { IBUS_INTERFACE_INPUT_CONTEXT, "ProcessKeyEvent",   _ic_process_key_event },
1123
 
        { IBUS_INTERFACE_INPUT_CONTEXT, "SetCursorLocation", _ic_set_cursor_location },
1124
 
        { IBUS_INTERFACE_INPUT_CONTEXT, "FocusIn",           _ic_focus_in },
1125
 
        { IBUS_INTERFACE_INPUT_CONTEXT, "FocusOut",          _ic_focus_out },
1126
 
        { IBUS_INTERFACE_INPUT_CONTEXT, "Reset",             _ic_reset },
1127
 
        { IBUS_INTERFACE_INPUT_CONTEXT, "SetCapabilities",   _ic_set_capabilities },
1128
 
        { IBUS_INTERFACE_INPUT_CONTEXT, "PropertyActivate",  _ic_property_activate },
1129
 
        { IBUS_INTERFACE_INPUT_CONTEXT, "Enable",            _ic_enable },
1130
 
        { IBUS_INTERFACE_INPUT_CONTEXT, "Disable",           _ic_disable },
1131
 
        { IBUS_INTERFACE_INPUT_CONTEXT, "IsEnabled",         _ic_is_enabled },
1132
 
        { IBUS_INTERFACE_INPUT_CONTEXT, "SetEngine",         _ic_set_engine },
1133
 
        { IBUS_INTERFACE_INPUT_CONTEXT, "GetEngine",         _ic_get_engine },
1134
 
        { IBUS_INTERFACE_INPUT_CONTEXT, "Destroy",           _ic_destroy },
 
1068
        const gchar *method_name;
 
1069
        void (* method_callback) (BusInputContext *, GVariant *, GDBusMethodInvocation *);
 
1070
    } methods [] =  {
 
1071
        { "ProcessKeyEvent",   _ic_process_key_event },
 
1072
        { "SetCursorLocation", _ic_set_cursor_location },
 
1073
        { "FocusIn",           _ic_focus_in },
 
1074
        { "FocusOut",          _ic_focus_out },
 
1075
        { "Reset",             _ic_reset },
 
1076
        { "SetCapabilities",   _ic_set_capabilities },
 
1077
        { "PropertyActivate",  _ic_property_activate },
 
1078
        { "Enable",            _ic_enable },
 
1079
        { "Disable",           _ic_disable },
 
1080
        { "IsEnabled",         _ic_is_enabled },
 
1081
        { "SetEngine",         _ic_set_engine },
 
1082
        { "GetEngine",         _ic_get_engine },
 
1083
        { "SetSurroundingText", _ic_set_surrounding_text},
1135
1084
    };
1136
1085
 
1137
 
    ibus_message_set_sender (message, bus_connection_get_unique_name (connection));
1138
 
    ibus_message_set_destination (message, DBUS_SERVICE_DBUS);
1139
 
 
1140
 
    for (i = 0; i < G_N_ELEMENTS (handlers); i++) {
1141
 
        if (ibus_message_is_method_call (message,
1142
 
                                         handlers[i].interface,
1143
 
                                         handlers[i].name)) {
1144
 
 
1145
 
            reply_message = handlers[i].handler (context, message, connection);
1146
 
            if (reply_message) {
1147
 
 
1148
 
                ibus_message_set_sender (reply_message,
1149
 
                                         DBUS_SERVICE_DBUS);
1150
 
                ibus_message_set_destination (reply_message,
1151
 
                                              bus_connection_get_unique_name (connection));
1152
 
                ibus_message_set_no_reply (reply_message, TRUE);
1153
 
 
1154
 
                ibus_connection_send (IBUS_CONNECTION (connection), reply_message);
1155
 
                ibus_message_unref (reply_message);
1156
 
            }
1157
 
 
1158
 
            g_signal_stop_emission_by_name (context, "ibus-message");
1159
 
            return TRUE;
 
1086
    gint i;
 
1087
    for (i = 0; i < G_N_ELEMENTS (methods); i++) {
 
1088
        if (g_strcmp0 (method_name, methods[i].method_name) == 0) {
 
1089
            methods[i].method_callback ((BusInputContext *)service, parameters, invocation);
 
1090
            return;
1160
1091
        }
1161
1092
    }
1162
1093
 
1163
 
    return IBUS_SERVICE_CLASS (bus_input_context_parent_class)->ibus_message (
1164
 
                                (IBusService *)context,
1165
 
                                (IBusConnection *)connection,
1166
 
                                message);
 
1094
    g_return_if_reached ();
1167
1095
}
1168
1096
 
1169
 
 
1170
1097
gboolean
1171
1098
bus_input_context_has_focus (BusInputContext *context)
1172
1099
{
1185
1112
 
1186
1113
    context->has_focus = TRUE;
1187
1114
 
1188
 
    // To make sure that we won't use an old value left before we losing focus
1189
 
    // last time.
 
1115
    /* To make sure that we won't use an old value left before we losing focus
 
1116
     * last time. */
1190
1117
    context->prev_keyval = IBUS_VoidSymbol;
1191
1118
    context->prev_modifiers = 0;
1192
1119
 
1193
1120
    if (context->engine == NULL && context->enabled) {
1194
 
        g_signal_emit (context, context_signals[REQUEST_ENGINE], 0, NULL);
 
1121
        /* request an engine, e.g. a global engine if the feature is enabled. */
 
1122
        IBusEngineDesc *desc = NULL;
 
1123
        g_signal_emit (context,
 
1124
                       context_signals[REQUEST_ENGINE], 0,
 
1125
                       NULL,
 
1126
                       &desc);
 
1127
 
 
1128
        if (desc != NULL) {
 
1129
            bus_input_context_set_engine_by_desc (context,
 
1130
                            desc,
 
1131
                            g_gdbus_timeout, /* timeout in msec. */
 
1132
                            NULL, /* we do not cancel the call. */
 
1133
                            NULL, /* use the default callback function. */
 
1134
                            NULL);
 
1135
            g_object_unref (desc);
 
1136
        }
1195
1137
    }
1196
1138
 
1197
1139
    if (context->engine && context->enabled) {
1204
1146
    if (context->capabilities & IBUS_CAP_FOCUS) {
1205
1147
        g_signal_emit (context, context_signals[FOCUS_IN], 0);
1206
1148
        if (context->engine && context->enabled) {
1207
 
          if (context->preedit_visible && !PREEDIT_CONDITION) {
 
1149
            /* if necessary, emit glib signals to the context object to update panel status. see the comment for PREEDIT_CONDITION
 
1150
             * for details. */
 
1151
            if (context->preedit_visible && !PREEDIT_CONDITION) {
1208
1152
                g_signal_emit (context,
1209
1153
                               context_signals[UPDATE_PREEDIT_TEXT],
1210
1154
                               0,
1230
1174
    }
1231
1175
}
1232
1176
 
 
1177
/**
 
1178
 * bus_input_context_clear_preedit_text:
 
1179
 *
 
1180
 * Clear context->preedit_text. If the preedit mode is IBUS_ENGINE_PREEDIT_COMMIT, commit it before clearing.
 
1181
 */
1233
1182
static void
1234
1183
bus_input_context_clear_preedit_text (BusInputContext *context)
1235
1184
{
1280
1229
        }                                                                   \
1281
1230
    }
1282
1231
 
1283
 
DEFINE_FUNC(page_up)
1284
 
DEFINE_FUNC(page_down)
1285
 
DEFINE_FUNC(cursor_up)
1286
 
DEFINE_FUNC(cursor_down)
 
1232
DEFINE_FUNC (page_up)
 
1233
DEFINE_FUNC (page_down)
 
1234
DEFINE_FUNC (cursor_up)
 
1235
DEFINE_FUNC (cursor_down)
1287
1236
 
1288
1237
#undef DEFINE_FUNC
1289
1238
 
1327
1276
    if (text == text_empty || text == NULL)
1328
1277
        return;
1329
1278
 
1330
 
    bus_input_context_send_signal (context,
 
1279
    GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)text);
 
1280
    bus_input_context_emit_signal (context,
1331
1281
                                   "CommitText",
1332
 
                                   IBUS_TYPE_TEXT, &text,
1333
 
                                   G_TYPE_INVALID);
 
1282
                                   g_variant_new ("(v)", variant),
 
1283
                                   NULL);
1334
1284
}
1335
1285
 
 
1286
/**
 
1287
 * bus_input_context_update_preedit_text:
 
1288
 *
 
1289
 * Update a preedit text. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
 
1290
 */
1336
1291
static void
1337
1292
bus_input_context_update_preedit_text (BusInputContext *context,
1338
1293
                                       IBusText        *text,
1352
1307
    context->preedit_mode = mode;
1353
1308
 
1354
1309
    if (PREEDIT_CONDITION) {
1355
 
        bus_input_context_send_signal (context,
 
1310
        GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)context->preedit_text);
 
1311
        bus_input_context_emit_signal (context,
1356
1312
                                       "UpdatePreeditText",
1357
 
                                       IBUS_TYPE_TEXT, &(context->preedit_text),
1358
 
                                       G_TYPE_UINT, &(context->preedit_cursor_pos),
1359
 
                                       G_TYPE_BOOLEAN, &(context->preedit_visible),
1360
 
                                       G_TYPE_INVALID);
 
1313
                                       g_variant_new ("(vub)", variant, context->preedit_cursor_pos, context->preedit_visible),
 
1314
                                       NULL);
1361
1315
    }
1362
1316
    else {
1363
1317
        g_signal_emit (context,
1369
1323
    }
1370
1324
}
1371
1325
 
 
1326
/**
 
1327
 * bus_input_context_show_preedit_text:
 
1328
 *
 
1329
 * Show a preedit text. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
 
1330
 */
1372
1331
static void
1373
1332
bus_input_context_show_preedit_text (BusInputContext *context)
1374
1333
{
1381
1340
    context->preedit_visible = TRUE;
1382
1341
 
1383
1342
    if (PREEDIT_CONDITION) {
1384
 
        bus_input_context_send_signal (context,
 
1343
        bus_input_context_emit_signal (context,
1385
1344
                                       "ShowPreeditText",
1386
 
                                       G_TYPE_INVALID);
 
1345
                                       NULL,
 
1346
                                       NULL);
1387
1347
    }
1388
1348
    else {
1389
1349
        g_signal_emit (context,
1392
1352
    }
1393
1353
}
1394
1354
 
 
1355
/**
 
1356
 * bus_input_context_hide_preedit_text:
 
1357
 *
 
1358
 * Hide a preedit text. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
 
1359
 */
1395
1360
static void
1396
1361
bus_input_context_hide_preedit_text (BusInputContext *context)
1397
1362
{
1404
1369
    context->preedit_visible = FALSE;
1405
1370
 
1406
1371
    if (PREEDIT_CONDITION) {
1407
 
        bus_input_context_send_signal (context,
 
1372
        bus_input_context_emit_signal (context,
1408
1373
                                       "HidePreeditText",
1409
 
                                       G_TYPE_INVALID);
 
1374
                                       NULL,
 
1375
                                       NULL);
1410
1376
    }
1411
1377
    else {
1412
1378
        g_signal_emit (context,
1415
1381
    }
1416
1382
}
1417
1383
 
 
1384
/**
 
1385
 * bus_input_context_update_auxiliary_text:
 
1386
 *
 
1387
 * Update an aux text. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
 
1388
 */
1418
1389
static void
1419
1390
bus_input_context_update_auxiliary_text (BusInputContext *context,
1420
1391
                                         IBusText        *text,
1430
1401
    context->auxiliary_visible = visible;
1431
1402
 
1432
1403
    if (context->capabilities & IBUS_CAP_AUXILIARY_TEXT) {
1433
 
        bus_input_context_send_signal (context,
 
1404
        GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)text);
 
1405
        bus_input_context_emit_signal (context,
1434
1406
                                       "UpdateAuxiliaryText",
1435
 
                                       IBUS_TYPE_TEXT, &(context->auxiliary_text),
1436
 
                                       G_TYPE_BOOLEAN, &(context->auxiliary_visible),
1437
 
                                       G_TYPE_INVALID);
 
1407
                                       g_variant_new ("(vb)", variant, visible),
 
1408
                                       NULL);
1438
1409
    }
1439
1410
    else {
1440
1411
        g_signal_emit (context,
1445
1416
    }
1446
1417
}
1447
1418
 
 
1419
/**
 
1420
 * bus_input_context_show_auxiliary_text:
 
1421
 *
 
1422
 * Show an aux text. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
 
1423
 */
1448
1424
static void
1449
1425
bus_input_context_show_auxiliary_text (BusInputContext *context)
1450
1426
{
1457
1433
    context->auxiliary_visible = TRUE;
1458
1434
 
1459
1435
    if ((context->capabilities & IBUS_CAP_AUXILIARY_TEXT) == IBUS_CAP_AUXILIARY_TEXT) {
1460
 
        bus_input_context_send_signal (context,
 
1436
        bus_input_context_emit_signal (context,
1461
1437
                                       "ShowAuxiliaryText",
1462
 
                                       G_TYPE_INVALID);
 
1438
                                       NULL,
 
1439
                                       NULL);
1463
1440
    }
1464
1441
    else {
1465
1442
        g_signal_emit (context,
1468
1445
    }
1469
1446
}
1470
1447
 
 
1448
/**
 
1449
 * bus_input_context_hide_auxiliary_text:
 
1450
 *
 
1451
 * Hide an aux text. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
 
1452
 */
1471
1453
static void
1472
1454
bus_input_context_hide_auxiliary_text (BusInputContext *context)
1473
1455
{
1480
1462
    context->auxiliary_visible = FALSE;
1481
1463
 
1482
1464
    if ((context->capabilities & IBUS_CAP_AUXILIARY_TEXT) == IBUS_CAP_AUXILIARY_TEXT) {
1483
 
        bus_input_context_send_signal (context,
 
1465
        bus_input_context_emit_signal (context,
1484
1466
                                       "HideAuxiliaryText",
1485
 
                                       G_TYPE_INVALID);
 
1467
                                       NULL,
 
1468
                                       NULL);
1486
1469
    }
1487
1470
    else {
1488
1471
        g_signal_emit (context,
1491
1474
    }
1492
1475
}
1493
1476
 
 
1477
/**
 
1478
 * bus_input_context_update_lookup_table:
 
1479
 *
 
1480
 * Update contents in the lookup table.
 
1481
 * Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
 
1482
 */
1494
1483
static void
1495
1484
bus_input_context_update_lookup_table (BusInputContext *context,
1496
1485
                                       IBusLookupTable *table,
1506
1495
    context->lookup_table_visible = visible;
1507
1496
 
1508
1497
    if (context->capabilities & IBUS_CAP_LOOKUP_TABLE) {
1509
 
        bus_input_context_send_signal (context,
 
1498
        GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)table);
 
1499
        bus_input_context_emit_signal (context,
1510
1500
                                       "UpdateLookupTable",
1511
 
                                       IBUS_TYPE_LOOKUP_TABLE, &(context->lookup_table),
1512
 
                                       G_TYPE_BOOLEAN, &(context->lookup_table_visible),
1513
 
                                       G_TYPE_INVALID);
 
1501
                                       g_variant_new ("(vb)", variant, visible),
 
1502
                                       NULL);
1514
1503
    }
1515
1504
    else {
1516
1505
        g_signal_emit (context,
1521
1510
    }
1522
1511
}
1523
1512
 
 
1513
/**
 
1514
 * bus_input_context_show_lookup_table:
 
1515
 *
 
1516
 * Show the lookup table. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
 
1517
 */
1524
1518
static void
1525
1519
bus_input_context_show_lookup_table (BusInputContext *context)
1526
1520
{
1533
1527
    context->lookup_table_visible = TRUE;
1534
1528
 
1535
1529
    if ((context->capabilities & IBUS_CAP_LOOKUP_TABLE) == IBUS_CAP_LOOKUP_TABLE) {
1536
 
        bus_input_context_send_signal (context,
 
1530
        bus_input_context_emit_signal (context,
1537
1531
                                       "ShowLookupTable",
1538
 
                                       G_TYPE_INVALID);
 
1532
                                       NULL,
 
1533
                                       NULL);
1539
1534
    }
1540
1535
    else {
1541
1536
        g_signal_emit (context,
1544
1539
    }
1545
1540
}
1546
1541
 
 
1542
/**
 
1543
 * bus_input_context_hide_lookup_table:
 
1544
 *
 
1545
 * Hide the lookup table. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
 
1546
 */
1547
1547
static void
1548
1548
bus_input_context_hide_lookup_table (BusInputContext *context)
1549
1549
{
1556
1556
    context->lookup_table_visible = FALSE;
1557
1557
 
1558
1558
    if ((context->capabilities & IBUS_CAP_LOOKUP_TABLE) == IBUS_CAP_LOOKUP_TABLE) {
1559
 
        bus_input_context_send_signal (context,
 
1559
        bus_input_context_emit_signal (context,
1560
1560
                                       "HideLookupTable",
1561
 
                                       G_TYPE_INVALID);
 
1561
                                       NULL,
 
1562
                                       NULL);
1562
1563
    }
1563
1564
    else {
1564
1565
        g_signal_emit (context,
1567
1568
    }
1568
1569
}
1569
1570
 
 
1571
/**
 
1572
 * bus_input_context_page_up_lookup_table:
 
1573
 *
 
1574
 * Change cursor position. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
 
1575
 */
1570
1576
static void
1571
1577
bus_input_context_page_up_lookup_table (BusInputContext *context)
1572
1578
{
1577
1583
    }
1578
1584
 
1579
1585
    if ((context->capabilities & IBUS_CAP_LOOKUP_TABLE) == IBUS_CAP_LOOKUP_TABLE) {
1580
 
        bus_input_context_send_signal (context,
 
1586
        bus_input_context_emit_signal (context,
1581
1587
                                       "PageUpLookupTable",
1582
 
                                       G_TYPE_INVALID);
 
1588
                                       NULL,
 
1589
                                       NULL);
1583
1590
    }
1584
1591
    else {
1585
1592
        g_signal_emit (context,
1588
1595
    }
1589
1596
}
1590
1597
 
 
1598
/**
 
1599
 * bus_input_context_page_down_lookup_table:
 
1600
 *
 
1601
 * Change cursor position. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
 
1602
 */
1591
1603
static void
1592
1604
bus_input_context_page_down_lookup_table (BusInputContext *context)
1593
1605
{
1598
1610
    }
1599
1611
 
1600
1612
    if ((context->capabilities & IBUS_CAP_LOOKUP_TABLE) == IBUS_CAP_LOOKUP_TABLE) {
1601
 
        bus_input_context_send_signal (context,
 
1613
        bus_input_context_emit_signal (context,
1602
1614
                                       "PageDownLookupTable",
1603
 
                                       G_TYPE_INVALID);
 
1615
                                       NULL,
 
1616
                                       NULL);
1604
1617
    }
1605
1618
    else {
1606
1619
        g_signal_emit (context,
1609
1622
    }
1610
1623
}
1611
1624
 
 
1625
/**
 
1626
 * bus_input_context_cursor_up_lookup_table:
 
1627
 *
 
1628
 * Change cursor position. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
 
1629
 */
1612
1630
static void
1613
1631
bus_input_context_cursor_up_lookup_table (BusInputContext *context)
1614
1632
{
1619
1637
    }
1620
1638
 
1621
1639
    if ((context->capabilities & IBUS_CAP_LOOKUP_TABLE) == IBUS_CAP_LOOKUP_TABLE) {
1622
 
        bus_input_context_send_signal (context,
 
1640
        bus_input_context_emit_signal (context,
1623
1641
                                       "CursorUpLookupTable",
1624
 
                                       G_TYPE_INVALID);
 
1642
                                       NULL,
 
1643
                                       NULL);
1625
1644
    }
1626
1645
    else {
1627
1646
        g_signal_emit (context,
1630
1649
    }
1631
1650
}
1632
1651
 
 
1652
/**
 
1653
 * bus_input_context_cursor_down_lookup_table:
 
1654
 *
 
1655
 * Change cursor position. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
 
1656
 */
1633
1657
static void
1634
1658
bus_input_context_cursor_down_lookup_table (BusInputContext *context)
1635
1659
{
1640
1664
    }
1641
1665
 
1642
1666
    if ((context->capabilities & IBUS_CAP_LOOKUP_TABLE) == IBUS_CAP_LOOKUP_TABLE) {
1643
 
        bus_input_context_send_signal (context,
 
1667
        bus_input_context_emit_signal (context,
1644
1668
                                       "CursorDownLookupTable",
1645
 
                                       G_TYPE_INVALID);
 
1669
                                       NULL,
 
1670
                                       NULL);
1646
1671
    }
1647
1672
    else {
1648
1673
        g_signal_emit (context,
1651
1676
    }
1652
1677
}
1653
1678
 
 
1679
/**
 
1680
 * bus_input_context_register_properties:
 
1681
 *
 
1682
 * Register properties. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
 
1683
 */
1654
1684
static void
1655
1685
bus_input_context_register_properties (BusInputContext *context,
1656
1686
                                       IBusPropList    *props)
1659
1689
    g_assert (IBUS_IS_PROP_LIST (props));
1660
1690
 
1661
1691
    if (context->capabilities & IBUS_CAP_PROPERTY) {
1662
 
        bus_input_context_send_signal (context,
 
1692
        GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)props);
 
1693
        bus_input_context_emit_signal (context,
1663
1694
                                       "RegisterProperties",
1664
 
                                       IBUS_TYPE_PROP_LIST, &props,
1665
 
                                       G_TYPE_INVALID);
 
1695
                                       g_variant_new ("(v)", variant),
 
1696
                                       NULL);
1666
1697
    }
1667
1698
    else {
1668
1699
        g_signal_emit (context,
1672
1703
    }
1673
1704
}
1674
1705
 
 
1706
/**
 
1707
 * bus_input_context_update_property:
 
1708
 *
 
1709
 * Update property. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
 
1710
 */
1675
1711
static void
1676
1712
bus_input_context_update_property (BusInputContext *context,
1677
1713
                                   IBusProperty    *prop)
1680
1716
    g_assert (IBUS_IS_PROPERTY (prop));
1681
1717
 
1682
1718
    if (context->capabilities & IBUS_CAP_PROPERTY) {
1683
 
        bus_input_context_send_signal (context,
 
1719
        GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)prop);
 
1720
        bus_input_context_emit_signal (context,
1684
1721
                                       "UpdateProperty",
1685
 
                                       IBUS_TYPE_PROPERTY, &prop,
1686
 
                                       G_TYPE_INVALID);
 
1722
                                       g_variant_new ("(v)", variant),
 
1723
                                       NULL);
1687
1724
    }
1688
1725
    else {
1689
1726
        g_signal_emit (context,
1693
1730
    }
1694
1731
}
1695
1732
 
 
1733
/**
 
1734
 * _engine_destroy_cb:
 
1735
 *
 
1736
 * A function to be called when "destroy" glib signal is sent to the engine object.
 
1737
 * Remove the engine from the context.
 
1738
 */
1696
1739
static void
1697
1740
_engine_destroy_cb (BusEngineProxy  *engine,
1698
1741
                    BusInputContext *context)
1705
1748
    bus_input_context_set_engine (context, NULL);
1706
1749
}
1707
1750
 
 
1751
/**
 
1752
 * _engine_commit_text_cb:
 
1753
 *
 
1754
 * A function to be called when "commit-text" glib signal is sent to the engine object.
 
1755
 */
1708
1756
static void
1709
1757
_engine_commit_text_cb (BusEngineProxy  *engine,
1710
1758
                        IBusText        *text,
1719
1767
    bus_input_context_commit_text (context, text);
1720
1768
}
1721
1769
 
 
1770
/**
 
1771
 * _engine_forward_key_event_cb:
 
1772
 *
 
1773
 * A function to be called when "forward-key-event" glib signal is sent to the engine object.
 
1774
 */
1722
1775
static void
1723
1776
_engine_forward_key_event_cb (BusEngineProxy    *engine,
1724
1777
                              guint              keyval,
1734
1787
    if (!context->enabled)
1735
1788
        return;
1736
1789
 
1737
 
    bus_input_context_send_signal (context,
 
1790
    bus_input_context_emit_signal (context,
1738
1791
                                   "ForwardKeyEvent",
1739
 
                                   G_TYPE_UINT,  &keyval,
1740
 
                                   G_TYPE_UINT,  &keycode,
1741
 
                                   G_TYPE_UINT,  &state,
1742
 
                                   G_TYPE_INVALID);
 
1792
                                   g_variant_new ("(uuu)", keyval, keycode, state),
 
1793
                                   NULL);
1743
1794
}
1744
1795
 
 
1796
/**
 
1797
 * _engine_delete_surrounding_text_cb:
 
1798
 *
 
1799
 * A function to be called when "delete-surrounding-text" glib signal is sent to the engine object.
 
1800
 */
1745
1801
static void
1746
1802
_engine_delete_surrounding_text_cb (BusEngineProxy    *engine,
1747
1803
                                    gint               offset_from_cursor,
1756
1812
    if (!context->enabled)
1757
1813
        return;
1758
1814
 
1759
 
    bus_input_context_send_signal (context,
 
1815
    bus_input_context_emit_signal (context,
1760
1816
                                   "DeleteSurroundingText",
1761
 
                                   G_TYPE_INT,   &offset_from_cursor,
1762
 
                                   G_TYPE_UINT,  &nchars,
1763
 
                                   G_TYPE_INVALID);
1764
 
}
1765
 
 
 
1817
                                   g_variant_new ("(iu)", offset_from_cursor, nchars),
 
1818
                                   NULL);
 
1819
}
 
1820
 
 
1821
/**
 
1822
 * _engine_require_surrounding_text_cb:
 
1823
 *
 
1824
 * A function to be called when "require-surrounding-text" glib signal is sent to the engine object.
 
1825
 */
 
1826
static void
 
1827
_engine_require_surrounding_text_cb (BusEngineProxy    *engine,
 
1828
                                     BusInputContext   *context)
 
1829
{
 
1830
    g_assert (BUS_IS_ENGINE_PROXY (engine));
 
1831
    g_assert (BUS_IS_INPUT_CONTEXT (context));
 
1832
 
 
1833
    g_assert (context->engine == engine);
 
1834
 
 
1835
    if (!context->enabled)
 
1836
        return;
 
1837
 
 
1838
    bus_input_context_emit_signal (context,
 
1839
                                   "RequireSurroundingText",
 
1840
                                   NULL,
 
1841
                                   NULL);
 
1842
}
 
1843
 
 
1844
/**
 
1845
 * _engine_update_preedit_text_cb:
 
1846
 *
 
1847
 * A function to be called when "update-preedit-text" glib signal is sent to the engine object.
 
1848
 */
1766
1849
static void
1767
1850
_engine_update_preedit_text_cb (BusEngineProxy  *engine,
1768
1851
                                IBusText        *text,
1783
1866
    bus_input_context_update_preedit_text (context, text, cursor_pos, visible, mode);
1784
1867
}
1785
1868
 
 
1869
/**
 
1870
 * _engine_update_auxiliary_text_cb:
 
1871
 *
 
1872
 * A function to be called when "update-auxiliary-text" glib signal is sent to the engine object.
 
1873
 */
1786
1874
static void
1787
1875
_engine_update_auxiliary_text_cb (BusEngineProxy   *engine,
1788
1876
                                  IBusText         *text,
1801
1889
    bus_input_context_update_auxiliary_text (context, text, visible);
1802
1890
}
1803
1891
 
 
1892
/**
 
1893
 * _engine_update_lookup_table_cb:
 
1894
 *
 
1895
 * A function to be called when "update-lookup-table" glib signal is sent to the engine object.
 
1896
 */
1804
1897
static void
1805
1898
_engine_update_lookup_table_cb (BusEngineProxy   *engine,
1806
1899
                                IBusLookupTable  *table,
1819
1912
    bus_input_context_update_lookup_table (context, table, visible);
1820
1913
}
1821
1914
 
 
1915
/**
 
1916
 * _engine_register_properties_cb:
 
1917
 *
 
1918
 * A function to be called when "register-properties" glib signal is sent to the engine object.
 
1919
 */
1822
1920
static void
1823
1921
_engine_register_properties_cb (BusEngineProxy  *engine,
1824
1922
                                IBusPropList    *props,
1836
1934
    bus_input_context_register_properties (context, props);
1837
1935
}
1838
1936
 
 
1937
/**
 
1938
 * _engine_update_property_cb:
 
1939
 *
 
1940
 * A function to be called when "update-property" glib signal is sent to the engine object.
 
1941
 */
1839
1942
static void
1840
1943
_engine_update_property_cb (BusEngineProxy  *engine,
1841
1944
                            IBusProperty    *prop,
1881
1984
DEFINE_FUNCTION (cursor_down_lookup_table)
1882
1985
#undef DEFINE_FUNCTION
1883
1986
 
 
1987
BusInputContext *
 
1988
bus_input_context_new (BusConnection    *connection,
 
1989
                       const gchar      *client)
 
1990
{
 
1991
    static guint id = 0;
 
1992
 
 
1993
    g_assert (connection == NULL || BUS_IS_CONNECTION (connection));
 
1994
    g_assert (client != NULL);
 
1995
 
 
1996
    gchar *path = g_strdup_printf (IBUS_PATH_INPUT_CONTEXT, ++id);
 
1997
 
 
1998
    BusInputContext *context = NULL;
 
1999
    if (connection) {
 
2000
        context = (BusInputContext *) g_object_new (BUS_TYPE_INPUT_CONTEXT,
 
2001
                                                    "object-path", path,
 
2002
                                                    "connection", bus_connection_get_dbus_connection (connection),
 
2003
                                                    NULL);
 
2004
    }
 
2005
    else {
 
2006
        context = (BusInputContext *) g_object_new (BUS_TYPE_INPUT_CONTEXT,
 
2007
                                                    "object-path", path,
 
2008
                                                    NULL);
 
2009
    }
 
2010
    g_free (path);
 
2011
 
 
2012
    context->client = g_strdup (client);
 
2013
 
 
2014
    /* it is a fake input context, just need process hotkey */
 
2015
    context->fake = (strncmp (client, "fake", 4) == 0);
 
2016
 
 
2017
    if (connection) {
 
2018
        g_object_ref_sink (connection);
 
2019
        context->connection = connection;
 
2020
        g_signal_connect (context->connection,
 
2021
                          "destroy",
 
2022
                          (GCallback) _connection_destroy_cb,
 
2023
                          context);
 
2024
    }
 
2025
 
 
2026
    return context;
 
2027
}
 
2028
 
1884
2029
void
1885
2030
bus_input_context_enable (BusInputContext *context)
1886
2031
{
1888
2033
 
1889
2034
    if (!context->has_focus) {
1890
2035
        context->enabled = TRUE;
1891
 
        /* TODO: Do we need to emit "enabled" signal? */
 
2036
        /* FIXME Do we need to emit "enabled" signal? */
1892
2037
        return;
1893
2038
    }
1894
2039
 
1895
2040
    if (context->engine == NULL) {
1896
 
        g_signal_emit (context, context_signals[REQUEST_ENGINE], 0, NULL);
 
2041
        IBusEngineDesc *desc = NULL;
 
2042
        g_signal_emit (context,
 
2043
                       context_signals[REQUEST_ENGINE], 0,
 
2044
                       NULL,
 
2045
                       &desc);
 
2046
        if (desc != NULL) {
 
2047
            bus_input_context_set_engine_by_desc (context,
 
2048
                            desc,
 
2049
                            g_gdbus_timeout, /* timeout in msec. */
 
2050
                            NULL, /* we do not cancel the call. */
 
2051
                            NULL, /* use the default callback function. */
 
2052
                            NULL);
 
2053
            g_object_unref (desc);
 
2054
        }
1897
2055
    }
1898
2056
 
1899
2057
    if (context->engine == NULL)
1901
2059
 
1902
2060
    context->enabled = TRUE;
1903
2061
 
 
2062
    bus_engine_proxy_focus_in (context->engine);
1904
2063
    bus_engine_proxy_enable (context->engine);
1905
 
    bus_engine_proxy_focus_in (context->engine);
1906
2064
    bus_engine_proxy_set_capabilities (context->engine, context->capabilities);
1907
2065
    bus_engine_proxy_set_cursor_location (context->engine, context->x, context->y, context->w, context->h);
1908
2066
 
1909
 
    bus_input_context_send_signal (context,
 
2067
    bus_input_context_emit_signal (context,
1910
2068
                                   "Enabled",
1911
 
                                   G_TYPE_INVALID);
 
2069
                                   NULL,
 
2070
                                   NULL);
1912
2071
    g_signal_emit (context,
1913
2072
                   context_signals[ENABLED],
1914
2073
                   0);
1929
2088
        bus_engine_proxy_disable (context->engine);
1930
2089
    }
1931
2090
 
1932
 
    bus_input_context_send_signal (context,
 
2091
    bus_input_context_emit_signal (context,
1933
2092
                                   "Disabled",
1934
 
                                   G_TYPE_INVALID);
 
2093
                                   NULL,
 
2094
                                   NULL);
1935
2095
    g_signal_emit (context,
1936
2096
                   context_signals[DISABLED],
1937
2097
                   0);
1947
2107
    return context->enabled;
1948
2108
}
1949
2109
 
 
2110
/* A list of signals (and their handler functions) that could be emit by the engine proxy object. */
1950
2111
const static struct {
1951
2112
    const gchar *name;
1952
2113
    GCallback    callback;
1953
 
} signals [] = {
1954
 
    { "commit-text",            G_CALLBACK (_engine_commit_text_cb) },
1955
 
    { "forward-key-event",      G_CALLBACK (_engine_forward_key_event_cb) },
1956
 
    { "delete-surrounding-text", G_CALLBACK (_engine_delete_surrounding_text_cb) },
1957
 
    { "update-preedit-text",    G_CALLBACK (_engine_update_preedit_text_cb) },
1958
 
    { "show-preedit-text",      G_CALLBACK (_engine_show_preedit_text_cb) },
1959
 
    { "hide-preedit-text",      G_CALLBACK (_engine_hide_preedit_text_cb) },
1960
 
    { "update-auxiliary-text",  G_CALLBACK (_engine_update_auxiliary_text_cb) },
1961
 
    { "show-auxiliary-text",    G_CALLBACK (_engine_show_auxiliary_text_cb) },
1962
 
    { "hide-auxiliary-text",    G_CALLBACK (_engine_hide_auxiliary_text_cb) },
1963
 
    { "update-lookup-table",    G_CALLBACK (_engine_update_lookup_table_cb) },
1964
 
    { "show-lookup-table",      G_CALLBACK (_engine_show_lookup_table_cb) },
1965
 
    { "hide-lookup-table",      G_CALLBACK (_engine_hide_lookup_table_cb) },
1966
 
    { "page-up-lookup-table",   G_CALLBACK (_engine_page_up_lookup_table_cb) },
1967
 
    { "page-down-lookup-table", G_CALLBACK (_engine_page_down_lookup_table_cb) },
1968
 
    { "cursor-up-lookup-table", G_CALLBACK (_engine_cursor_up_lookup_table_cb) },
 
2114
} engine_signals [] = {
 
2115
    { "commit-text",              G_CALLBACK (_engine_commit_text_cb) },
 
2116
    { "forward-key-event",        G_CALLBACK (_engine_forward_key_event_cb) },
 
2117
    { "delete-surrounding-text",  G_CALLBACK (_engine_delete_surrounding_text_cb) },
 
2118
    { "require-surrounding-text", G_CALLBACK (_engine_require_surrounding_text_cb) },
 
2119
    { "update-preedit-text",      G_CALLBACK (_engine_update_preedit_text_cb) },
 
2120
    { "show-preedit-text",        G_CALLBACK (_engine_show_preedit_text_cb) },
 
2121
    { "hide-preedit-text",        G_CALLBACK (_engine_hide_preedit_text_cb) },
 
2122
    { "update-auxiliary-text",    G_CALLBACK (_engine_update_auxiliary_text_cb) },
 
2123
    { "show-auxiliary-text",      G_CALLBACK (_engine_show_auxiliary_text_cb) },
 
2124
    { "hide-auxiliary-text",      G_CALLBACK (_engine_hide_auxiliary_text_cb) },
 
2125
    { "update-lookup-table",      G_CALLBACK (_engine_update_lookup_table_cb) },
 
2126
    { "show-lookup-table",        G_CALLBACK (_engine_show_lookup_table_cb) },
 
2127
    { "hide-lookup-table",        G_CALLBACK (_engine_hide_lookup_table_cb) },
 
2128
    { "page-up-lookup-table",     G_CALLBACK (_engine_page_up_lookup_table_cb) },
 
2129
    { "page-down-lookup-table",   G_CALLBACK (_engine_page_down_lookup_table_cb) },
 
2130
    { "cursor-up-lookup-table",   G_CALLBACK (_engine_cursor_up_lookup_table_cb) },
1969
2131
    { "cursor-down-lookup-table", G_CALLBACK (_engine_cursor_down_lookup_table_cb) },
1970
 
    { "register-properties",    G_CALLBACK (_engine_register_properties_cb) },
1971
 
    { "update-property",        G_CALLBACK (_engine_update_property_cb) },
1972
 
    { "destroy",                G_CALLBACK (_engine_destroy_cb) },
 
2132
    { "register-properties",      G_CALLBACK (_engine_register_properties_cb) },
 
2133
    { "update-property",          G_CALLBACK (_engine_update_property_cb) },
 
2134
    { "destroy",                  G_CALLBACK (_engine_destroy_cb) },
1973
2135
    { NULL, 0 }
1974
2136
};
1975
2137
 
1985
2147
 
1986
2148
    if (context->engine) {
1987
2149
        gint i;
1988
 
        for (i = 0; signals[i].name != NULL; i++) {
1989
 
            g_signal_handlers_disconnect_by_func (context->engine, signals[i].callback, context);
 
2150
        /* uninstall signal handlers for the engine. */
 
2151
        for (i = 0; engine_signals[i].name != NULL; i++) {
 
2152
            g_signal_handlers_disconnect_by_func (context->engine, engine_signals[i].callback, context);
1990
2153
        }
1991
2154
        /* Do not destroy the engine anymore, because of global engine feature */
1992
2155
        g_object_unref (context->engine);
2013
2176
    else {
2014
2177
        gint i;
2015
2178
        context->engine = engine;
2016
 
        g_object_ref_sink (context->engine);
 
2179
        g_object_ref (context->engine);
2017
2180
 
2018
 
        for (i = 0; signals[i].name != NULL; i++) {
 
2181
        /* handle signals from the engine. */
 
2182
        for (i = 0; engine_signals[i].name != NULL; i++) {
2019
2183
            g_signal_connect (context->engine,
2020
 
                              signals[i].name,
2021
 
                              signals[i].callback,
 
2184
                              engine_signals[i].name,
 
2185
                              engine_signals[i].callback,
2022
2186
                              context);
2023
2187
        }
2024
2188
        if (context->has_focus && context->enabled) {
2033
2197
                   0);
2034
2198
}
2035
2199
 
 
2200
static void set_engine_by_desc_data_free (SetEngineByDescData *data)
 
2201
{
 
2202
    if (data->context != NULL) {
 
2203
        if (data->context->data == data)
 
2204
            data->context->data = NULL;
 
2205
        g_object_unref (data->context);
 
2206
    }
 
2207
 
 
2208
    if (data->simple != NULL) {
 
2209
        g_object_unref (data->simple);
 
2210
    }
 
2211
 
 
2212
    if (data->cancellable != NULL)
 
2213
        g_object_unref (data->cancellable);
 
2214
 
 
2215
    if (data->origin_cancellable != NULL) {
 
2216
        if (data->cancelled_handler_id != 0)
 
2217
            g_cancellable_disconnect (data->origin_cancellable,
 
2218
                data->cancelled_handler_id);
 
2219
        g_object_unref (data->origin_cancellable);
 
2220
    }
 
2221
 
 
2222
    g_slice_free (SetEngineByDescData, data);
 
2223
}
 
2224
 
 
2225
/**
 
2226
 * new_engine_cb:
 
2227
 *
 
2228
 * A callback function to be called when bus_engine_proxy_new() is finished.
 
2229
 */
 
2230
static void
 
2231
new_engine_cb (GObject             *obj,
 
2232
               GAsyncResult        *res,
 
2233
               SetEngineByDescData *data)
 
2234
{
 
2235
    GError *error = NULL;
 
2236
    BusEngineProxy *engine = bus_engine_proxy_new_finish (res, &error);
 
2237
 
 
2238
    if (engine == NULL) {
 
2239
        g_simple_async_result_set_from_error (data->simple, error);
 
2240
        g_error_free (error);
 
2241
    }
 
2242
    else {
 
2243
        if (data->context->data != data) {
 
2244
            /* Request has been overriden or cancelled */
 
2245
            g_object_unref (engine);
 
2246
            g_simple_async_result_set_error (data->simple,
 
2247
                                             G_IO_ERROR,
 
2248
                                             G_IO_ERROR_CANCELLED,
 
2249
                                             "Opertation was cancelled");
 
2250
        }
 
2251
        else {
 
2252
            bus_input_context_set_engine (data->context, engine);
 
2253
            bus_input_context_enable (data->context);
 
2254
            g_simple_async_result_set_op_res_gboolean (data->simple, TRUE);
 
2255
        }
 
2256
    }
 
2257
 
 
2258
    /* Call the callback function for bus_input_context_set_engine_by_desc(). */
 
2259
    g_simple_async_result_complete_in_idle (data->simple);
 
2260
 
 
2261
    set_engine_by_desc_data_free (data);
 
2262
}
 
2263
 
 
2264
static void
 
2265
cancel_set_engine_by_desc (SetEngineByDescData *data)
 
2266
{
 
2267
    if (data->context->data == data)
 
2268
        data->context->data = NULL;
 
2269
 
 
2270
    if (data->origin_cancellable != NULL) {
 
2271
        if (data->cancelled_handler_id != 0) {
 
2272
            g_cancellable_disconnect (data->origin_cancellable,
 
2273
                                      data->cancelled_handler_id);
 
2274
            data->cancelled_handler_id = 0;
 
2275
        }
 
2276
 
 
2277
        g_object_unref (data->origin_cancellable);
 
2278
        data->origin_cancellable = NULL;
 
2279
    }
 
2280
 
 
2281
    if (data->cancellable != NULL) {
 
2282
        g_cancellable_cancel (data->cancellable);
 
2283
        g_object_unref (data->cancellable);
 
2284
        data->cancellable = NULL;
 
2285
    }
 
2286
}
 
2287
 
 
2288
static gboolean
 
2289
set_engine_by_desc_cancelled_idle_cb (SetEngineByDescData *data)
 
2290
{
 
2291
    cancel_set_engine_by_desc (data);
 
2292
    return FALSE;
 
2293
}
 
2294
 
 
2295
static void
 
2296
set_engine_by_desc_cancelled_cb (GCancellable        *cancellable,
 
2297
                                 SetEngineByDescData *data)
 
2298
{
 
2299
    /* Cancel in idle to avoid deadlock */
 
2300
    g_idle_add ((GSourceFunc) set_engine_by_desc_cancelled_idle_cb, data);
 
2301
}
 
2302
 
 
2303
/**
 
2304
 * set_engine_by_desc_ready_cb:
 
2305
 *
 
2306
 * A default callback function for bus_input_context_set_engine_by_desc().
 
2307
 */
 
2308
static void
 
2309
set_engine_by_desc_ready_cb (BusInputContext *context,
 
2310
                             GAsyncResult    *res,
 
2311
                             gpointer         user_data)
 
2312
{
 
2313
    GError *error = NULL;
 
2314
    if (!bus_input_context_set_engine_by_desc_finish (context, res, &error)) {
 
2315
        g_warning ("Set context engine failed: %s", error->message);
 
2316
        g_error_free (error);
 
2317
    }
 
2318
}
 
2319
 
 
2320
void
 
2321
bus_input_context_set_engine_by_desc (BusInputContext    *context,
 
2322
                                      IBusEngineDesc     *desc,
 
2323
                                      gint                timeout,
 
2324
                                      GCancellable       *cancellable,
 
2325
                                      GAsyncReadyCallback callback,
 
2326
                                      gpointer            user_data)
 
2327
{
 
2328
    g_assert (BUS_IS_INPUT_CONTEXT (context));
 
2329
    g_assert (IBUS_IS_ENGINE_DESC (desc));
 
2330
    g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
 
2331
 
 
2332
    if (context->data != NULL) {
 
2333
        /* Cancel previous set_engine_by_desc() request */
 
2334
        cancel_set_engine_by_desc (context->data);
 
2335
    }
 
2336
 
 
2337
    /* Previous request must be completed or cancelled */
 
2338
    g_assert (context->data == NULL);
 
2339
 
 
2340
    if (callback == NULL)
 
2341
        callback = (GAsyncReadyCallback) set_engine_by_desc_ready_cb;
 
2342
 
 
2343
    GSimpleAsyncResult *simple =
 
2344
            g_simple_async_result_new ((GObject *) context,
 
2345
                                       callback,
 
2346
                                       user_data,
 
2347
                                       bus_input_context_set_engine_by_desc);
 
2348
 
 
2349
    if (g_cancellable_is_cancelled (cancellable)) {
 
2350
        g_simple_async_result_set_error (simple,
 
2351
                                         G_IO_ERROR,
 
2352
                                         G_IO_ERROR_CANCELLED,
 
2353
                                         "Operation was cancelled");
 
2354
        g_simple_async_result_complete_in_idle (simple);
 
2355
        g_object_unref (simple);
 
2356
        return;
 
2357
    }
 
2358
 
 
2359
    SetEngineByDescData *data = g_slice_new0 (SetEngineByDescData);
 
2360
    context->data = data;
 
2361
    data->context = context;
 
2362
    g_object_ref (context);
 
2363
    data->simple = simple;
 
2364
 
 
2365
    if (cancellable != NULL) {
 
2366
        data->origin_cancellable = cancellable;
 
2367
        g_object_ref (cancellable);
 
2368
        data->cancelled_handler_id =
 
2369
                g_cancellable_connect (data->origin_cancellable,
 
2370
                                       (GCallback) set_engine_by_desc_cancelled_cb,
 
2371
                                       data,
 
2372
                                       NULL);
 
2373
    }
 
2374
 
 
2375
    data->cancellable = g_cancellable_new ();
 
2376
    /* We can cancel the bus_engine_proxy_new() call by data->cancellable;
 
2377
     * See cancel_set_engine_by_desc() and set_engine_by_desc_cancelled_cb(). */
 
2378
    bus_engine_proxy_new (desc,
 
2379
                          timeout,
 
2380
                          data->cancellable,
 
2381
                          (GAsyncReadyCallback) new_engine_cb,
 
2382
                          data);
 
2383
}
 
2384
 
 
2385
gboolean
 
2386
bus_input_context_set_engine_by_desc_finish (BusInputContext  *context,
 
2387
                                             GAsyncResult     *res,
 
2388
                                             GError          **error)
 
2389
{
 
2390
    GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
 
2391
 
 
2392
    g_assert (BUS_IS_INPUT_CONTEXT (context));
 
2393
    g_assert (g_simple_async_result_get_source_tag (simple) ==
 
2394
                bus_input_context_set_engine_by_desc);
 
2395
 
 
2396
    if (g_simple_async_result_propagate_error (simple, error))
 
2397
        return FALSE;
 
2398
    return TRUE;
 
2399
}
 
2400
 
2036
2401
BusEngineProxy *
2037
2402
bus_input_context_get_engine (BusInputContext *context)
2038
2403
{
2041
2406
    return context->engine;
2042
2407
}
2043
2408
 
 
2409
IBusEngineDesc *
 
2410
bus_input_context_get_engine_desc (BusInputContext *context)
 
2411
{
 
2412
    g_assert (BUS_IS_INPUT_CONTEXT (context));
 
2413
    if (context->engine)
 
2414
        return bus_engine_proxy_get_desc (context->engine);
 
2415
    return NULL;
 
2416
}
 
2417
 
2044
2418
static gboolean
2045
2419
bus_input_context_filter_keyboard_shortcuts (BusInputContext    *context,
2046
2420
                                             guint               keyval,
2052
2426
    gboolean retval = FALSE;
2053
2427
 
2054
2428
    if (context->filter_release){
2055
 
        if(modifiers & IBUS_RELEASE_MASK) {
 
2429
        if (modifiers & IBUS_RELEASE_MASK) {
2056
2430
            /* filter release key event */
2057
2431
            return TRUE;
2058
2432
        }
2062
2436
        }
2063
2437
    }
2064
2438
 
2065
 
    if (keycode != 0 && !BUS_DEFAULT_IBUS->use_sys_layout) {
2066
 
        IBusKeymap *keymap = BUS_DEFAULT_KEYMAP;
2067
 
        if (keymap != NULL) {
2068
 
            guint tmp = ibus_keymap_lookup_keysym (keymap,
2069
 
                                                 keycode,
2070
 
                                                 modifiers);
2071
 
            if (tmp != IBUS_VoidSymbol)
2072
 
                keyval = tmp;
2073
 
        }
2074
 
    }
2075
 
 
2076
2439
    retval = bus_ibus_impl_filter_keyboard_shortcuts (BUS_DEFAULT_IBUS,
2077
2440
                                                      context,
2078
2441
                                                      keyval,
2090
2453
    return retval;
2091
2454
}
2092
2455
 
2093
 
 
2094
 
static gboolean
2095
 
bus_input_context_send_signal (BusInputContext *context,
2096
 
                               const gchar     *signal_name,
2097
 
                               GType            first_arg_type,
2098
 
                               ...)
2099
 
{
2100
 
    g_assert (BUS_IS_INPUT_CONTEXT (context));
2101
 
    g_assert (signal_name != NULL);
2102
 
    g_assert (context->connection != NULL);
2103
 
 
2104
 
    va_list args;
2105
 
    gboolean retval;
2106
 
    IBusMessage *message;
2107
 
 
2108
 
    message = ibus_message_new_signal (ibus_service_get_path ((IBusService *)context),
2109
 
                                       IBUS_INTERFACE_INPUT_CONTEXT,
2110
 
                                       signal_name);
2111
 
 
2112
 
    ibus_message_set_sender (message, IBUS_SERVICE_IBUS);
2113
 
 
2114
 
    va_start (args, first_arg_type);
2115
 
    ibus_message_append_args_valist (message, first_arg_type, args);
2116
 
    va_end (args);
2117
 
 
2118
 
    retval = ibus_connection_send ((IBusConnection *)context->connection, message);
2119
 
    ibus_message_unref (message);
2120
 
 
2121
 
    return retval;
2122
 
}
2123
 
 
2124
2456
guint
2125
2457
bus_input_context_get_capabilities (BusInputContext *context)
2126
2458
{
2127
2459
    g_assert (BUS_IS_INPUT_CONTEXT (context));
2128
2460
    return context->capabilities;
2129
2461
}
 
2462
 
 
2463
void
 
2464
bus_input_context_set_capabilities (BusInputContext    *context,
 
2465
                                    guint               capabilities)
 
2466
{
 
2467
    g_assert (BUS_IS_INPUT_CONTEXT (context));
 
2468
 
 
2469
    /* If the context does not support IBUS_CAP_FOCUS, then the client application have to handle all information such as
 
2470
     * preedit and auxiliary text. */
 
2471
    if ((capabilities & IBUS_CAP_FOCUS) == 0) {
 
2472
        capabilities |= (IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_AUXILIARY_TEXT | IBUS_CAP_LOOKUP_TABLE | IBUS_CAP_PROPERTY);
 
2473
    }
 
2474
 
 
2475
    if (context->capabilities != capabilities) {
 
2476
        context->capabilities = capabilities;
 
2477
 
 
2478
        /* If the context does not support IBUS_CAP_FOCUS, then we always assume
 
2479
         * it has focus. */
 
2480
        if ((capabilities & IBUS_CAP_FOCUS) == 0) {
 
2481
            bus_input_context_focus_in (context);
 
2482
        }
 
2483
 
 
2484
        if (context->engine) {
 
2485
            bus_engine_proxy_set_capabilities (context->engine, capabilities);
 
2486
        }
 
2487
    }
 
2488
 
 
2489
    context->capabilities = capabilities;
 
2490
}
 
2491
 
 
2492
 
 
2493
const gchar *
 
2494
bus_input_context_get_client (BusInputContext *context)
 
2495
{
 
2496
    g_assert (BUS_IS_INPUT_CONTEXT (context));
 
2497
    return context->client;
 
2498
}