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