1 /* vim:set et sts=4: */
2 /* ibus - The Input Bus
3 * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com>
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.
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.
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.
22 #include "ibusengine.h"
23 #include "ibusinternal.h"
24 #include "ibusshare.h"
26 #define IBUS_ENGINE_GET_PRIVATE(o) \
27 (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_ENGINE, IBusEnginePrivate))
56 struct _IBusEnginePrivate {
58 IBusConnection *connection;
60 typedef struct _IBusEnginePrivate IBusEnginePrivate;
62 static guint engine_signals[LAST_SIGNAL] = { 0 };
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,
72 static void ibus_engine_get_property (IBusEngine *engine,
76 static gboolean ibus_engine_ibus_message (IBusEngine *engine,
77 IBusConnection *connection,
78 IBusMessage *message);
79 static gboolean ibus_engine_process_key_event
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
94 static void ibus_engine_set_capabilities
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
103 const gchar *prop_name,
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);
111 static IBusServiceClass *parent_class = NULL;
114 ibus_engine_get_type (void)
116 static GType type = 0;
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 */
127 (GInstanceInitFunc) ibus_engine_init,
131 type = g_type_register_static (IBUS_TYPE_SERVICE,
140 ibus_engine_new (const gchar *name,
142 IBusConnection *connection)
145 g_assert (IBUS_IS_CONNECTION (connection));
149 engine = (IBusEngine *) g_object_new (IBUS_TYPE_ENGINE,
152 "connection", connection,
159 ibus_engine_class_init (IBusEngineClass *klass)
161 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
162 IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
164 parent_class = (IBusServiceClass *) g_type_class_peek_parent (klass);
166 g_type_class_add_private (klass, sizeof (IBusEnginePrivate));
168 gobject_class->set_property = (GObjectSetPropertyFunc) ibus_engine_set_property;
169 gobject_class->get_property = (GObjectGetPropertyFunc) ibus_engine_get_property;
171 ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_engine_destroy;
173 IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) ibus_engine_ibus_message;
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;
192 /* install properties */
193 g_object_class_install_property (gobject_class,
195 g_param_spec_string ("name",
199 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
202 g_object_class_install_property (gobject_class,
204 g_param_spec_object ("connection",
206 "The connection of engine object",
207 IBUS_TYPE_CONNECTION,
208 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
210 /* install signals */
211 engine_signals[PROCESS_KEY_EVENT] =
212 g_signal_new (I_("process-key-event"),
213 G_TYPE_FROM_CLASS (gobject_class),
215 G_STRUCT_OFFSET (IBusEngineClass, process_key_event),
217 ibus_marshal_BOOL__UINT_UINT,
223 engine_signals[FOCUS_IN] =
224 g_signal_new (I_("focus-in"),
225 G_TYPE_FROM_CLASS (gobject_class),
227 G_STRUCT_OFFSET (IBusEngineClass, focus_in),
229 ibus_marshal_VOID__VOID,
233 engine_signals[FOCUS_OUT] =
234 g_signal_new (I_("focus-out"),
235 G_TYPE_FROM_CLASS (gobject_class),
237 G_STRUCT_OFFSET (IBusEngineClass, focus_out),
239 ibus_marshal_VOID__VOID,
243 engine_signals[RESET] =
244 g_signal_new (I_("reset"),
245 G_TYPE_FROM_CLASS (gobject_class),
247 G_STRUCT_OFFSET (IBusEngineClass, reset),
249 ibus_marshal_VOID__VOID,
253 engine_signals[ENABLE] =
254 g_signal_new (I_("enable"),
255 G_TYPE_FROM_CLASS (gobject_class),
257 G_STRUCT_OFFSET (IBusEngineClass, enable),
259 ibus_marshal_VOID__VOID,
263 engine_signals[DISABLE] =
264 g_signal_new (I_("disable"),
265 G_TYPE_FROM_CLASS (gobject_class),
267 G_STRUCT_OFFSET (IBusEngineClass, disable),
269 ibus_marshal_VOID__VOID,
273 engine_signals[SET_CURSOR_LOCATION] =
274 g_signal_new (I_("set-cursor-location"),
275 G_TYPE_FROM_CLASS (gobject_class),
277 G_STRUCT_OFFSET (IBusEngineClass, set_cursor_location),
279 ibus_marshal_VOID__INT_INT_INT_INT,
287 engine_signals[SET_CAPABILITIES] =
288 g_signal_new (I_("set-capabilities"),
289 G_TYPE_FROM_CLASS (gobject_class),
291 G_STRUCT_OFFSET (IBusEngineClass, set_capabilities),
293 ibus_marshal_VOID__UINT,
298 engine_signals[PAGE_UP] =
299 g_signal_new (I_("page-up"),
300 G_TYPE_FROM_CLASS (gobject_class),
302 G_STRUCT_OFFSET (IBusEngineClass, page_up),
304 ibus_marshal_VOID__VOID,
308 engine_signals[PAGE_DOWN] =
309 g_signal_new (I_("page-down"),
310 G_TYPE_FROM_CLASS (gobject_class),
312 G_STRUCT_OFFSET (IBusEngineClass, page_down),
314 ibus_marshal_VOID__VOID,
318 engine_signals[CURSOR_UP] =
319 g_signal_new (I_("cursor-up"),
320 G_TYPE_FROM_CLASS (gobject_class),
322 G_STRUCT_OFFSET (IBusEngineClass, cursor_up),
324 ibus_marshal_VOID__VOID,
328 engine_signals[CURSOR_DOWN] =
329 g_signal_new (I_("cursor-down"),
330 G_TYPE_FROM_CLASS (gobject_class),
332 G_STRUCT_OFFSET (IBusEngineClass, cursor_down),
334 ibus_marshal_VOID__VOID,
338 engine_signals[PROPERTY_ACTIVATE] =
339 g_signal_new (I_("property-activate"),
340 G_TYPE_FROM_CLASS (gobject_class),
342 G_STRUCT_OFFSET (IBusEngineClass, property_activate),
344 ibus_marshal_VOID__STRING_INT,
350 engine_signals[PROPERTY_SHOW] =
351 g_signal_new (I_("property-show"),
352 G_TYPE_FROM_CLASS (gobject_class),
354 G_STRUCT_OFFSET (IBusEngineClass, property_show),
356 ibus_marshal_VOID__STRING,
361 engine_signals[PROPERTY_HIDE] =
362 g_signal_new (I_("property-hide"),
363 G_TYPE_FROM_CLASS (gobject_class),
365 G_STRUCT_OFFSET (IBusEngineClass, property_hide),
367 ibus_marshal_VOID__STRING,
375 ibus_engine_init (IBusEngine *engine)
377 IBusEnginePrivate *priv;
378 priv = IBUS_ENGINE_GET_PRIVATE (engine);
381 priv->connection = NULL;
385 ibus_engine_destroy (IBusEngine *engine)
387 IBusEnginePrivate *priv;
388 priv = IBUS_ENGINE_GET_PRIVATE (engine);
392 if (priv->connection) {
393 g_object_unref (priv->connection);
394 priv->connection = NULL;
397 IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (engine));
401 ibus_engine_set_property (IBusEngine *engine,
406 IBusEnginePrivate *priv;
407 priv = IBUS_ENGINE_GET_PRIVATE (engine);
411 priv->name = g_strdup (g_value_dup_string (value));
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,
422 G_OBJECT_WARN_INVALID_PROPERTY_ID (engine, prop_id, pspec);
427 ibus_engine_get_property (IBusEngine *engine,
428 guint prop_id, GValue *value, GParamSpec *pspec)
430 IBusEnginePrivate *priv;
431 priv = IBUS_ENGINE_GET_PRIVATE (engine);
435 g_value_set_string (value, priv->name);
438 case PROP_CONNECTION:
439 g_value_set_object (value, priv->connection);
443 G_OBJECT_WARN_INVALID_PROPERTY_ID (engine, prop_id, pspec);
448 ibus_engine_ibus_message (IBusEngine *engine,
449 IBusConnection *connection,
450 IBusMessage *message)
452 g_assert (IBUS_IS_ENGINE (engine));
453 g_assert (IBUS_IS_CONNECTION (connection));
454 g_assert (message != NULL);
456 IBusEnginePrivate *priv;
457 priv = IBUS_ENGINE_GET_PRIVATE (engine);
459 g_assert (priv->connection == connection);
461 IBusMessage *return_message = NULL;
462 IBusMessage *error_message = NULL;
464 static const struct {
467 } no_arg_methods[] = {
468 {"FocusIn", FOCUS_IN},
469 {"FocusOut", FOCUS_OUT},
472 {"Disable", DISABLE},
474 {"PageDown", PAGE_DOWN},
475 {"CursorUp", CURSOR_UP},
476 {"CursorDown", CURSOR_DOWN},
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))
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);
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);
505 if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "ProcessKeyEvent")) {
508 IBusError *error = NULL;
510 retval = ibus_message_get_args (message,
512 G_TYPE_UINT, &keyval,
520 g_signal_emit (engine,
521 engine_signals[PROCESS_KEY_EVENT],
527 return_message = ibus_message_new_method_return (message);
528 ibus_message_append_args (return_message,
529 G_TYPE_BOOLEAN, &retval,
531 ibus_connection_send (connection, return_message);
532 ibus_message_unref (return_message);
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);
544 else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyActivate")) {
548 IBusError *error = NULL;
550 retval = ibus_message_get_args (message,
552 G_TYPE_STRING, &name,
557 goto _property_activate_fail;
559 g_signal_emit (engine,
560 engine_signals[PROPERTY_ACTIVATE],
565 return_message = ibus_message_new_method_return (message);
566 ibus_connection_send (connection, return_message);
567 ibus_message_unref (return_message);
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,
576 ibus_connection_send (connection, error_message);
577 ibus_message_unref (error_message);
581 else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyShow")) {
586 retval = ibus_message_get_args (message,
588 G_TYPE_STRING, &name,
592 goto _property_show_fail;
594 g_signal_emit (engine,
595 engine_signals[PROPERTY_SHOW],
599 return_message = ibus_message_new_method_return (message);
600 ibus_connection_send (connection, return_message);
601 ibus_message_unref (return_message);
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,
610 ibus_connection_send (connection, error_message);
611 ibus_message_unref (error_message);
614 else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyHide")) {
617 IBusError *error = NULL;
619 retval = ibus_message_get_args (message,
621 G_TYPE_STRING, &name,
624 goto _property_hide_fail;
626 g_signal_emit (engine, engine_signals[PROPERTY_HIDE], 0, name);
628 return_message = ibus_message_new_method_return (message);
629 ibus_connection_send (connection, return_message);
630 ibus_message_unref (return_message);
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);
642 else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "SetCursorLocation")) {
645 IBusError *error = NULL;
647 retval = ibus_message_get_args (message,
655 goto _set_cursor_location_fail;
657 engine->cursor_area.x = x;
658 engine->cursor_area.y = y;
659 engine->cursor_area.width = w;
660 engine->cursor_area.height = h;
662 g_signal_emit (engine,
663 engine_signals[SET_CURSOR_LOCATION],
667 return_message = ibus_message_new_method_return (message);
668 ibus_connection_send (connection, return_message);
669 ibus_message_unref (return_message);
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);
682 else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "SetCapabilities")) {
685 IBusError *error = NULL;
687 retval = ibus_message_get_args (message,
693 goto _set_capabilities_fail;
695 engine->client_capabilities = caps;
697 g_signal_emit (engine, engine_signals[SET_CAPABILITIES], 0, caps);
699 return_message = ibus_message_new_method_return (message);
700 ibus_connection_send (connection, return_message);
701 ibus_message_unref (return_message);
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);
713 else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "Destroy")) {
714 return_message = ibus_message_new_method_return (message);
716 ibus_connection_send (connection, return_message);
717 ibus_message_unref (return_message);
719 ibus_object_destroy ((IBusObject *) engine);
722 return parent_class->ibus_message ((IBusService *) engine, connection, message);
726 ibus_engine_process_key_event (IBusEngine *engine,
730 // g_debug ("process-key-event (%d, %d)", keyval, state);
735 ibus_engine_focus_in (IBusEngine *engine)
737 // g_debug ("focus-in");
741 ibus_engine_focus_out (IBusEngine *engine)
743 // g_debug ("focus-out");
747 ibus_engine_reset (IBusEngine *engine)
749 // g_debug ("reset");
753 ibus_engine_enable (IBusEngine *engine)
755 // g_debug ("enable");
759 ibus_engine_disable (IBusEngine *engine)
761 // g_debug ("disable");
765 ibus_engine_set_cursor_location (IBusEngine *engine,
771 // g_debug ("set-cursor-location (%d, %d, %d, %d)", x, y, w, h);
775 ibus_engine_set_capabilities (IBusEngine *engine,
778 // g_debug ("set-capabilities (0x%04x)", caps);
782 ibus_engine_page_up (IBusEngine *engine)
784 // g_debug ("page-up");
788 ibus_engine_page_down (IBusEngine *engine)
790 // g_debug ("page-down");
794 ibus_engine_cursor_up (IBusEngine *engine)
796 // g_debug ("cursor-up");
800 ibus_engine_cursor_down (IBusEngine *engine)
802 // g_debug ("cursor-down");
806 ibus_engine_property_activate (IBusEngine *engine,
807 const gchar *prop_name, gint prop_state)
809 // g_debug ("property-activate ('%s', %d)", prop_name, prop_state);
813 ibus_engine_property_show (IBusEngine *engine, const gchar *prop_name)
815 // g_debug ("property-show ('%s')", prop_name);
819 ibus_engine_property_hide (IBusEngine *engine, const gchar *prop_name)
821 // g_debug ("property-hide ('%s')", prop_name);
825 _send_signal (IBusEngine *engine,
827 GType first_arg_type,
830 g_assert (IBUS_IS_ENGINE (engine));
831 g_assert (name != NULL);
835 IBusEnginePrivate *priv;
837 priv = IBUS_ENGINE_GET_PRIVATE (engine);
839 path = ibus_service_get_path ((IBusService *)engine);
841 va_start (args, first_arg_type);
842 ibus_connection_send_signal_valist (priv->connection,
844 IBUS_INTERFACE_ENGINE,
852 ibus_engine_commit_text (IBusEngine *engine,
855 _send_signal (engine,
857 IBUS_TYPE_TEXT, &text,
862 ibus_engine_update_preedit_text (IBusEngine *engine,
867 _send_signal (engine,
869 IBUS_TYPE_TEXT, &text,
870 G_TYPE_UINT, &cursor_pos,
871 G_TYPE_BOOLEAN, &visible,
876 ibus_engine_show_preedit_text (IBusEngine *engine)
878 _send_signal (engine,
883 void ibus_engine_hide_preedit_text (IBusEngine *engine)
885 _send_signal (engine,
890 void ibus_engine_update_auxiliary_text (IBusEngine *engine,
894 _send_signal (engine,
895 "UpdateAuxiliaryText",
896 IBUS_TYPE_TEXT, &text,
897 G_TYPE_BOOLEAN, &visible,
902 ibus_engine_show_auxiliary_text (IBusEngine *engine)
904 _send_signal (engine,
910 ibus_engine_hide_auxiliary_text (IBusEngine *engine)
912 _send_signal (engine,
917 void ibus_engine_update_lookup_table (IBusEngine *engine,
918 IBusLookupTable *table,
921 _send_signal (engine,
923 IBUS_TYPE_LOOKUP_TABLE, &table,
924 G_TYPE_BOOLEAN, &visible,
928 void ibus_engine_show_lookup_table (IBusEngine *engine)
930 _send_signal (engine,
935 void ibus_engine_hide_lookup_table (IBusEngine *engine)
937 _send_signal (engine,
942 void ibus_engine_forward_key_event (IBusEngine *engine,
947 _send_signal (engine,
949 G_TYPE_UINT, &keyval,
950 G_TYPE_BOOLEAN, &is_press,
956 ibus_engine_register_properties (IBusEngine *engine,
957 IBusPropList *prop_list)
959 _send_signal (engine,
960 "RegisterProperties",
961 IBUS_TYPE_PROP_LIST, &prop_list,
966 ibus_engine_update_property (IBusEngine *engine,
969 _send_signal (engine,
971 IBUS_TYPE_PROPERTY, &prop,
976 ibus_engine_get_name (IBusEngine *engine)
978 g_assert (IBUS_IS_ENGINE (engine));
980 IBusEnginePrivate *priv;
981 priv = IBUS_ENGINE_GET_PRIVATE (engine);