1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 /* vim:set et sts=4: */
3 /* ibus - The Input Bus
4 * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
5 * Copyright (C) 2018-2019 Takao Fujiwara <takao.fujiwara1@gmail.com>
6 * Copyright (C) 2008-2019 Red Hat, Inc.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
21 * USA
22 */
23 #include "ibusinputcontext.h"
24 #include <gio/gio.h>
25 #include "ibusshare.h"
26 #include "ibusinternal.h"
27 #include "ibusmarshalers.h"
28 #include "ibusattribute.h"
29 #include "ibuslookuptable.h"
30 #include "ibusproplist.h"
31 #include "ibuserror.h"
32
33 #define IBUS_INPUT_CONTEXT_GET_PRIVATE(o) \
34 ((IBusInputContextPrivate *)ibus_input_context_get_instance_private (o))
35
36 enum {
37 ENABLED,
38 DISABLED,
39 COMMIT_TEXT,
40 FORWARD_KEY_EVENT,
41 DELETE_SURROUNDING_TEXT,
42 UPDATE_PREEDIT_TEXT,
43 UPDATE_PREEDIT_TEXT_WITH_MODE,
44 SHOW_PREEDIT_TEXT,
45 HIDE_PREEDIT_TEXT,
46 UPDATE_AUXILIARY_TEXT,
47 SHOW_AUXILIARY_TEXT,
48 HIDE_AUXILIARY_TEXT,
49 UPDATE_LOOKUP_TABLE,
50 SHOW_LOOKUP_TABLE,
51 HIDE_LOOKUP_TABLE,
52 PAGE_UP_LOOKUP_TABLE,
53 PAGE_DOWN_LOOKUP_TABLE,
54 CURSOR_UP_LOOKUP_TABLE,
55 CURSOR_DOWN_LOOKUP_TABLE,
56 REGISTER_PROPERTIES,
57 UPDATE_PROPERTY,
58 LAST_SIGNAL,
59 };
60
61 /* IBusInputContextPrivate */
62 struct _IBusInputContextPrivate {
63 /* TRUE if the current engine needs surrounding text; FALSE otherwise */
64 gboolean needs_surrounding_text;
65
66 /* cached surrounding text (see also IBusEnginePrivate and
67 BusEngineProxy) */
68 IBusText *surrounding_text;
69 guint surrounding_cursor_pos;
70 guint selection_anchor_pos;
71 };
72
73 typedef struct _IBusInputContextPrivate IBusInputContextPrivate;
74
75 static guint context_signals[LAST_SIGNAL] = { 0 };
76
77 static IBusText *text_empty = NULL;
78
79 /* functions prototype */
80 static void ibus_input_context_real_destroy (IBusProxy *context);
81 static void ibus_input_context_g_signal (GDBusProxy *proxy,
82 const gchar *sender_name,
83 const gchar *signal_name,
84 GVariant *parameters);
85
G_DEFINE_TYPE_WITH_PRIVATE(IBusInputContext,ibus_input_context,IBUS_TYPE_PROXY)86 G_DEFINE_TYPE_WITH_PRIVATE (IBusInputContext,
87 ibus_input_context,
88 IBUS_TYPE_PROXY)
89
90 static void
91 ibus_input_context_class_init (IBusInputContextClass *class)
92 {
93 IBusProxyClass *ibus_proxy_class = IBUS_PROXY_CLASS (class);
94 GDBusProxyClass *g_dbus_proxy_class = G_DBUS_PROXY_CLASS (class);
95
96 ibus_proxy_class->destroy = ibus_input_context_real_destroy;
97
98 g_dbus_proxy_class->g_signal = ibus_input_context_g_signal;
99
100 /* install signals */
101 /**
102 * IBusInputContext::enabled:
103 * @context: An IBusInputContext.
104 *
105 * Emitted when an IME is enabled.
106 */
107 context_signals[ENABLED] =
108 g_signal_new (I_("enabled"),
109 G_TYPE_FROM_CLASS (class),
110 G_SIGNAL_RUN_LAST,
111 0,
112 NULL, NULL,
113 _ibus_marshal_VOID__VOID,
114 G_TYPE_NONE, 0);
115
116 /**
117 * IBusInputContext::disabled:
118 * @context: An IBusInputContext.
119 *
120 * Emitted when an IME is disabled.
121 */
122 context_signals[DISABLED] =
123 g_signal_new (I_("disabled"),
124 G_TYPE_FROM_CLASS (class),
125 G_SIGNAL_RUN_LAST,
126 0,
127 NULL, NULL,
128 _ibus_marshal_VOID__VOID,
129 G_TYPE_NONE, 0);
130
131 /**
132 * IBusInputContext::commit-text:
133 * @context: An IBusInputContext.
134 * @text: Text to be committed.
135 *
136 * Emitted when the text is going to be committed.
137 *
138 * (Note: The text object is floating, and it will be released after the
139 * signal. If signal handler wants to keep the object, the handler should
140 * use g_object_ref_sink() to get the ownership of the object.)
141 */
142 context_signals[COMMIT_TEXT] =
143 g_signal_new (I_("commit-text"),
144 G_TYPE_FROM_CLASS (class),
145 G_SIGNAL_RUN_LAST,
146 0,
147 NULL, NULL,
148 _ibus_marshal_VOID__OBJECT,
149 G_TYPE_NONE,
150 1,
151 IBUS_TYPE_TEXT);
152
153 /**
154 * IBusInputContext::forward-key-event:
155 * @context: An IBusInputContext.
156 * @keyval: Key symbol of the keyboard event.
157 * @keycode: Key symbol of the keyboard event.
158 * @modifiers: Key modifier flags.
159 *
160 * Emitted to forward key event from IME to client of IME.
161 */
162 context_signals[FORWARD_KEY_EVENT] =
163 g_signal_new (I_("forward-key-event"),
164 G_TYPE_FROM_CLASS (class),
165 G_SIGNAL_RUN_LAST,
166 0,
167 NULL, NULL,
168 _ibus_marshal_VOID__UINT_UINT_UINT,
169 G_TYPE_NONE,
170 3,
171 G_TYPE_UINT,
172 G_TYPE_UINT,
173 G_TYPE_UINT);
174
175 /**
176 * IBusInputContext::delete-surrounding-text:
177 * @context: An IBusInputContext.
178 * @offset: the character offset from the cursor position of the text to be deleted.
179 * A negative value indicates a position before the cursor.
180 * @n_chars: the number of characters to be deleted.
181 *
182 * Emitted to delete surrounding text event from IME to client of IME.
183 */
184 context_signals[DELETE_SURROUNDING_TEXT] =
185 g_signal_new (I_("delete-surrounding-text"),
186 G_TYPE_FROM_CLASS (class),
187 G_SIGNAL_RUN_LAST,
188 0,
189 NULL, NULL,
190 _ibus_marshal_VOID__INT_UINT,
191 G_TYPE_NONE,
192 2,
193 G_TYPE_INT,
194 G_TYPE_UINT);
195
196 /**
197 * IBusInputContext::update-preedit-text:
198 * @context: An IBusInputContext.
199 * @text: Text to be updated.
200 * @cursor_pos: Cursor position.
201 * @visible: Whether the update is visible.
202 *
203 * Emitted to update preedit text.
204 *
205 * (Note: The text object is floating, and it will be released after the
206 * signal. If signal handler wants to keep the object, the handler should
207 * use g_object_ref_sink() to get the ownership of the object.)
208 */
209 context_signals[UPDATE_PREEDIT_TEXT] =
210 g_signal_new (I_("update-preedit-text"),
211 G_TYPE_FROM_CLASS (class),
212 G_SIGNAL_RUN_LAST,
213 0,
214 NULL, NULL,
215 _ibus_marshal_VOID__OBJECT_UINT_BOOLEAN,
216 G_TYPE_NONE,
217 3,
218 IBUS_TYPE_TEXT,
219 G_TYPE_UINT,
220 G_TYPE_BOOLEAN);
221
222 /**
223 * IBusInputContext::update-preedit-text-with-mode:
224 * @context: An IBusInputContext.
225 * @text: Text to be updated.
226 * @cursor_pos: Cursor position.
227 * @visible: Whether the update is visible.
228 * @mode: Preedit mode.
229 *
230 * Emitted to update preedit text with the mode.
231 *
232 * (Note: The text object is floating, and it will be released after the
233 * signal. If signal handler wants to keep the object, the handler should
234 * use g_object_ref_sink() to get the ownership of the object.)
235 */
236 context_signals[UPDATE_PREEDIT_TEXT_WITH_MODE] =
237 g_signal_new (I_("update-preedit-text-with-mode"),
238 G_TYPE_FROM_CLASS (class),
239 G_SIGNAL_RUN_LAST,
240 0,
241 NULL, NULL,
242 _ibus_marshal_VOID__OBJECT_UINT_BOOLEAN_UINT,
243 G_TYPE_NONE,
244 4,
245 IBUS_TYPE_TEXT,
246 G_TYPE_UINT,
247 G_TYPE_BOOLEAN,
248 G_TYPE_UINT);
249
250 /**
251 * IBusInputContext::show-preedit-text:
252 * @context: An IBusInputContext.
253 *
254 * Emitted to show preedit text.
255 */
256 context_signals[SHOW_PREEDIT_TEXT] =
257 g_signal_new (I_("show-preedit-text"),
258 G_TYPE_FROM_CLASS (class),
259 G_SIGNAL_RUN_LAST,
260 0,
261 NULL, NULL,
262 _ibus_marshal_VOID__VOID,
263 G_TYPE_NONE, 0);
264
265 /**
266 * IBusInputContext::hide-preedit-text:
267 * @context: An IBusInputContext.
268 *
269 * Emitted to hide preedit text.
270 */
271 context_signals[HIDE_PREEDIT_TEXT] =
272 g_signal_new (I_("hide-preedit-text"),
273 G_TYPE_FROM_CLASS (class),
274 G_SIGNAL_RUN_LAST,
275 0,
276 NULL, NULL,
277 _ibus_marshal_VOID__VOID,
278 G_TYPE_NONE, 0);
279
280 /**
281 * IBusInputContext::update-auxiliary-text:
282 * @context: An IBusInputContext.
283 * @text: An auxiliary text
284 * @visible: The visibility of @text
285 *
286 * Emitted to hide auxilary text.
287 *
288 * (Note: The text object is floating, and it will be released after the
289 * signal. If signal handler wants to keep the object, the handler should
290 * use g_object_ref_sink() to get the ownership of the object.)
291 */
292 context_signals[UPDATE_AUXILIARY_TEXT] =
293 g_signal_new (I_("update-auxiliary-text"),
294 G_TYPE_FROM_CLASS (class),
295 G_SIGNAL_RUN_LAST,
296 0,
297 NULL, NULL,
298 _ibus_marshal_VOID__OBJECT_BOOLEAN,
299 G_TYPE_NONE, 2,
300 IBUS_TYPE_TEXT,
301 G_TYPE_BOOLEAN);
302
303 /**
304 * IBusInputContext::show-auxiliary-text:
305 * @context: An IBusInputContext.
306 *
307 * Emitted to show auxiliary text.
308 */
309 context_signals[SHOW_AUXILIARY_TEXT] =
310 g_signal_new (I_("show-auxiliary-text"),
311 G_TYPE_FROM_CLASS (class),
312 G_SIGNAL_RUN_LAST,
313 0,
314 NULL, NULL,
315 _ibus_marshal_VOID__VOID,
316 G_TYPE_NONE, 0);
317
318 /**
319 * IBusInputContext::hide-auxiliary-text:
320 * @context: An IBusInputContext.
321 *
322 * Emitted to hide auxiliary text.
323 */
324 context_signals[HIDE_AUXILIARY_TEXT] =
325 g_signal_new (I_("hide-auxiliary-text"),
326 G_TYPE_FROM_CLASS (class),
327 G_SIGNAL_RUN_LAST,
328 0,
329 NULL, NULL,
330 _ibus_marshal_VOID__VOID,
331 G_TYPE_NONE, 0);
332
333 /**
334 * IBusInputContext::update-lookup-table:
335 * @context: An IBusInputContext.
336 * @table: An IBusLookupTable to be updated.
337 * @visible: Whether the table should be visible.
338 *
339 * Emitted to update lookup table.
340 *
341 * (Note: The table object is floating, and it will be released after the
342 * signal. If signal handler wants to keep the object, the handler should
343 * use g_object_ref_sink() to get the ownership of the object.)
344 */
345 context_signals[UPDATE_LOOKUP_TABLE] =
346 g_signal_new (I_("update-lookup-table"),
347 G_TYPE_FROM_CLASS (class),
348 G_SIGNAL_RUN_LAST,
349 0,
350 NULL, NULL,
351 _ibus_marshal_VOID__OBJECT_BOOLEAN,
352 G_TYPE_NONE, 2,
353 IBUS_TYPE_LOOKUP_TABLE,
354 G_TYPE_BOOLEAN);
355
356 /**
357 * IBusInputContext::show-lookup-table:
358 * @context: An IBusInputContext.
359 *
360 * Emitted to show lookup table.
361 */
362 context_signals[SHOW_LOOKUP_TABLE] =
363 g_signal_new (I_("show-lookup-table"),
364 G_TYPE_FROM_CLASS (class),
365 G_SIGNAL_RUN_LAST,
366 0,
367 NULL, NULL,
368 _ibus_marshal_VOID__VOID,
369 G_TYPE_NONE, 0);
370
371 /**
372 * IBusInputContext::hide-lookup-table:
373 * @context: An IBusInputContext.
374 *
375 * Emitted to hide lookup table.
376 */
377 context_signals[HIDE_LOOKUP_TABLE] =
378 g_signal_new (I_("hide-lookup-table"),
379 G_TYPE_FROM_CLASS (class),
380 G_SIGNAL_RUN_LAST,
381 0,
382 NULL, NULL,
383 _ibus_marshal_VOID__VOID,
384 G_TYPE_NONE, 0);
385
386 /**
387 * IBusInputContext::page-up-lookup-table:
388 * @context: An IBusInputContext.
389 *
390 * Emitted to view the previous page of lookup table.
391 */
392 context_signals[PAGE_UP_LOOKUP_TABLE] =
393 g_signal_new (I_("page-up-lookup-table"),
394 G_TYPE_FROM_CLASS (class),
395 G_SIGNAL_RUN_LAST,
396 0,
397 NULL, NULL,
398 _ibus_marshal_VOID__VOID,
399 G_TYPE_NONE, 0);
400
401 /**
402 * IBusInputContext::page-down-lookup-table:
403 * @context: An IBusInputContext.
404 *
405 * Emitted to view the next page of lookup table.
406 */
407 context_signals[PAGE_DOWN_LOOKUP_TABLE] =
408 g_signal_new (I_("page-down-lookup-table"),
409 G_TYPE_FROM_CLASS (class),
410 G_SIGNAL_RUN_LAST,
411 0,
412 NULL, NULL,
413 _ibus_marshal_VOID__VOID,
414 G_TYPE_NONE, 0);
415
416 /**
417 * IBusInputContext::cursor-up-lookup-table:
418 * @context: An IBusInputContext.
419 *
420 * Emitted to select previous candidate of lookup table.
421 */
422 context_signals[CURSOR_UP_LOOKUP_TABLE] =
423 g_signal_new (I_("cursor-up-lookup-table"),
424 G_TYPE_FROM_CLASS (class),
425 G_SIGNAL_RUN_LAST,
426 0,
427 NULL, NULL,
428 _ibus_marshal_VOID__VOID,
429 G_TYPE_NONE, 0);
430
431 /**
432 * IBusInputContext::cursor-down-lookup-table:
433 * @context: An IBusInputContext.
434 *
435 * Emitted to select next candidate of lookup table.
436 */
437 context_signals[CURSOR_DOWN_LOOKUP_TABLE] =
438 g_signal_new (I_("cursor-down-lookup-table"),
439 G_TYPE_FROM_CLASS (class),
440 G_SIGNAL_RUN_LAST,
441 0,
442 NULL, NULL,
443 _ibus_marshal_VOID__VOID,
444 G_TYPE_NONE,
445 0);
446
447 /**
448 * IBusInputContext::register-properties:
449 * @context: An IBusInputContext.
450 * @props: An IBusPropList that contains properties.
451 *
452 * Emitted to register the properties in @props.
453 *
454 * (Note: The props object is floating, and it will be released after the
455 * signal. If signal handler wants to keep the object, the handler should
456 * use g_object_ref_sink() to get the ownership of the object.)
457 */
458 context_signals[REGISTER_PROPERTIES] =
459 g_signal_new (I_("register-properties"),
460 G_TYPE_FROM_CLASS (class),
461 G_SIGNAL_RUN_LAST,
462 0,
463 NULL, NULL,
464 _ibus_marshal_VOID__OBJECT,
465 G_TYPE_NONE,
466 1,
467 IBUS_TYPE_PROP_LIST);
468
469 /**
470 * IBusInputContext::update-property:
471 * @context: An IBusInputContext.
472 * @prop: The IBusProperty to be updated.
473 *
474 * Emitted to update the property @prop.
475 *
476 * (Note: The prop object is floating, and it will be released after the
477 * signal. If signal handler wants to keep the object, the handler should
478 * use g_object_ref_sink() to get the ownership of the object.)
479 */
480 context_signals[UPDATE_PROPERTY] =
481 g_signal_new (I_("update-property"),
482 G_TYPE_FROM_CLASS (class),
483 G_SIGNAL_RUN_LAST,
484 0,
485 NULL, NULL,
486 _ibus_marshal_VOID__OBJECT,
487 G_TYPE_NONE,
488 1,
489 IBUS_TYPE_PROPERTY);
490
491 text_empty = ibus_text_new_from_static_string ("");
492 g_object_ref_sink (text_empty);
493 }
494
495 static void
ibus_input_context_init(IBusInputContext * context)496 ibus_input_context_init (IBusInputContext *context)
497 {
498 IBusInputContextPrivate *priv;
499
500 priv = IBUS_INPUT_CONTEXT_GET_PRIVATE (context);
501 priv->surrounding_text = g_object_ref_sink (text_empty);
502 }
503
504 static void
ibus_input_context_real_destroy(IBusProxy * context)505 ibus_input_context_real_destroy (IBusProxy *context)
506 {
507 IBusInputContextPrivate *priv;
508 priv = IBUS_INPUT_CONTEXT_GET_PRIVATE (IBUS_INPUT_CONTEXT (context));
509
510 if (priv->surrounding_text) {
511 g_object_unref (priv->surrounding_text);
512 priv->surrounding_text = NULL;
513 }
514
515 IBUS_PROXY_CLASS(ibus_input_context_parent_class)->destroy (context);
516 }
517
518 static void
ibus_input_context_g_signal(GDBusProxy * proxy,const gchar * sender_name,const gchar * signal_name,GVariant * parameters)519 ibus_input_context_g_signal (GDBusProxy *proxy,
520 const gchar *sender_name,
521 const gchar *signal_name,
522 GVariant *parameters)
523 {
524 g_assert (IBUS_IS_INPUT_CONTEXT (proxy));
525
526 IBusInputContext *context;
527 context = IBUS_INPUT_CONTEXT (proxy);
528
529 static const struct {
530 const gchar *signal_name;
531 guint signal_id;
532 } signals [] = {
533 { "ShowPreeditText", SHOW_PREEDIT_TEXT },
534 { "HidePreeditText", HIDE_PREEDIT_TEXT },
535 { "ShowAuxiliaryText", SHOW_AUXILIARY_TEXT },
536 { "HideAuxiliaryText", HIDE_AUXILIARY_TEXT },
537 { "ShowLookupTable", SHOW_LOOKUP_TABLE },
538 { "HideLookupTable", HIDE_LOOKUP_TABLE },
539 { "PageUpLookupTable", PAGE_UP_LOOKUP_TABLE },
540 { "PageDownLookupTable", PAGE_DOWN_LOOKUP_TABLE },
541 { "CursorUpLookupTable", CURSOR_UP_LOOKUP_TABLE },
542 { "CursorDownLookupTable", CURSOR_DOWN_LOOKUP_TABLE },
543 };
544
545 if (g_strcmp0 (signal_name, "CommitText") == 0) {
546 GVariant *variant = NULL;
547 g_variant_get (parameters, "(v)", &variant);
548 IBusText *text = IBUS_TEXT (ibus_serializable_deserialize (variant));
549 g_variant_unref (variant);
550 g_signal_emit (context, context_signals[COMMIT_TEXT], 0, text);
551
552 if (g_object_is_floating (text))
553 g_object_unref (text);
554 return;
555 }
556 if (g_strcmp0 (signal_name, "UpdatePreeditText") == 0) {
557 GVariant *variant = NULL;
558 gint32 cursor_pos;
559 gboolean visible;
560 g_variant_get (parameters, "(vub)", &variant, &cursor_pos, &visible);
561 IBusText *text = IBUS_TEXT (ibus_serializable_deserialize (variant));
562 g_variant_unref (variant);
563
564 g_signal_emit (context,
565 context_signals[UPDATE_PREEDIT_TEXT],
566 0,
567 text,
568 cursor_pos,
569 visible);
570
571 if (g_object_is_floating (text))
572 g_object_unref (text);
573 return;
574 }
575 if (g_strcmp0 (signal_name, "UpdatePreeditTextWithMode") == 0) {
576 GVariant *variant = NULL;
577 gint32 cursor_pos;
578 gboolean visible;
579 guint mode = 0;
580 g_variant_get (parameters,
581 "(vubu)", &variant, &cursor_pos, &visible, &mode);
582 IBusText *text = IBUS_TEXT (ibus_serializable_deserialize (variant));
583 g_variant_unref (variant);
584
585 g_signal_emit (context,
586 context_signals[UPDATE_PREEDIT_TEXT_WITH_MODE],
587 0,
588 text,
589 cursor_pos,
590 visible,
591 mode);
592
593 if (g_object_is_floating (text))
594 g_object_unref (text);
595 return;
596 }
597
598 /* lookup signal in table */
599 gint i;
600 for (i = 0;
601 i < G_N_ELEMENTS (signals) && g_strcmp0 (signal_name, signals[i].signal_name) != 0;
602 i++);
603
604 if (i < G_N_ELEMENTS (signals)) {
605 g_signal_emit (context, context_signals[signals[i].signal_id], 0);
606 return;
607 }
608
609 if (g_strcmp0 (signal_name, "UpdateAuxiliaryText") == 0) {
610 GVariant *variant = NULL;
611 gboolean visible;
612 g_variant_get (parameters, "(vb)", &variant, &visible);
613 IBusText *text = IBUS_TEXT (ibus_serializable_deserialize (variant));
614 g_variant_unref (variant);
615
616 g_signal_emit (context,
617 context_signals[UPDATE_AUXILIARY_TEXT],
618 0,
619 text,
620 visible);
621 if (g_object_is_floating (text))
622 g_object_unref (text);
623 return;
624 }
625
626 if (g_strcmp0 (signal_name, "UpdateLookupTable") == 0) {
627 GVariant *variant = NULL;
628 gboolean visible;
629 g_variant_get (parameters, "(vb)", &variant, &visible);
630
631 IBusLookupTable *table = IBUS_LOOKUP_TABLE (ibus_serializable_deserialize (variant));
632 g_variant_unref (variant);
633
634 g_signal_emit (context,
635 context_signals[UPDATE_LOOKUP_TABLE],
636 0,
637 table,
638 visible);
639 if (g_object_is_floating (table))
640 g_object_unref (table);
641 return;
642
643 }
644
645 if (g_strcmp0 (signal_name, "RegisterProperties") == 0) {
646 GVariant *variant = NULL;
647 g_variant_get (parameters, "(v)", &variant);
648
649 IBusPropList *prop_list = IBUS_PROP_LIST (ibus_serializable_deserialize (variant));
650 g_variant_unref (variant);
651
652 g_signal_emit (context,
653 context_signals[REGISTER_PROPERTIES],
654 0,
655 prop_list);
656
657 if (g_object_is_floating (prop_list))
658 g_object_unref (prop_list);
659 return;
660 }
661
662 if (g_strcmp0 (signal_name, "UpdateProperty") == 0) {
663 GVariant *variant = NULL;
664 g_variant_get (parameters, "(v)", &variant);
665 IBusProperty *prop = IBUS_PROPERTY (ibus_serializable_deserialize (variant));
666 g_variant_unref (variant);
667
668 g_signal_emit (context, context_signals[UPDATE_PROPERTY], 0, prop);
669
670 if (g_object_is_floating (prop))
671 g_object_unref (prop);
672 return;
673 }
674
675 if (g_strcmp0 (signal_name, "ForwardKeyEvent") == 0) {
676 guint32 keyval;
677 guint32 keycode;
678 guint32 state;
679
680 g_variant_get (parameters, "(uuu)", &keyval, &keycode, &state);
681
682 /* Forward key event back with IBUS_FORWARD_MASK. And process_key_event will
683 * not process key event with IBUS_FORWARD_MASK again. */
684 g_signal_emit (context,
685 context_signals[FORWARD_KEY_EVENT],
686 0,
687 keyval,
688 keycode,
689 state | IBUS_FORWARD_MASK);
690 return;
691 }
692
693 if (g_strcmp0 (signal_name, "DeleteSurroundingText") == 0) {
694 gint offset_from_cursor;
695 guint nchars;
696
697 g_variant_get (parameters, "(iu)", &offset_from_cursor, &nchars);
698
699 g_signal_emit (context,
700 context_signals[DELETE_SURROUNDING_TEXT],
701 0,
702 offset_from_cursor,
703 nchars);
704 return;
705 }
706
707 IBusInputContextPrivate *priv;
708 priv = IBUS_INPUT_CONTEXT_GET_PRIVATE (IBUS_INPUT_CONTEXT (context));
709
710 if (g_strcmp0 (signal_name, "Enabled") == 0) {
711 priv->needs_surrounding_text = FALSE;
712 g_signal_emit (context, context_signals[ENABLED], 0);
713 return;
714 }
715
716 if (g_strcmp0 (signal_name, "Disabled") == 0) {
717 priv->needs_surrounding_text = FALSE;
718 g_signal_emit (context, context_signals[DISABLED], 0);
719 return;
720 }
721
722 if (g_strcmp0 (signal_name, "RequireSurroundingText") == 0) {
723 priv->needs_surrounding_text = TRUE;
724 return;
725 }
726
727 G_DBUS_PROXY_CLASS (ibus_input_context_parent_class)->g_signal (
728 proxy, sender_name, signal_name, parameters);
729 }
730
731 IBusInputContext *
ibus_input_context_new(const gchar * path,GDBusConnection * connection,GCancellable * cancellable,GError ** error)732 ibus_input_context_new (const gchar *path,
733 GDBusConnection *connection,
734 GCancellable *cancellable,
735 GError **error)
736 {
737 g_assert (path != NULL);
738 g_assert (G_IS_DBUS_CONNECTION (connection));
739 const gchar *service_name = IBUS_SERVICE_IBUS;
740
741 GInitable *initable;
742
743 GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START;
744
745 if (g_object_get_data (G_OBJECT (connection), "ibus-portal-connection"))
746 service_name = IBUS_SERVICE_PORTAL;
747
748 initable = g_initable_new (IBUS_TYPE_INPUT_CONTEXT,
749 cancellable,
750 error,
751 "g-connection", connection,
752 "g-name", service_name,
753 "g-flags", flags,
754 "g-interface-name", IBUS_INTERFACE_INPUT_CONTEXT,
755 "g-object-path", path,
756 "g-default-timeout", ibus_get_timeout (),
757 NULL);
758 if (initable != NULL)
759 return IBUS_INPUT_CONTEXT (initable);
760 return NULL;
761 }
762
763 void
ibus_input_context_new_async(const gchar * path,GDBusConnection * connection,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)764 ibus_input_context_new_async (const gchar *path,
765 GDBusConnection *connection,
766 GCancellable *cancellable,
767 GAsyncReadyCallback callback,
768 gpointer user_data)
769 {
770 g_assert (path != NULL);
771 g_assert (G_IS_DBUS_CONNECTION (connection));
772 g_assert (callback != NULL);
773 const gchar *service_name = IBUS_SERVICE_IBUS;
774
775 GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START;
776
777 if (g_object_get_data (G_OBJECT (connection), "ibus-portal-connection"))
778 service_name = IBUS_SERVICE_PORTAL;
779
780 g_async_initable_new_async (IBUS_TYPE_INPUT_CONTEXT,
781 G_PRIORITY_DEFAULT,
782 cancellable,
783 callback,
784 user_data,
785 "g-connection", connection,
786 "g-name", service_name,
787 "g-flags", flags,
788 "g-interface-name", IBUS_INTERFACE_INPUT_CONTEXT,
789 "g-object-path", path,
790 "g-default-timeout", ibus_get_timeout (),
791 NULL);
792 }
793
794 IBusInputContext *
ibus_input_context_new_async_finish(GAsyncResult * res,GError ** error)795 ibus_input_context_new_async_finish (GAsyncResult *res,
796 GError **error)
797 {
798 GObject *object = NULL;
799 GObject *source_object = NULL;
800
801 source_object = g_async_result_get_source_object (res);
802 g_assert (source_object != NULL);
803
804 object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
805 res,
806 error);
807 g_object_unref (source_object);
808
809 if (object != NULL) {
810 return IBUS_INPUT_CONTEXT (object);
811 }
812 else {
813 return NULL;
814 }
815 }
816
817 IBusInputContext *
ibus_input_context_get_input_context(const gchar * path,GDBusConnection * connection)818 ibus_input_context_get_input_context (const gchar *path,
819 GDBusConnection *connection)
820 {
821 IBusInputContext *context = NULL;
822 GError *error = NULL;
823
824 context = ibus_input_context_new (path, connection, NULL, &error);
825 if (context == NULL) {
826 g_warning ("ibus_input_context_get_input_context: %s", error->message);
827 g_error_free (error);
828 return NULL;
829 }
830
831 /* Do not call "org.freedesktop.IBus.Service.Destroy" when the input
832 * context object is disposed. */
833 IBUS_PROXY (context)->own = FALSE;
834 return context;
835 }
836
837 void
ibus_input_context_get_input_context_async(const gchar * path,GDBusConnection * connection,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)838 ibus_input_context_get_input_context_async (const gchar *path,
839 GDBusConnection *connection,
840 GCancellable *cancellable,
841 GAsyncReadyCallback callback,
842 gpointer user_data)
843 {
844 ibus_input_context_new_async (path,
845 connection,
846 cancellable,
847 callback,
848 user_data);
849 }
850
851 IBusInputContext *
ibus_input_context_get_input_context_async_finish(GAsyncResult * res,GError ** error)852 ibus_input_context_get_input_context_async_finish (GAsyncResult *res,
853 GError **error)
854 {
855 IBusInputContext *context = NULL;
856
857 context = ibus_input_context_new_async_finish (res, error);
858 if (context == NULL) {
859 return NULL;
860 }
861
862 /* Do not call "org.freedesktop.IBus.Service.Destroy" when the input
863 * context object is disposed. */
864 IBUS_PROXY (context)->own = FALSE;
865 return context;
866 }
867
868 void
ibus_input_context_process_hand_writing_event(IBusInputContext * context,const gdouble * coordinates,guint coordinates_len)869 ibus_input_context_process_hand_writing_event (IBusInputContext *context,
870 const gdouble *coordinates,
871 guint coordinates_len)
872 {
873 g_assert (IBUS_IS_INPUT_CONTEXT (context));
874 g_return_if_fail (coordinates != NULL);
875 g_return_if_fail (coordinates_len >= 4); /* The array should contain at least one line. */
876 g_return_if_fail ((coordinates_len & 1) == 0);
877
878 guint i;
879 GVariantBuilder builder;
880 g_variant_builder_init (&builder, G_VARIANT_TYPE ("ad"));
881 for (i = 0; i < coordinates_len; i++) {
882 g_variant_builder_add (&builder, "d", coordinates[i]);
883 }
884
885 g_dbus_proxy_call ((GDBusProxy *) context,
886 "ProcessHandWritingEvent", /* method_name */
887 g_variant_new ("(ad)", &builder), /* parameters */
888 G_DBUS_CALL_FLAGS_NONE, /* flags */
889 -1, /* timeout */
890 NULL, /* cancellable */
891 NULL, /* callback */
892 NULL /* user_data */
893 );
894 }
895
896 void
ibus_input_context_cancel_hand_writing(IBusInputContext * context,guint n_strokes)897 ibus_input_context_cancel_hand_writing (IBusInputContext *context,
898 guint n_strokes)
899 {
900 g_assert (IBUS_IS_INPUT_CONTEXT (context));
901
902 g_dbus_proxy_call ((GDBusProxy *) context,
903 "CancelHandWriting", /* method_name */
904 g_variant_new ("(u)", n_strokes), /* parameters */
905 G_DBUS_CALL_FLAGS_NONE, /* flags */
906 -1, /* timeout */
907 NULL, /* cancellable */
908 NULL, /* callback */
909 NULL /* user_data */
910 );
911 }
912
913 void
ibus_input_context_process_key_event_async(IBusInputContext * context,guint32 keyval,guint32 keycode,guint32 state,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)914 ibus_input_context_process_key_event_async (IBusInputContext *context,
915 guint32 keyval,
916 guint32 keycode,
917 guint32 state,
918 gint timeout_msec,
919 GCancellable *cancellable,
920 GAsyncReadyCallback callback,
921 gpointer user_data)
922 {
923 g_assert (IBUS_IS_INPUT_CONTEXT (context));
924
925 g_dbus_proxy_call ((GDBusProxy *) context,
926 "ProcessKeyEvent", /* method_name */
927 g_variant_new ("(uuu)",
928 keyval, keycode, state), /* parameters */
929 G_DBUS_CALL_FLAGS_NONE, /* flags */
930 timeout_msec, /* timeout */
931 cancellable, /* cancellable */
932 callback, /* callback */
933 user_data /* user_data */
934 );
935 }
936
937 gboolean
ibus_input_context_process_key_event_async_finish(IBusInputContext * context,GAsyncResult * res,GError ** error)938 ibus_input_context_process_key_event_async_finish (IBusInputContext *context,
939 GAsyncResult *res,
940 GError **error)
941 {
942 g_assert (IBUS_IS_INPUT_CONTEXT (context));
943 g_assert (G_IS_ASYNC_RESULT (res));
944 g_assert (error == NULL || *error == NULL);
945
946 gboolean processed = FALSE;
947
948 GVariant *variant = g_dbus_proxy_call_finish ((GDBusProxy *) context,
949 res, error);
950 if (variant != NULL) {
951 g_variant_get (variant, "(b)", &processed);
952 g_variant_unref (variant);
953 }
954
955 return processed;
956 }
957
958 gboolean
ibus_input_context_process_key_event(IBusInputContext * context,guint32 keyval,guint32 keycode,guint32 state)959 ibus_input_context_process_key_event (IBusInputContext *context,
960 guint32 keyval,
961 guint32 keycode,
962 guint32 state)
963 {
964 g_assert (IBUS_IS_INPUT_CONTEXT (context));
965
966 GVariant *result = g_dbus_proxy_call_sync ((GDBusProxy *) context,
967 "ProcessKeyEvent", /* method_name */
968 g_variant_new ("(uuu)",
969 keyval, keycode, state), /* parameters */
970 G_DBUS_CALL_FLAGS_NONE, /* flags */
971 -1, /* timeout */
972 NULL, /* cancellable */
973 NULL);
974
975 if (result != NULL) {
976 gboolean processed = FALSE;
977
978 g_variant_get (result, "(b)", &processed);
979 g_variant_unref (result);
980 return processed;
981 }
982
983 return FALSE;
984 }
985
986 void
ibus_input_context_set_cursor_location(IBusInputContext * context,gint32 x,gint32 y,gint32 w,gint32 h)987 ibus_input_context_set_cursor_location (IBusInputContext *context,
988 gint32 x,
989 gint32 y,
990 gint32 w,
991 gint32 h)
992 {
993 g_assert (IBUS_IS_INPUT_CONTEXT (context));
994
995 g_dbus_proxy_call ((GDBusProxy *) context,
996 "SetCursorLocation", /* method_name */
997 g_variant_new ("(iiii)", x, y, w, h),/* parameters */
998 G_DBUS_CALL_FLAGS_NONE, /* flags */
999 -1, /* timeout */
1000 NULL, /* cancellable */
1001 NULL, /* callback */
1002 NULL /* user_data */
1003 );
1004 }
1005
1006 void
ibus_input_context_set_cursor_location_relative(IBusInputContext * context,gint32 x,gint32 y,gint32 w,gint32 h)1007 ibus_input_context_set_cursor_location_relative (IBusInputContext *context,
1008 gint32 x,
1009 gint32 y,
1010 gint32 w,
1011 gint32 h)
1012 {
1013 g_assert (IBUS_IS_INPUT_CONTEXT (context));
1014
1015 g_dbus_proxy_call ((GDBusProxy *) context,
1016 "SetCursorLocationRelative", /* method_name */
1017 g_variant_new ("(iiii)", x, y, w, h),/* parameters */
1018 G_DBUS_CALL_FLAGS_NONE, /* flags */
1019 -1, /* timeout */
1020 NULL, /* cancellable */
1021 NULL, /* callback */
1022 NULL /* user_data */
1023 );
1024 }
1025
1026 void
ibus_input_context_set_capabilities(IBusInputContext * context,guint32 capabilites)1027 ibus_input_context_set_capabilities (IBusInputContext *context,
1028 guint32 capabilites)
1029 {
1030 g_assert (IBUS_IS_INPUT_CONTEXT (context));
1031 g_dbus_proxy_call ((GDBusProxy *) context,
1032 "SetCapabilities", /* method_name */
1033 g_variant_new ("(u)", capabilites), /* parameters */
1034 G_DBUS_CALL_FLAGS_NONE, /* flags */
1035 -1, /* timeout */
1036 NULL, /* cancellable */
1037 NULL, /* callback */
1038 NULL /* user_data */
1039 );
1040 }
1041
1042 void
ibus_input_context_property_activate(IBusInputContext * context,const gchar * prop_name,guint32 state)1043 ibus_input_context_property_activate (IBusInputContext *context,
1044 const gchar *prop_name,
1045 guint32 state)
1046 {
1047 g_assert (IBUS_IS_INPUT_CONTEXT (context));
1048 g_dbus_proxy_call ((GDBusProxy *) context,
1049 "PropertyActivate", /* method_name */
1050 g_variant_new ("(su)",
1051 prop_name, state), /* parameters */
1052 G_DBUS_CALL_FLAGS_NONE, /* flags */
1053 -1, /* timeout */
1054 NULL, /* cancellable */
1055 NULL, /* callback */
1056 NULL /* user_data */
1057 );
1058 }
1059
1060 void
ibus_input_context_property_show(IBusInputContext * context,const gchar * prop_name)1061 ibus_input_context_property_show (IBusInputContext *context,
1062 const gchar *prop_name)
1063 {
1064 g_assert (IBUS_IS_INPUT_CONTEXT (context));
1065 g_dbus_proxy_call ((GDBusProxy *) context,
1066 "PropertyShow", /* method_name */
1067 g_variant_new ("(s)", prop_name), /* parameters */
1068 G_DBUS_CALL_FLAGS_NONE, /* flags */
1069 -1, /* timeout */
1070 NULL, /* cancellable */
1071 NULL, /* callback */
1072 NULL /* user_data */
1073 );
1074 }
1075
1076 void
ibus_input_context_property_hide(IBusInputContext * context,const gchar * prop_name)1077 ibus_input_context_property_hide (IBusInputContext *context,
1078 const gchar *prop_name)
1079 {
1080 g_assert (IBUS_IS_INPUT_CONTEXT (context));
1081 g_dbus_proxy_call ((GDBusProxy *) context,
1082 "PropertyHide", /* method_name */
1083 g_variant_new ("(s)", prop_name), /* parameters */
1084 G_DBUS_CALL_FLAGS_NONE, /* flags */
1085 -1, /* timeout */
1086 NULL, /* cancellable */
1087 NULL, /* callback */
1088 NULL /* user_data */
1089 );
1090 }
1091
1092 void
ibus_input_context_set_surrounding_text(IBusInputContext * context,IBusText * text,guint32 cursor_pos,guint32 anchor_pos)1093 ibus_input_context_set_surrounding_text (IBusInputContext *context,
1094 IBusText *text,
1095 guint32 cursor_pos,
1096 guint32 anchor_pos)
1097 {
1098 IBusInputContextPrivate *priv;
1099
1100 g_assert (IBUS_IS_INPUT_CONTEXT (context));
1101 g_assert (IBUS_IS_TEXT (text));
1102
1103 priv = IBUS_INPUT_CONTEXT_GET_PRIVATE (context);
1104
1105 if (cursor_pos != priv->surrounding_cursor_pos ||
1106 anchor_pos != priv->selection_anchor_pos ||
1107 priv->surrounding_text == NULL ||
1108 g_strcmp0 (text->text, priv->surrounding_text->text) != 0) {
1109 if (priv->surrounding_text)
1110 g_object_unref (priv->surrounding_text);
1111 priv->surrounding_text = (IBusText *) g_object_ref_sink (text);
1112 priv->surrounding_cursor_pos = cursor_pos;
1113 priv->selection_anchor_pos = anchor_pos;
1114
1115 if (priv->needs_surrounding_text) {
1116 GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)text);
1117 g_dbus_proxy_call ((GDBusProxy *) context,
1118 "SetSurroundingText", /* method_name */
1119 g_variant_new ("(vuu)",
1120 variant,
1121 cursor_pos,
1122 anchor_pos), /* parameters */
1123 G_DBUS_CALL_FLAGS_NONE, /* flags */
1124 -1, /* timeout */
1125 NULL, /* cancellable */
1126 NULL, /* callback */
1127 NULL /* user_data */
1128 );
1129 }
1130 }
1131 }
1132
1133 gboolean
ibus_input_context_needs_surrounding_text(IBusInputContext * context)1134 ibus_input_context_needs_surrounding_text (IBusInputContext *context)
1135 {
1136 IBusInputContextPrivate *priv;
1137 priv = IBUS_INPUT_CONTEXT_GET_PRIVATE (IBUS_INPUT_CONTEXT (context));
1138 return priv->needs_surrounding_text;
1139 }
1140
1141 void
ibus_input_context_set_content_type(IBusInputContext * context,guint purpose,guint hints)1142 ibus_input_context_set_content_type (IBusInputContext *context,
1143 guint purpose,
1144 guint hints)
1145 {
1146 GVariant *cached_content_type;
1147 GVariant *content_type;
1148
1149 g_assert (IBUS_IS_INPUT_CONTEXT (context));
1150
1151 cached_content_type =
1152 g_dbus_proxy_get_cached_property ((GDBusProxy *) context,
1153 "ContentType");
1154 content_type = g_variant_new ("(uu)", purpose, hints);
1155
1156 g_variant_ref_sink (content_type);
1157 if (cached_content_type == NULL ||
1158 !g_variant_equal (content_type, cached_content_type)) {
1159 g_dbus_proxy_call ((GDBusProxy *) context,
1160 "org.freedesktop.DBus.Properties.Set",
1161 g_variant_new ("(ssv)",
1162 IBUS_INTERFACE_INPUT_CONTEXT,
1163 "ContentType",
1164 content_type),
1165 G_DBUS_CALL_FLAGS_NONE,
1166 -1,
1167 NULL, /* cancellable */
1168 NULL, /* callback */
1169 NULL /* user_data */
1170 );
1171 }
1172
1173 if (cached_content_type != NULL)
1174 g_variant_unref (cached_content_type);
1175 g_variant_unref (content_type);
1176 }
1177
1178 void
ibus_input_context_get_engine_async(IBusInputContext * context,gint timeout_msec,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1179 ibus_input_context_get_engine_async (IBusInputContext *context,
1180 gint timeout_msec,
1181 GCancellable *cancellable,
1182 GAsyncReadyCallback callback,
1183 gpointer user_data)
1184 {
1185 g_assert (IBUS_IS_INPUT_CONTEXT (context));
1186 g_dbus_proxy_call ((GDBusProxy *) context,
1187 "GetEngine", /* method_name */
1188 NULL, /* parameters */
1189 G_DBUS_CALL_FLAGS_NONE, /* flags */
1190 timeout_msec,
1191 cancellable,
1192 callback,
1193 user_data);
1194 }
1195
1196 IBusEngineDesc *
ibus_input_context_get_engine_async_finish(IBusInputContext * context,GAsyncResult * res,GError ** error)1197 ibus_input_context_get_engine_async_finish (IBusInputContext *context,
1198 GAsyncResult *res,
1199 GError **error)
1200 {
1201 GVariant *variant;
1202 GVariant *engine_desc_variant;
1203 IBusEngineDesc *desc;
1204
1205 g_assert (IBUS_IS_INPUT_CONTEXT (context));
1206 g_assert (G_IS_ASYNC_RESULT (res));
1207 g_assert (error == NULL || *error == NULL);
1208
1209 variant = g_dbus_proxy_call_finish ((GDBusProxy *) context, res, error);
1210 if (variant == NULL) {
1211 return NULL;
1212 }
1213
1214 engine_desc_variant = g_variant_get_child_value (variant, 0);
1215 desc = IBUS_ENGINE_DESC (
1216 ibus_serializable_deserialize (engine_desc_variant));
1217 g_variant_unref (engine_desc_variant);
1218 g_variant_unref (variant);
1219
1220 return desc;
1221 }
1222
1223 IBusEngineDesc *
ibus_input_context_get_engine(IBusInputContext * context)1224 ibus_input_context_get_engine (IBusInputContext *context)
1225 {
1226 GVariant *result = NULL;
1227 GError *error = NULL;
1228 GVariant *engine_desc_variant;
1229 IBusEngineDesc *desc;
1230
1231 g_assert (IBUS_IS_INPUT_CONTEXT (context));
1232
1233 result = g_dbus_proxy_call_sync ((GDBusProxy *) context,
1234 "GetEngine", /* method_name */
1235 NULL, /* parameters */
1236 G_DBUS_CALL_FLAGS_NONE, /* flags */
1237 -1, /* timeout */
1238 NULL, /* cancellable */
1239 &error /* error */
1240 );
1241 if (result == NULL) {
1242 if (g_error_matches (error, IBUS_ERROR, IBUS_ERROR_NO_ENGINE)) {
1243 g_debug ("%s.GetEngine: %s",
1244 IBUS_INTERFACE_INPUT_CONTEXT,
1245 error->message);
1246 }
1247 else {
1248 g_warning ("%s.GetEngine: %s",
1249 IBUS_INTERFACE_INPUT_CONTEXT,
1250 error->message);
1251 }
1252 g_error_free (error);
1253 return NULL;
1254 }
1255
1256 engine_desc_variant = g_variant_get_child_value (result, 0);
1257 desc = IBUS_ENGINE_DESC (
1258 ibus_serializable_deserialize (engine_desc_variant));
1259 g_variant_unref (engine_desc_variant);
1260 g_variant_unref (result);
1261
1262 return desc;
1263 }
1264
1265 void
ibus_input_context_set_engine(IBusInputContext * context,const gchar * name)1266 ibus_input_context_set_engine (IBusInputContext *context,
1267 const gchar *name)
1268 {
1269 g_assert (IBUS_IS_INPUT_CONTEXT (context));
1270 g_assert (name);
1271 g_dbus_proxy_call ((GDBusProxy *) context,
1272 "SetEngine", /* method_name */
1273 g_variant_new ("(s)", name), /* parameters */
1274 G_DBUS_CALL_FLAGS_NONE, /* flags */
1275 -1, /* timeout */
1276 NULL, /* cancellable */
1277 NULL, /* callback */
1278 NULL /* user_data */
1279 );
1280 }
1281
1282 void
ibus_input_context_set_client_commit_preedit(IBusInputContext * context,gboolean client_commit)1283 ibus_input_context_set_client_commit_preedit (IBusInputContext *context,
1284 gboolean client_commit)
1285 {
1286 GVariant *cached_content_type;
1287 GVariant *var_client_commit;
1288
1289 g_assert (IBUS_IS_INPUT_CONTEXT (context));
1290
1291 cached_content_type =
1292 g_dbus_proxy_get_cached_property ((GDBusProxy *) context,
1293 "ClientCommitPreedit");
1294 var_client_commit = g_variant_new ("(b)", client_commit);
1295
1296 g_variant_ref_sink (var_client_commit);
1297 if (cached_content_type == NULL) {
1298 g_dbus_proxy_call ((GDBusProxy *) context,
1299 "org.freedesktop.DBus.Properties.Set",
1300 g_variant_new ("(ssv)",
1301 IBUS_INTERFACE_INPUT_CONTEXT,
1302 "ClientCommitPreedit",
1303 var_client_commit),
1304 G_DBUS_CALL_FLAGS_NONE,
1305 -1,
1306 NULL, /* cancellable */
1307 NULL, /* callback */
1308 NULL /* user_data */
1309 );
1310 }
1311
1312 if (cached_content_type != NULL)
1313 g_variant_unref (cached_content_type);
1314 g_variant_unref (var_client_commit);
1315 }
1316
1317 #define DEFINE_FUNC(name, Name) \
1318 void \
1319 ibus_input_context_##name (IBusInputContext *context) \
1320 { \
1321 g_assert (IBUS_IS_INPUT_CONTEXT (context)); \
1322 g_dbus_proxy_call ((GDBusProxy *) context, \
1323 #Name, /* method_name */ \
1324 NULL, /* parameters */ \
1325 G_DBUS_CALL_FLAGS_NONE, /* flags */ \
1326 -1, /* timeout */ \
1327 NULL, /* cancellable */ \
1328 NULL, /* callback */ \
1329 NULL /* user_data */ \
1330 ); \
1331 }
1332
1333 DEFINE_FUNC(focus_in, FocusIn);
1334 DEFINE_FUNC(focus_out, FocusOut);
1335 DEFINE_FUNC(reset, Reset);
1336 DEFINE_FUNC(page_up, PageUp);
1337 DEFINE_FUNC(page_down, PageDown);
1338 DEFINE_FUNC(cursor_up, CursorUp);
1339 DEFINE_FUNC(cursor_down, CursorDown);
1340 #undef DEFINE_FUNC
1341