47cfeb060d58f3b985d103fa7773433810ecc2ea
[platform/upstream/ibus.git] / src / ibusengine.c
1 /* vim:set et sts=4: */
2 /* ibus - The Input Bus
3  * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include <stdarg.h>
22 #include "ibusengine.h"
23 #include "ibusinternal.h"
24 #include "ibusshare.h"
25
26 #define IBUS_ENGINE_GET_PRIVATE(o)  \
27    (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_ENGINE, IBusEnginePrivate))
28
29 enum {
30     PROCESS_KEY_EVENT,
31     FOCUS_IN,
32     FOCUS_OUT,
33     RESET,
34     ENABLE,
35     DISABLE,
36     SET_CURSOR_LOCATION,
37     SET_CAPABILITIES,
38     PAGE_UP,
39     PAGE_DOWN,
40     CURSOR_UP,
41     CURSOR_DOWN,
42     PROPERTY_ACTIVATE,
43     PROPERTY_SHOW,
44     PROPERTY_HIDE,
45     LAST_SIGNAL,
46 };
47
48 enum {
49     PROP_0,
50     PROP_NAME,
51     PROP_CONNECTION,
52 };
53
54
55 /* IBusEnginePriv */
56 struct _IBusEnginePrivate {
57     gchar *name;
58     IBusConnection *connection;
59 };
60 typedef struct _IBusEnginePrivate IBusEnginePrivate;
61
62 static guint            engine_signals[LAST_SIGNAL] = { 0 };
63
64 /* functions prototype */
65 static void     ibus_engine_class_init      (IBusEngineClass    *klass);
66 static void     ibus_engine_init            (IBusEngine         *engine);
67 static void     ibus_engine_destroy         (IBusEngine         *engine);
68 static void     ibus_engine_set_property    (IBusEngine         *engine,
69                                              guint               prop_id,
70                                              const GValue       *value,
71                                              GParamSpec         *pspec);
72 static void     ibus_engine_get_property    (IBusEngine         *engine,
73                                              guint               prop_id,
74                                              GValue             *value,
75                                              GParamSpec         *pspec);
76 static gboolean ibus_engine_ibus_message    (IBusEngine         *engine,
77                                              IBusConnection     *connection,
78                                              IBusMessage        *message);
79 static gboolean ibus_engine_process_key_event
80                                             (IBusEngine         *engine,
81                                              guint               keyval,
82                                              guint               state);
83 static void     ibus_engine_focus_in        (IBusEngine         *engine);
84 static void     ibus_engine_focus_out       (IBusEngine         *engine);
85 static void     ibus_engine_reset           (IBusEngine         *engine);
86 static void     ibus_engine_enable          (IBusEngine         *engine);
87 static void     ibus_engine_disable         (IBusEngine         *engine);
88 static void     ibus_engine_set_cursor_location
89                                             (IBusEngine         *engine,
90                                              gint                x,
91                                              gint                y,
92                                              gint                w,
93                                              gint                h);
94 static void     ibus_engine_set_capabilities
95                                             (IBusEngine         *engine,
96                                              guint               caps);
97 static void     ibus_engine_page_up         (IBusEngine         *engine);
98 static void     ibus_engine_page_down       (IBusEngine         *engine);
99 static void     ibus_engine_cursor_up       (IBusEngine         *engine);
100 static void     ibus_engine_cursor_down     (IBusEngine         *engine);
101 static void     ibus_engine_property_activate
102                                             (IBusEngine         *engine,
103                                              const gchar        *prop_name,
104                                              gint                prop_state);
105 static void     ibus_engine_property_show   (IBusEngine         *engine,
106                                              const gchar        *prop_name);
107 static void     ibus_engine_property_hide   (IBusEngine         *engine,
108                                              const gchar        *prop_name);
109
110
111 static IBusServiceClass  *parent_class = NULL;
112
113 GType
114 ibus_engine_get_type (void)
115 {
116     static GType type = 0;
117
118     static const GTypeInfo type_info = {
119         sizeof (IBusEngineClass),
120         (GBaseInitFunc)     NULL,
121         (GBaseFinalizeFunc) NULL,
122         (GClassInitFunc)    ibus_engine_class_init,
123         NULL,               /* class finalize */
124         NULL,               /* class data */
125         sizeof (IBusEngine),
126         0,
127         (GInstanceInitFunc) ibus_engine_init,
128     };
129
130     if (type == 0) {
131         type = g_type_register_static (IBUS_TYPE_SERVICE,
132                     "IBusEngine",
133                     &type_info,
134                     (GTypeFlags) 0);
135     }
136     return type;
137 }
138
139 IBusEngine *
140 ibus_engine_new (const gchar    *name,
141                  const gchar    *path,
142                  IBusConnection *connection)
143 {
144     g_assert (path);
145     g_assert (IBUS_IS_CONNECTION (connection));
146
147     IBusEngine *engine;
148
149     engine = (IBusEngine *) g_object_new (IBUS_TYPE_ENGINE,
150                                           "name", name,
151                                           "path", path,
152                                           "connection", connection,
153                                           NULL);
154
155     return engine;
156 }
157
158 static void
159 ibus_engine_class_init (IBusEngineClass *klass)
160 {
161     GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
162     IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
163
164     parent_class = (IBusServiceClass *) g_type_class_peek_parent (klass);
165
166     g_type_class_add_private (klass, sizeof (IBusEnginePrivate));
167
168     gobject_class->set_property = (GObjectSetPropertyFunc) ibus_engine_set_property;
169     gobject_class->get_property = (GObjectGetPropertyFunc) ibus_engine_get_property;
170
171     ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_engine_destroy;
172
173     IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) ibus_engine_ibus_message;
174
175     klass->process_key_event = ibus_engine_process_key_event;
176     klass->focus_in     = ibus_engine_focus_in;
177     klass->focus_out    = ibus_engine_focus_out;
178     klass->reset        = ibus_engine_reset;
179     klass->enable       = ibus_engine_enable;
180     klass->disable      = ibus_engine_disable;
181     klass->page_up      = ibus_engine_page_up;
182     klass->page_down    = ibus_engine_page_down;
183     klass->cursor_up    = ibus_engine_cursor_up;
184     klass->cursor_down  = ibus_engine_cursor_down;
185     klass->property_activate    = ibus_engine_property_activate;
186     klass->property_show        = ibus_engine_property_show;
187     klass->property_hide        = ibus_engine_property_hide;
188     klass->set_cursor_location  = ibus_engine_set_cursor_location;
189     klass->set_capabilities     = ibus_engine_set_capabilities;
190
191
192     /* install properties */
193     g_object_class_install_property (gobject_class,
194                     PROP_NAME,
195                     g_param_spec_string ("name",
196                         "name",
197                         "engine name",
198                         "noname",
199                         G_PARAM_READWRITE |  G_PARAM_CONSTRUCT_ONLY));
200
201
202     g_object_class_install_property (gobject_class,
203                     PROP_CONNECTION,
204                     g_param_spec_object ("connection",
205                         "connection",
206                         "The connection of engine object",
207                         IBUS_TYPE_CONNECTION,
208                         G_PARAM_READWRITE |  G_PARAM_CONSTRUCT_ONLY));
209
210     /* install signals */
211     engine_signals[PROCESS_KEY_EVENT] =
212         g_signal_new (I_("process-key-event"),
213             G_TYPE_FROM_CLASS (gobject_class),
214             G_SIGNAL_RUN_LAST,
215             G_STRUCT_OFFSET (IBusEngineClass, process_key_event),
216             NULL, NULL,
217             ibus_marshal_BOOL__UINT_UINT,
218             G_TYPE_BOOLEAN,
219             2,
220             G_TYPE_UINT,
221             G_TYPE_UINT);
222
223     engine_signals[FOCUS_IN] =
224         g_signal_new (I_("focus-in"),
225             G_TYPE_FROM_CLASS (gobject_class),
226             G_SIGNAL_RUN_LAST,
227             G_STRUCT_OFFSET (IBusEngineClass, focus_in),
228             NULL, NULL,
229             ibus_marshal_VOID__VOID,
230             G_TYPE_NONE,
231             0);
232
233     engine_signals[FOCUS_OUT] =
234         g_signal_new (I_("focus-out"),
235             G_TYPE_FROM_CLASS (gobject_class),
236             G_SIGNAL_RUN_LAST,
237             G_STRUCT_OFFSET (IBusEngineClass, focus_out),
238             NULL, NULL,
239             ibus_marshal_VOID__VOID,
240             G_TYPE_NONE,
241             0);
242
243     engine_signals[RESET] =
244         g_signal_new (I_("reset"),
245             G_TYPE_FROM_CLASS (gobject_class),
246             G_SIGNAL_RUN_LAST,
247             G_STRUCT_OFFSET (IBusEngineClass, reset),
248             NULL, NULL,
249             ibus_marshal_VOID__VOID,
250             G_TYPE_NONE,
251             0);
252
253     engine_signals[ENABLE] =
254         g_signal_new (I_("enable"),
255             G_TYPE_FROM_CLASS (gobject_class),
256             G_SIGNAL_RUN_LAST,
257             G_STRUCT_OFFSET (IBusEngineClass, enable),
258             NULL, NULL,
259             ibus_marshal_VOID__VOID,
260             G_TYPE_NONE,
261             0);
262
263     engine_signals[DISABLE] =
264         g_signal_new (I_("disable"),
265             G_TYPE_FROM_CLASS (gobject_class),
266             G_SIGNAL_RUN_LAST,
267             G_STRUCT_OFFSET (IBusEngineClass, disable),
268             NULL, NULL,
269             ibus_marshal_VOID__VOID,
270             G_TYPE_NONE,
271             0);
272
273     engine_signals[SET_CURSOR_LOCATION] =
274         g_signal_new (I_("set-cursor-location"),
275             G_TYPE_FROM_CLASS (gobject_class),
276             G_SIGNAL_RUN_LAST,
277             G_STRUCT_OFFSET (IBusEngineClass, set_cursor_location),
278             NULL, NULL,
279             ibus_marshal_VOID__INT_INT_INT_INT,
280             G_TYPE_NONE,
281             4,
282             G_TYPE_INT,
283             G_TYPE_INT,
284             G_TYPE_INT,
285             G_TYPE_INT);
286
287     engine_signals[SET_CAPABILITIES] =
288         g_signal_new (I_("set-capabilities"),
289             G_TYPE_FROM_CLASS (gobject_class),
290             G_SIGNAL_RUN_LAST,
291             G_STRUCT_OFFSET (IBusEngineClass, set_capabilities),
292             NULL, NULL,
293             ibus_marshal_VOID__UINT,
294             G_TYPE_NONE,
295             1,
296             G_TYPE_UINT);
297
298     engine_signals[PAGE_UP] =
299         g_signal_new (I_("page-up"),
300             G_TYPE_FROM_CLASS (gobject_class),
301             G_SIGNAL_RUN_LAST,
302             G_STRUCT_OFFSET (IBusEngineClass, page_up),
303             NULL, NULL,
304             ibus_marshal_VOID__VOID,
305             G_TYPE_NONE,
306             0);
307
308     engine_signals[PAGE_DOWN] =
309         g_signal_new (I_("page-down"),
310             G_TYPE_FROM_CLASS (gobject_class),
311             G_SIGNAL_RUN_LAST,
312             G_STRUCT_OFFSET (IBusEngineClass, page_down),
313             NULL, NULL,
314             ibus_marshal_VOID__VOID,
315             G_TYPE_NONE,
316             0);
317
318     engine_signals[CURSOR_UP] =
319         g_signal_new (I_("cursor-up"),
320             G_TYPE_FROM_CLASS (gobject_class),
321             G_SIGNAL_RUN_LAST,
322             G_STRUCT_OFFSET (IBusEngineClass, cursor_up),
323             NULL, NULL,
324             ibus_marshal_VOID__VOID,
325             G_TYPE_NONE,
326             0);
327
328     engine_signals[CURSOR_DOWN] =
329         g_signal_new (I_("cursor-down"),
330             G_TYPE_FROM_CLASS (gobject_class),
331             G_SIGNAL_RUN_LAST,
332             G_STRUCT_OFFSET (IBusEngineClass, cursor_down),
333             NULL, NULL,
334             ibus_marshal_VOID__VOID,
335             G_TYPE_NONE,
336             0);
337
338     engine_signals[PROPERTY_ACTIVATE] =
339         g_signal_new (I_("property-activate"),
340             G_TYPE_FROM_CLASS (gobject_class),
341             G_SIGNAL_RUN_LAST,
342             G_STRUCT_OFFSET (IBusEngineClass, property_activate),
343             NULL, NULL,
344             ibus_marshal_VOID__STRING_INT,
345             G_TYPE_NONE,
346             2,
347             G_TYPE_STRING,
348             G_TYPE_INT);
349
350     engine_signals[PROPERTY_SHOW] =
351         g_signal_new (I_("property-show"),
352             G_TYPE_FROM_CLASS (gobject_class),
353             G_SIGNAL_RUN_LAST,
354             G_STRUCT_OFFSET (IBusEngineClass, property_show),
355             NULL, NULL,
356             ibus_marshal_VOID__STRING,
357             G_TYPE_NONE,
358             1,
359             G_TYPE_STRING);
360
361     engine_signals[PROPERTY_HIDE] =
362         g_signal_new (I_("property-hide"),
363             G_TYPE_FROM_CLASS (gobject_class),
364             G_SIGNAL_RUN_LAST,
365             G_STRUCT_OFFSET (IBusEngineClass, property_hide),
366             NULL, NULL,
367             ibus_marshal_VOID__STRING,
368             G_TYPE_NONE,
369             1,
370             G_TYPE_STRING);
371
372 }
373
374 static void
375 ibus_engine_init (IBusEngine *engine)
376 {
377     IBusEnginePrivate *priv;
378     priv = IBUS_ENGINE_GET_PRIVATE (engine);
379
380     priv->name = NULL;
381     priv->connection = NULL;
382 }
383
384 static void
385 ibus_engine_destroy (IBusEngine *engine)
386 {
387     IBusEnginePrivate *priv;
388     priv = IBUS_ENGINE_GET_PRIVATE (engine);
389
390     g_free (priv->name);
391
392     if (priv->connection) {
393         g_object_unref (priv->connection);
394         priv->connection = NULL;
395     }
396
397     IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (engine));
398 }
399
400 static void
401 ibus_engine_set_property (IBusEngine   *engine,
402                           guint         prop_id,
403                           const GValue *value,
404                           GParamSpec   *pspec)
405 {
406     IBusEnginePrivate *priv;
407     priv = IBUS_ENGINE_GET_PRIVATE (engine);
408
409     switch (prop_id) {
410     case PROP_NAME:
411         priv->name = g_strdup (g_value_dup_string (value));
412         break;
413
414     case PROP_CONNECTION:
415         priv->connection = g_value_get_object (value);
416         g_object_ref (priv->connection);
417         ibus_service_add_to_connection ((IBusService *) engine,
418                                         priv->connection);
419         break;
420
421     default:
422         G_OBJECT_WARN_INVALID_PROPERTY_ID (engine, prop_id, pspec);
423     }
424 }
425
426 static void
427 ibus_engine_get_property (IBusEngine *engine,
428     guint prop_id, GValue *value, GParamSpec *pspec)
429 {
430     IBusEnginePrivate *priv;
431     priv = IBUS_ENGINE_GET_PRIVATE (engine);
432
433     switch (prop_id) {
434     case PROP_NAME:
435         g_value_set_string (value, priv->name);
436         break;
437
438     case PROP_CONNECTION:
439         g_value_set_object (value, priv->connection);
440         break;
441
442     default:
443         G_OBJECT_WARN_INVALID_PROPERTY_ID (engine, prop_id, pspec);
444     }
445 }
446
447 static gboolean
448 ibus_engine_ibus_message (IBusEngine     *engine,
449                           IBusConnection *connection,
450                           IBusMessage    *message)
451 {
452     g_assert (IBUS_IS_ENGINE (engine));
453     g_assert (IBUS_IS_CONNECTION (connection));
454     g_assert (message != NULL);
455
456     IBusEnginePrivate *priv;
457     priv = IBUS_ENGINE_GET_PRIVATE (engine);
458
459     g_assert (priv->connection == connection);
460
461     IBusMessage *return_message = NULL;
462     IBusMessage *error_message = NULL;
463
464     static const struct {
465         gchar *member;
466         guint  signal_id;
467     } no_arg_methods[] = {
468         {"FocusIn",     FOCUS_IN},
469         {"FocusOut",    FOCUS_OUT},
470         {"Reset",       RESET},
471         {"Enable",      ENABLE},
472         {"Disable",     DISABLE},
473         {"PageUp",      PAGE_UP},
474         {"PageDown",    PAGE_DOWN},
475         {"CursorUp",    CURSOR_UP},
476         {"CursorDown",  CURSOR_DOWN},
477         {NULL, 0},
478     };
479     gint i;
480
481     for (i = 0; no_arg_methods[i].member != NULL; i++) {
482         if (!ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, no_arg_methods[i].member))
483             continue;
484
485         IBusMessageIter iter;
486         ibus_message_iter_init (message, &iter);
487         if (ibus_message_iter_has_next (&iter)) {
488             error_message = ibus_message_new_error_printf (message,
489                                 "%s.%s: Method does not have arguments",
490                                 IBUS_INTERFACE_ENGINE, no_arg_methods[i].member);
491             ibus_connection_send (connection, error_message);
492             ibus_message_unref (error_message);
493             return TRUE;
494         }
495
496         g_signal_emit (engine, engine_signals[no_arg_methods[i].signal_id], 0);
497         return_message = ibus_message_new_method_return (message);
498         ibus_connection_send (connection, return_message);
499         ibus_message_unref (return_message);
500         return TRUE;
501     }
502
503
504     if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "ProcessKeyEvent")) {
505         guint keyval, state;
506         gboolean retval;
507         IBusError *error = NULL;
508
509         retval = ibus_message_get_args (message,
510                                         &error,
511                                         G_TYPE_UINT, &keyval,
512                                         G_TYPE_UINT, &state,
513                                         G_TYPE_INVALID);
514
515         if (!retval)
516             goto _keypress_fail;
517
518         retval = FALSE;
519         g_signal_emit (engine,
520                        engine_signals[PROCESS_KEY_EVENT],
521                        0,
522                        keyval,
523                        state,
524                        &retval);
525
526         return_message = ibus_message_new_method_return (message);
527         ibus_message_append_args (return_message,
528                                   G_TYPE_BOOLEAN, &retval,
529                                   G_TYPE_INVALID);
530         ibus_connection_send (connection, return_message);
531         ibus_message_unref (return_message);
532         return TRUE;
533
534     _keypress_fail:
535         error_message = ibus_message_new_error_printf (message,
536                         "%s.%s: Can not match signature (ubu) of method",
537                         IBUS_INTERFACE_ENGINE, "ProcessKeyEvent");
538         ibus_connection_send (connection, error_message);
539         ibus_message_unref (error_message);
540         return TRUE;
541     }
542     else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyActivate")) {
543         gchar *name;
544         gint state;
545         gboolean retval;
546         IBusError *error = NULL;
547
548         retval = ibus_message_get_args (message,
549                                         &error,
550                                         G_TYPE_STRING, &name,
551                                         G_TYPE_INT, &state,
552                                         G_TYPE_INVALID);
553
554         if (!retval)
555             goto _property_activate_fail;
556
557         g_signal_emit (engine,
558                        engine_signals[PROPERTY_ACTIVATE],
559                        0,
560                        name,
561                        state);
562
563         return_message = ibus_message_new_method_return (message);
564         ibus_connection_send (connection, return_message);
565         ibus_message_unref (return_message);
566         return TRUE;
567
568     _property_activate_fail:
569         error_message = ibus_message_new_error_printf (message,
570                         "%s.%s: Can not match signature (si) of method",
571                         IBUS_INTERFACE_ENGINE,
572                         "PropertyActivate");
573         ibus_connection_send (connection, error_message);
574         ibus_message_unref (error_message);
575         return TRUE;
576
577     }
578     else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyShow")) {
579         gchar *name;
580         gboolean retval;
581         IBusError *error;
582
583         retval = ibus_message_get_args (message,
584                                         &error,
585                                         G_TYPE_STRING, &name,
586                                         G_TYPE_INVALID);
587
588         if (!retval)
589             goto _property_show_fail;
590
591         g_signal_emit (engine,
592                        engine_signals[PROPERTY_SHOW],
593                        0,
594                        name);
595
596         return_message = ibus_message_new_method_return (message);
597         ibus_connection_send (connection, return_message);
598         ibus_message_unref (return_message);
599         return TRUE;
600
601     _property_show_fail:
602         error_message = ibus_message_new_error_printf (message,
603                         "%s.%s: Can not match signature (s) of method",
604                         IBUS_INTERFACE_ENGINE,
605                         "PropertyShow");
606         ibus_connection_send (connection, error_message);
607         ibus_message_unref (error_message);
608         return TRUE;
609     }
610     else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyHide")) {
611         gchar *name;
612         gboolean retval;
613         IBusError *error = NULL;
614
615         retval = ibus_message_get_args (message,
616                                         &error,
617                                         G_TYPE_STRING, &name,
618                                         G_TYPE_INVALID);
619         if (!retval)
620             goto _property_hide_fail;
621
622         g_signal_emit (engine, engine_signals[PROPERTY_HIDE], 0, name);
623
624         return_message = ibus_message_new_method_return (message);
625         ibus_connection_send (connection, return_message);
626         ibus_message_unref (return_message);
627         return TRUE;
628
629     _property_hide_fail:
630         error_message = ibus_message_new_error_printf (message,
631                         "%s.%s: Can not match signature (s) of method",
632                         IBUS_INTERFACE_ENGINE, "PropertyHide");
633         ibus_connection_send (connection, error_message);
634         ibus_message_unref (error_message);
635         return TRUE;
636     }
637     else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "SetCursorLocation")) {
638         gint x, y, w, h;
639         gboolean retval;
640         IBusError *error = NULL;
641
642         retval = ibus_message_get_args (message,
643                                         &error,
644                                         G_TYPE_INT, &x,
645                                         G_TYPE_INT, &y,
646                                         G_TYPE_INT, &w,
647                                         G_TYPE_INT, &h,
648                                         G_TYPE_INVALID);
649         if (!retval)
650             goto _set_cursor_location_fail;
651
652         engine->cursor_area.x = x;
653         engine->cursor_area.y = y;
654         engine->cursor_area.width = w;
655         engine->cursor_area.height = h;
656
657         g_signal_emit (engine,
658                        engine_signals[SET_CURSOR_LOCATION],
659                        0,
660                        x, y, w, h);
661
662         return_message = ibus_message_new_method_return (message);
663         ibus_connection_send (connection, return_message);
664         ibus_message_unref (return_message);
665         return TRUE;
666
667     _set_cursor_location_fail:
668         error_message = ibus_message_new_error_printf (message,
669                         "%s.%s: Can not match signature (iiii) of method",
670                         IBUS_INTERFACE_ENGINE,
671                         "SetCursorLocation");
672         ibus_connection_send (connection, error_message);
673         ibus_message_unref (error_message);
674         return TRUE;
675     }
676     else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "SetCapabilities")) {
677         guint caps;
678         gboolean retval;
679         IBusError *error = NULL;
680
681         retval = ibus_message_get_args (message,
682                                         &error,
683                                         G_TYPE_UINT, &caps,
684                                         G_TYPE_INVALID);
685
686         if (!retval)
687             goto _set_capabilities_fail;
688
689         engine->client_capabilities = caps;
690
691         g_signal_emit (engine, engine_signals[SET_CAPABILITIES], 0, caps);
692
693         return_message = ibus_message_new_method_return (message);
694         ibus_connection_send (connection, return_message);
695         ibus_message_unref (return_message);
696         return TRUE;
697
698     _set_capabilities_fail:
699         error_message = ibus_message_new_error_printf (message,
700                         "%s.%s: Can not match signature (u) of method",
701                         IBUS_INTERFACE_ENGINE, "SetCapabilities");
702         ibus_connection_send (connection, error_message);
703         ibus_message_unref (error_message);
704         return TRUE;
705     }
706     else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "Destroy")) {
707         return_message = ibus_message_new_method_return (message);
708
709         ibus_connection_send (connection, return_message);
710         ibus_message_unref (return_message);
711
712         ibus_object_destroy ((IBusObject *) engine);
713     }
714
715     return parent_class->ibus_message ((IBusService *) engine, connection, message);
716 }
717
718 static gboolean
719 ibus_engine_process_key_event (IBusEngine *engine,
720                                guint       keyval,
721                                guint       state)
722 {
723     // g_debug ("process-key-event (%d, %d)", keyval, state);
724     return FALSE;
725 }
726
727 static void
728 ibus_engine_focus_in (IBusEngine *engine)
729 {
730     // g_debug ("focus-in");
731 }
732
733 static void
734 ibus_engine_focus_out (IBusEngine *engine)
735 {
736     // g_debug ("focus-out");
737 }
738
739 static void
740 ibus_engine_reset (IBusEngine *engine)
741 {
742     // g_debug ("reset");
743 }
744
745 static void
746 ibus_engine_enable (IBusEngine *engine)
747 {
748     // g_debug ("enable");
749 }
750
751 static void
752 ibus_engine_disable (IBusEngine *engine)
753 {
754     // g_debug ("disable");
755 }
756
757 static void
758 ibus_engine_set_cursor_location (IBusEngine *engine,
759                                  gint        x,
760                                  gint        y,
761                                  gint        w,
762                                  gint        h)
763 {
764     // g_debug ("set-cursor-location (%d, %d, %d, %d)", x, y, w, h);
765 }
766
767 static void
768 ibus_engine_set_capabilities (IBusEngine *engine,
769                               guint       caps)
770 {
771     // g_debug ("set-capabilities (0x%04x)", caps);
772 }
773
774 static void
775 ibus_engine_page_up (IBusEngine *engine)
776 {
777     // g_debug ("page-up");
778 }
779
780 static void
781 ibus_engine_page_down (IBusEngine *engine)
782 {
783     // g_debug ("page-down");
784 }
785
786 static void
787 ibus_engine_cursor_up (IBusEngine *engine)
788 {
789     // g_debug ("cursor-up");
790 }
791
792 static void
793 ibus_engine_cursor_down (IBusEngine *engine)
794 {
795     // g_debug ("cursor-down");
796 }
797
798 static void
799 ibus_engine_property_activate (IBusEngine *engine,
800     const gchar *prop_name, gint prop_state)
801 {
802     // g_debug ("property-activate ('%s', %d)", prop_name, prop_state);
803 }
804
805 static void
806 ibus_engine_property_show (IBusEngine *engine, const gchar *prop_name)
807 {
808     // g_debug ("property-show ('%s')", prop_name);
809 }
810
811 static void
812 ibus_engine_property_hide (IBusEngine *engine, const gchar *prop_name)
813 {
814     // g_debug ("property-hide ('%s')", prop_name);
815 }
816
817 static void
818 _send_signal (IBusEngine  *engine,
819               const gchar *name,
820               GType        first_arg_type,
821               ...)
822 {
823     g_assert (IBUS_IS_ENGINE (engine));
824     g_assert (name != NULL);
825
826     va_list args;
827     const gchar *path;
828     IBusEnginePrivate *priv;
829
830     priv = IBUS_ENGINE_GET_PRIVATE (engine);
831
832     path = ibus_service_get_path ((IBusService *)engine);
833
834     va_start (args, first_arg_type);
835     ibus_connection_send_signal_valist (priv->connection,
836                                         path,
837                                         IBUS_INTERFACE_ENGINE,
838                                         name,
839                                         first_arg_type,
840                                         args);
841     va_end (args);
842 }
843
844 void
845 ibus_engine_commit_text (IBusEngine *engine,
846                          IBusText   *text)
847 {
848     _send_signal (engine,
849                   "CommitText",
850                   IBUS_TYPE_TEXT, &text,
851                   G_TYPE_INVALID);
852 }
853
854 void
855 ibus_engine_update_preedit_text (IBusEngine      *engine,
856                                  IBusText        *text,
857                                  guint            cursor_pos,
858                                  gboolean         visible)
859 {
860     _send_signal (engine,
861                   "UpdatePreeditText",
862                   IBUS_TYPE_TEXT, &text,
863                   G_TYPE_UINT, &cursor_pos,
864                   G_TYPE_BOOLEAN, &visible,
865                   G_TYPE_INVALID);
866 }
867
868 void
869 ibus_engine_show_preedit_text (IBusEngine *engine)
870 {
871     _send_signal (engine,
872                   "ShowPreeditText",
873                   G_TYPE_INVALID);
874 }
875
876 void ibus_engine_hide_preedit_text (IBusEngine *engine)
877 {
878     _send_signal (engine,
879                   "HidePreeditText",
880                   G_TYPE_INVALID);
881 }
882
883 void ibus_engine_update_auxiliary_text (IBusEngine      *engine,
884                                         IBusText        *text,
885                                         gboolean         visible)
886 {
887     _send_signal (engine,
888                   "UpdateAuxiliaryText",
889                   IBUS_TYPE_TEXT, &text,
890                   G_TYPE_BOOLEAN, &visible,
891                   G_TYPE_INVALID);
892 }
893
894 void
895 ibus_engine_show_auxiliary_text (IBusEngine *engine)
896 {
897     _send_signal (engine,
898                   "ShowAuxiliaryText",
899                   G_TYPE_INVALID);
900 }
901
902 void
903 ibus_engine_hide_auxiliary_text (IBusEngine *engine)
904 {
905     _send_signal (engine,
906                   "HideAuxiliaryText",
907                   G_TYPE_INVALID);
908 }
909
910 void ibus_engine_update_lookup_table (IBusEngine        *engine,
911                                       IBusLookupTable   *table,
912                                       gboolean           visible)
913 {
914     _send_signal (engine,
915                   "UpdateLookupTable",
916                   IBUS_TYPE_LOOKUP_TABLE, &table,
917                   G_TYPE_BOOLEAN, &visible,
918                   G_TYPE_INVALID);
919 }
920
921 void ibus_engine_show_lookup_table (IBusEngine *engine)
922 {
923     _send_signal (engine,
924                   "ShowLookupTable",
925                   G_TYPE_INVALID);
926 }
927
928 void ibus_engine_hide_lookup_table (IBusEngine *engine)
929 {
930     _send_signal (engine,
931                   "HideLookupTable",
932                   G_TYPE_INVALID);
933 }
934
935 void ibus_engine_forward_key_event (IBusEngine      *engine,
936                                     guint            keyval,
937                                     gboolean         is_press,
938                                     guint            state)
939 {
940     _send_signal (engine,
941                   "HideLookupTable",
942                   G_TYPE_UINT, &keyval,
943                   G_TYPE_BOOLEAN, &is_press,
944                   G_TYPE_UINT, &state,
945                   G_TYPE_INVALID);
946 }
947
948 void
949 ibus_engine_register_properties (IBusEngine   *engine,
950                                  IBusPropList *prop_list)
951 {
952     _send_signal (engine,
953                   "RegisterProperties",
954                   IBUS_TYPE_PROP_LIST, &prop_list,
955                   G_TYPE_INVALID);
956 }
957
958 void
959 ibus_engine_update_property (IBusEngine   *engine,
960                              IBusProperty *prop)
961 {
962     _send_signal (engine,
963                   "UpdateProperty",
964                   IBUS_TYPE_PROPERTY, &prop,
965                   G_TYPE_INVALID);
966 }
967
968 const gchar *
969 ibus_engine_get_name (IBusEngine *engine)
970 {
971     g_assert (IBUS_IS_ENGINE (engine));
972
973     IBusEnginePrivate *priv;
974     priv = IBUS_ENGINE_GET_PRIVATE (engine);
975
976     return priv->name;
977 }
978