dbeb091cf4fae9a8de0665f99e5922a0ee0f9d57
[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                                 DBUS_ERROR_INVALID_ARGS,
490                                 "%s.%s: Method does not have arguments",
491                                 IBUS_INTERFACE_ENGINE, no_arg_methods[i].member);
492             ibus_connection_send (connection, error_message);
493             ibus_message_unref (error_message);
494             return TRUE;
495         }
496
497         g_signal_emit (engine, engine_signals[no_arg_methods[i].signal_id], 0);
498         return_message = ibus_message_new_method_return (message);
499         ibus_connection_send (connection, return_message);
500         ibus_message_unref (return_message);
501         return TRUE;
502     }
503
504
505     if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "ProcessKeyEvent")) {
506         guint keyval, state;
507         gboolean retval;
508         IBusError *error = NULL;
509
510         retval = ibus_message_get_args (message,
511                                         &error,
512                                         G_TYPE_UINT, &keyval,
513                                         G_TYPE_UINT, &state,
514                                         G_TYPE_INVALID);
515
516         if (!retval)
517             goto _keypress_fail;
518
519         retval = FALSE;
520         g_signal_emit (engine,
521                        engine_signals[PROCESS_KEY_EVENT],
522                        0,
523                        keyval,
524                        state,
525                        &retval);
526
527         return_message = ibus_message_new_method_return (message);
528         ibus_message_append_args (return_message,
529                                   G_TYPE_BOOLEAN, &retval,
530                                   G_TYPE_INVALID);
531         ibus_connection_send (connection, return_message);
532         ibus_message_unref (return_message);
533         return TRUE;
534
535     _keypress_fail:
536         error_message = ibus_message_new_error_printf (message,
537                         DBUS_ERROR_INVALID_ARGS,
538                         "%s.%s: Can not match signature (ubu) of method",
539                         IBUS_INTERFACE_ENGINE, "ProcessKeyEvent");
540         ibus_connection_send (connection, error_message);
541         ibus_message_unref (error_message);
542         return TRUE;
543     }
544     else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyActivate")) {
545         gchar *name;
546         gint state;
547         gboolean retval;
548         IBusError *error = NULL;
549
550         retval = ibus_message_get_args (message,
551                                         &error,
552                                         G_TYPE_STRING, &name,
553                                         G_TYPE_INT, &state,
554                                         G_TYPE_INVALID);
555
556         if (!retval)
557             goto _property_activate_fail;
558
559         g_signal_emit (engine,
560                        engine_signals[PROPERTY_ACTIVATE],
561                        0,
562                        name,
563                        state);
564
565         return_message = ibus_message_new_method_return (message);
566         ibus_connection_send (connection, return_message);
567         ibus_message_unref (return_message);
568         return TRUE;
569
570     _property_activate_fail:
571         error_message = ibus_message_new_error_printf (message,
572                         DBUS_ERROR_INVALID_ARGS,
573                         "%s.%s: Can not match signature (si) of method",
574                         IBUS_INTERFACE_ENGINE,
575                         "PropertyActivate");
576         ibus_connection_send (connection, error_message);
577         ibus_message_unref (error_message);
578         return TRUE;
579
580     }
581     else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyShow")) {
582         gchar *name;
583         gboolean retval;
584         IBusError *error;
585
586         retval = ibus_message_get_args (message,
587                                         &error,
588                                         G_TYPE_STRING, &name,
589                                         G_TYPE_INVALID);
590
591         if (!retval)
592             goto _property_show_fail;
593
594         g_signal_emit (engine,
595                        engine_signals[PROPERTY_SHOW],
596                        0,
597                        name);
598
599         return_message = ibus_message_new_method_return (message);
600         ibus_connection_send (connection, return_message);
601         ibus_message_unref (return_message);
602         return TRUE;
603
604     _property_show_fail:
605         error_message = ibus_message_new_error_printf (message,
606                         DBUS_ERROR_INVALID_ARGS,
607                         "%s.%s: Can not match signature (s) of method",
608                         IBUS_INTERFACE_ENGINE,
609                         "PropertyShow");
610         ibus_connection_send (connection, error_message);
611         ibus_message_unref (error_message);
612         return TRUE;
613     }
614     else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyHide")) {
615         gchar *name;
616         gboolean retval;
617         IBusError *error = NULL;
618
619         retval = ibus_message_get_args (message,
620                                         &error,
621                                         G_TYPE_STRING, &name,
622                                         G_TYPE_INVALID);
623         if (!retval)
624             goto _property_hide_fail;
625
626         g_signal_emit (engine, engine_signals[PROPERTY_HIDE], 0, name);
627
628         return_message = ibus_message_new_method_return (message);
629         ibus_connection_send (connection, return_message);
630         ibus_message_unref (return_message);
631         return TRUE;
632
633     _property_hide_fail:
634         error_message = ibus_message_new_error_printf (message,
635                         DBUS_ERROR_INVALID_ARGS,
636                         "%s.%s: Can not match signature (s) of method",
637                         IBUS_INTERFACE_ENGINE, "PropertyHide");
638         ibus_connection_send (connection, error_message);
639         ibus_message_unref (error_message);
640         return TRUE;
641     }
642     else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "SetCursorLocation")) {
643         gint x, y, w, h;
644         gboolean retval;
645         IBusError *error = NULL;
646
647         retval = ibus_message_get_args (message,
648                                         &error,
649                                         G_TYPE_INT, &x,
650                                         G_TYPE_INT, &y,
651                                         G_TYPE_INT, &w,
652                                         G_TYPE_INT, &h,
653                                         G_TYPE_INVALID);
654         if (!retval)
655             goto _set_cursor_location_fail;
656
657         engine->cursor_area.x = x;
658         engine->cursor_area.y = y;
659         engine->cursor_area.width = w;
660         engine->cursor_area.height = h;
661
662         g_signal_emit (engine,
663                        engine_signals[SET_CURSOR_LOCATION],
664                        0,
665                        x, y, w, h);
666
667         return_message = ibus_message_new_method_return (message);
668         ibus_connection_send (connection, return_message);
669         ibus_message_unref (return_message);
670         return TRUE;
671
672     _set_cursor_location_fail:
673         error_message = ibus_message_new_error_printf (message,
674                         DBUS_ERROR_INVALID_ARGS,
675                         "%s.%s: Can not match signature (iiii) of method",
676                         IBUS_INTERFACE_ENGINE,
677                         "SetCursorLocation");
678         ibus_connection_send (connection, error_message);
679         ibus_message_unref (error_message);
680         return TRUE;
681     }
682     else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "SetCapabilities")) {
683         guint caps;
684         gboolean retval;
685         IBusError *error = NULL;
686
687         retval = ibus_message_get_args (message,
688                                         &error,
689                                         G_TYPE_UINT, &caps,
690                                         G_TYPE_INVALID);
691
692         if (!retval)
693             goto _set_capabilities_fail;
694
695         engine->client_capabilities = caps;
696
697         g_signal_emit (engine, engine_signals[SET_CAPABILITIES], 0, caps);
698
699         return_message = ibus_message_new_method_return (message);
700         ibus_connection_send (connection, return_message);
701         ibus_message_unref (return_message);
702         return TRUE;
703
704     _set_capabilities_fail:
705         error_message = ibus_message_new_error_printf (message,
706                         DBUS_ERROR_INVALID_ARGS,
707                         "%s.%s: Can not match signature (u) of method",
708                         IBUS_INTERFACE_ENGINE, "SetCapabilities");
709         ibus_connection_send (connection, error_message);
710         ibus_message_unref (error_message);
711         return TRUE;
712     }
713     else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "Destroy")) {
714         return_message = ibus_message_new_method_return (message);
715
716         ibus_connection_send (connection, return_message);
717         ibus_message_unref (return_message);
718
719         ibus_object_destroy ((IBusObject *) engine);
720     }
721
722     return parent_class->ibus_message ((IBusService *) engine, connection, message);
723 }
724
725 static gboolean
726 ibus_engine_process_key_event (IBusEngine *engine,
727                                guint       keyval,
728                                guint       state)
729 {
730     // g_debug ("process-key-event (%d, %d)", keyval, state);
731     return FALSE;
732 }
733
734 static void
735 ibus_engine_focus_in (IBusEngine *engine)
736 {
737     // g_debug ("focus-in");
738 }
739
740 static void
741 ibus_engine_focus_out (IBusEngine *engine)
742 {
743     // g_debug ("focus-out");
744 }
745
746 static void
747 ibus_engine_reset (IBusEngine *engine)
748 {
749     // g_debug ("reset");
750 }
751
752 static void
753 ibus_engine_enable (IBusEngine *engine)
754 {
755     // g_debug ("enable");
756 }
757
758 static void
759 ibus_engine_disable (IBusEngine *engine)
760 {
761     // g_debug ("disable");
762 }
763
764 static void
765 ibus_engine_set_cursor_location (IBusEngine *engine,
766                                  gint        x,
767                                  gint        y,
768                                  gint        w,
769                                  gint        h)
770 {
771     // g_debug ("set-cursor-location (%d, %d, %d, %d)", x, y, w, h);
772 }
773
774 static void
775 ibus_engine_set_capabilities (IBusEngine *engine,
776                               guint       caps)
777 {
778     // g_debug ("set-capabilities (0x%04x)", caps);
779 }
780
781 static void
782 ibus_engine_page_up (IBusEngine *engine)
783 {
784     // g_debug ("page-up");
785 }
786
787 static void
788 ibus_engine_page_down (IBusEngine *engine)
789 {
790     // g_debug ("page-down");
791 }
792
793 static void
794 ibus_engine_cursor_up (IBusEngine *engine)
795 {
796     // g_debug ("cursor-up");
797 }
798
799 static void
800 ibus_engine_cursor_down (IBusEngine *engine)
801 {
802     // g_debug ("cursor-down");
803 }
804
805 static void
806 ibus_engine_property_activate (IBusEngine *engine,
807     const gchar *prop_name, gint prop_state)
808 {
809     // g_debug ("property-activate ('%s', %d)", prop_name, prop_state);
810 }
811
812 static void
813 ibus_engine_property_show (IBusEngine *engine, const gchar *prop_name)
814 {
815     // g_debug ("property-show ('%s')", prop_name);
816 }
817
818 static void
819 ibus_engine_property_hide (IBusEngine *engine, const gchar *prop_name)
820 {
821     // g_debug ("property-hide ('%s')", prop_name);
822 }
823
824 static void
825 _send_signal (IBusEngine  *engine,
826               const gchar *name,
827               GType        first_arg_type,
828               ...)
829 {
830     g_assert (IBUS_IS_ENGINE (engine));
831     g_assert (name != NULL);
832
833     va_list args;
834     const gchar *path;
835     IBusEnginePrivate *priv;
836
837     priv = IBUS_ENGINE_GET_PRIVATE (engine);
838
839     path = ibus_service_get_path ((IBusService *)engine);
840
841     va_start (args, first_arg_type);
842     ibus_connection_send_signal_valist (priv->connection,
843                                         path,
844                                         IBUS_INTERFACE_ENGINE,
845                                         name,
846                                         first_arg_type,
847                                         args);
848     va_end (args);
849 }
850
851 void
852 ibus_engine_commit_text (IBusEngine *engine,
853                          IBusText   *text)
854 {
855     _send_signal (engine,
856                   "CommitText",
857                   IBUS_TYPE_TEXT, &text,
858                   G_TYPE_INVALID);
859 }
860
861 void
862 ibus_engine_update_preedit_text (IBusEngine      *engine,
863                                  IBusText        *text,
864                                  guint            cursor_pos,
865                                  gboolean         visible)
866 {
867     _send_signal (engine,
868                   "UpdatePreeditText",
869                   IBUS_TYPE_TEXT, &text,
870                   G_TYPE_UINT, &cursor_pos,
871                   G_TYPE_BOOLEAN, &visible,
872                   G_TYPE_INVALID);
873 }
874
875 void
876 ibus_engine_show_preedit_text (IBusEngine *engine)
877 {
878     _send_signal (engine,
879                   "ShowPreeditText",
880                   G_TYPE_INVALID);
881 }
882
883 void ibus_engine_hide_preedit_text (IBusEngine *engine)
884 {
885     _send_signal (engine,
886                   "HidePreeditText",
887                   G_TYPE_INVALID);
888 }
889
890 void ibus_engine_update_auxiliary_text (IBusEngine      *engine,
891                                         IBusText        *text,
892                                         gboolean         visible)
893 {
894     _send_signal (engine,
895                   "UpdateAuxiliaryText",
896                   IBUS_TYPE_TEXT, &text,
897                   G_TYPE_BOOLEAN, &visible,
898                   G_TYPE_INVALID);
899 }
900
901 void
902 ibus_engine_show_auxiliary_text (IBusEngine *engine)
903 {
904     _send_signal (engine,
905                   "ShowAuxiliaryText",
906                   G_TYPE_INVALID);
907 }
908
909 void
910 ibus_engine_hide_auxiliary_text (IBusEngine *engine)
911 {
912     _send_signal (engine,
913                   "HideAuxiliaryText",
914                   G_TYPE_INVALID);
915 }
916
917 void ibus_engine_update_lookup_table (IBusEngine        *engine,
918                                       IBusLookupTable   *table,
919                                       gboolean           visible)
920 {
921     _send_signal (engine,
922                   "UpdateLookupTable",
923                   IBUS_TYPE_LOOKUP_TABLE, &table,
924                   G_TYPE_BOOLEAN, &visible,
925                   G_TYPE_INVALID);
926 }
927
928 void ibus_engine_show_lookup_table (IBusEngine *engine)
929 {
930     _send_signal (engine,
931                   "ShowLookupTable",
932                   G_TYPE_INVALID);
933 }
934
935 void ibus_engine_hide_lookup_table (IBusEngine *engine)
936 {
937     _send_signal (engine,
938                   "HideLookupTable",
939                   G_TYPE_INVALID);
940 }
941
942 void ibus_engine_forward_key_event (IBusEngine      *engine,
943                                     guint            keyval,
944                                     gboolean         is_press,
945                                     guint            state)
946 {
947     _send_signal (engine,
948                   "HideLookupTable",
949                   G_TYPE_UINT, &keyval,
950                   G_TYPE_BOOLEAN, &is_press,
951                   G_TYPE_UINT, &state,
952                   G_TYPE_INVALID);
953 }
954
955 void
956 ibus_engine_register_properties (IBusEngine   *engine,
957                                  IBusPropList *prop_list)
958 {
959     _send_signal (engine,
960                   "RegisterProperties",
961                   IBUS_TYPE_PROP_LIST, &prop_list,
962                   G_TYPE_INVALID);
963 }
964
965 void
966 ibus_engine_update_property (IBusEngine   *engine,
967                              IBusProperty *prop)
968 {
969     _send_signal (engine,
970                   "UpdateProperty",
971                   IBUS_TYPE_PROPERTY, &prop,
972                   G_TYPE_INVALID);
973 }
974
975 const gchar *
976 ibus_engine_get_name (IBusEngine *engine)
977 {
978     g_assert (IBUS_IS_ENGINE (engine));
979
980     IBusEnginePrivate *priv;
981     priv = IBUS_ENGINE_GET_PRIVATE (engine);
982
983     return priv->name;
984 }
985