diff options
Diffstat (limited to 'bus/engineproxy.c')
-rw-r--r-- | bus/engineproxy.c | 716 |
1 files changed, 716 insertions, 0 deletions
diff --git a/bus/engineproxy.c b/bus/engineproxy.c new file mode 100644 index 0000000..963dfe2 --- /dev/null +++ b/bus/engineproxy.c @@ -0,0 +1,716 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <ibusinternal.h> +#include <ibusmarshalers.h> +#include "engineproxy.h" + +#define BUS_ENGINE_PROXY_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), BUS_TYPE_ENGINE_PROXY, BusEngineProxyPrivate)) + +enum { + COMMIT_TEXT, + FORWARD_KEY_EVENT, + UPDATE_PREEDIT_TEXT, + SHOW_PREEDIT_TEXT, + HIDE_PREEDIT_TEXT, + UPDATE_AUXILIARY_TEXT, + SHOW_AUXILIARY_TEXT, + HIDE_AUXILIARY_TEXT, + UPDATE_LOOKUP_TABLE, + SHOW_LOOKUP_TABLE, + HIDE_LOOKUP_TABLE, + PAGE_UP_LOOKUP_TABLE, + PAGE_DOWN_LOOKUP_TABLE, + CURSOR_UP_LOOKUP_TABLE, + CURSOR_DOWN_LOOKUP_TABLE, + REGISTER_PROPERTIES, + UPDATE_PROPERTY, + LAST_SIGNAL, +}; + + +/* BusEngineProxyPriv */ +struct _BusEngineProxyPrivate { + gboolean enabled; + IBusEngineDesc *desc; + + IBusPropList *prop_list; +}; +typedef struct _BusEngineProxyPrivate BusEngineProxyPrivate; + +static guint engine_signals[LAST_SIGNAL] = { 0 }; +// static guint engine_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void bus_engine_proxy_class_init (BusEngineProxyClass *klass); +static void bus_engine_proxy_init (BusEngineProxy *engine); +static void bus_engine_proxy_real_destroy (BusEngineProxy *engine); + +static gboolean bus_engine_proxy_ibus_signal (IBusProxy *proxy, + IBusMessage *message); + +static IBusProxyClass *parent_class = NULL; + +GType +bus_engine_proxy_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (BusEngineProxyClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) bus_engine_proxy_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (BusEngineProxy), + 0, + (GInstanceInitFunc) bus_engine_proxy_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_PROXY, + "BusEngineProxy", + &type_info, + (GTypeFlags)0); + } + return type; +} + +BusEngineProxy * +bus_engine_proxy_new (const gchar *path, + IBusEngineDesc *desc, + BusConnection *connection) +{ + g_assert (path); + g_assert (IBUS_IS_ENGINE_DESC (desc)); + g_assert (BUS_IS_CONNECTION (connection)); + + BusEngineProxy *engine; + + engine = (BusEngineProxy *) g_object_new (BUS_TYPE_ENGINE_PROXY, + "name", NULL, + "path", path, + "connection", connection, + NULL); + + BusEngineProxyPrivate *priv; + priv = BUS_ENGINE_PROXY_GET_PRIVATE (engine); + priv->desc = desc; + g_object_ref (desc); + + return engine; +} + +static void +bus_engine_proxy_class_init (BusEngineProxyClass *klass) +{ + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + IBusProxyClass *proxy_class = IBUS_PROXY_CLASS (klass); + + + parent_class = (IBusProxyClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (BusEngineProxyPrivate)); + + ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_engine_proxy_real_destroy; + + proxy_class->ibus_signal = bus_engine_proxy_ibus_signal; + + /* install signals */ + engine_signals[COMMIT_TEXT] = + g_signal_new (I_("commit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + IBUS_TYPE_TEXT); + + engine_signals[FORWARD_KEY_EVENT] = + g_signal_new (I_("forward-key-event"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__UINT_UINT, + G_TYPE_NONE, + 2, + G_TYPE_UINT, + G_TYPE_UINT); + + engine_signals[UPDATE_PREEDIT_TEXT] = + g_signal_new (I_("update-preedit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT_UINT_BOOLEAN, + G_TYPE_NONE, + 3, + IBUS_TYPE_TEXT, + G_TYPE_UINT, + G_TYPE_BOOLEAN); + + engine_signals[SHOW_PREEDIT_TEXT] = + g_signal_new (I_("show-preedit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[HIDE_PREEDIT_TEXT] = + g_signal_new (I_("hide-preedit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[UPDATE_AUXILIARY_TEXT] = + g_signal_new (I_("update-auxiliary-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT_BOOLEAN, + G_TYPE_NONE, + 2, + IBUS_TYPE_TEXT, + G_TYPE_BOOLEAN); + + engine_signals[SHOW_AUXILIARY_TEXT] = + g_signal_new (I_("show-auxiliary-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[HIDE_AUXILIARY_TEXT] = + g_signal_new (I_("hide-auxiliary-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[UPDATE_LOOKUP_TABLE] = + g_signal_new (I_("update-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__BOXED_BOOLEAN, + G_TYPE_NONE, + 2, + IBUS_TYPE_LOOKUP_TABLE, + G_TYPE_BOOLEAN); + + engine_signals[SHOW_LOOKUP_TABLE] = + g_signal_new (I_("show-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[HIDE_LOOKUP_TABLE] = + g_signal_new (I_("hide-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[PAGE_UP_LOOKUP_TABLE] = + g_signal_new (I_("page-up-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[PAGE_DOWN_LOOKUP_TABLE] = + g_signal_new (I_("page-down-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[CURSOR_UP_LOOKUP_TABLE] = + g_signal_new (I_("cursor-up-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[CURSOR_DOWN_LOOKUP_TABLE] = + g_signal_new (I_("cursor-down-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + engine_signals[REGISTER_PROPERTIES] = + g_signal_new (I_("register-properties"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + IBUS_TYPE_PROP_LIST); + + engine_signals[UPDATE_PROPERTY] = + g_signal_new (I_("update-property"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + IBUS_TYPE_PROPERTY); + +} + +static void +bus_engine_proxy_init (BusEngineProxy *engine) +{ + BusEngineProxyPrivate *priv; + priv = BUS_ENGINE_PROXY_GET_PRIVATE (engine); + + priv->enabled = FALSE; + priv->prop_list = NULL; + priv->desc = NULL; +} + +static void +bus_engine_proxy_real_destroy (BusEngineProxy *engine) +{ + BusEngineProxyPrivate *priv; + priv = BUS_ENGINE_PROXY_GET_PRIVATE (engine); + + if (priv->prop_list) { + g_object_unref (priv->prop_list); + priv->prop_list = NULL; + } + + if (ibus_proxy_get_connection ((IBusProxy *) engine)) { + ibus_proxy_call ((IBusProxy *) engine, + "Destroy", + DBUS_TYPE_INVALID); + } + + if (priv->desc) { + g_object_unref (priv->desc); + priv->desc = NULL; + } + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (engine)); +} + +static gboolean +bus_engine_proxy_ibus_signal (IBusProxy *proxy, + IBusMessage *message) +{ + g_assert (BUS_IS_ENGINE_PROXY (proxy)); + g_assert (message != NULL); + + BusEngineProxy *engine; + BusEngineProxyPrivate *priv; + IBusError *error; + gint i; + + static const struct { + const gchar *member; + const guint signal_id; + } signals [] = { + { "ShowPreeditText", SHOW_PREEDIT_TEXT }, + { "HidePreeditText", HIDE_PREEDIT_TEXT }, + { "ShowAuxiliaryText", SHOW_AUXILIARY_TEXT }, + { "HideAuxiliaryText", HIDE_AUXILIARY_TEXT }, + { "ShowLookupTable", SHOW_LOOKUP_TABLE }, + { "HideLookupTable", HIDE_LOOKUP_TABLE }, + { "PageUpLookupTable", PAGE_UP_LOOKUP_TABLE }, + { "PageDownLookupTable", PAGE_DOWN_LOOKUP_TABLE }, + { "CursorUpLookupTable", CURSOR_UP_LOOKUP_TABLE }, + { "CursorDownLookupTable", CURSOR_DOWN_LOOKUP_TABLE }, + { NULL, 0}, + }; + + engine = BUS_ENGINE_PROXY (proxy); + priv = BUS_ENGINE_PROXY_GET_PRIVATE (engine); + + for (i = 0; ; i++) { + if (signals[i].member == NULL) + break; + if (ibus_message_is_signal (message, IBUS_INTERFACE_ENGINE, signals[i].member)) { + g_signal_emit (engine, engine_signals[signals[i].signal_id], 0); + goto handled; + } + } + + if (ibus_message_is_signal (message, IBUS_INTERFACE_ENGINE, "CommitText")) { + IBusText *text; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_TEXT, &text, + G_TYPE_INVALID); + if (!retval) + goto failed; + g_signal_emit (engine, engine_signals[COMMIT_TEXT], 0, text); + g_object_unref (text); + } + else if (ibus_message_is_signal (message, IBUS_INTERFACE_ENGINE, "ForwardKeyEvent")) { + guint keyval; + guint states; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_UINT, &keyval, + G_TYPE_UINT, &states, + G_TYPE_INVALID); + + if (!retval) + goto failed; + g_signal_emit (engine, engine_signals[FORWARD_KEY_EVENT], keyval, states); + } + else if (ibus_message_is_signal (message, IBUS_INTERFACE_ENGINE, "UpdatePreeditText")) { + IBusText *text; + gint cursor_pos; + gboolean visible; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_TEXT, &text, + G_TYPE_UINT, &cursor_pos, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); + + if (!retval) + goto failed; + + g_signal_emit (engine, engine_signals[UPDATE_PREEDIT_TEXT], 0, + text, cursor_pos, visible); + g_object_unref (text); + } + else if (ibus_message_is_signal (message, IBUS_INTERFACE_ENGINE, "UpdateAuxiliaryText")) { + IBusText *text; + gboolean visible; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_TEXT, &text, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); + + if (!retval) + goto failed; + + g_signal_emit (engine, engine_signals[UPDATE_AUXILIARY_TEXT], 0, text, visible); + g_object_unref (text); + } + else if (ibus_message_is_signal (message, IBUS_INTERFACE_ENGINE, "UpdateLookupTable")) { + IBusLookupTable *table; + gboolean visible; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_LOOKUP_TABLE, &table, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); + + if (!retval) + goto failed; + + g_signal_emit (engine, engine_signals[UPDATE_LOOKUP_TABLE], 0, table, visible); + g_object_unref (table); + } + else if (ibus_message_is_signal (message, IBUS_INTERFACE_ENGINE, "RegisterProperties")) { + gboolean retval; + + if (priv->prop_list) { + g_object_unref (priv->prop_list); + priv->prop_list = NULL; + } + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_PROP_LIST, &priv->prop_list, + G_TYPE_INVALID); + if (!retval) { + priv->prop_list = NULL; + goto failed; + } + g_signal_emit (engine, engine_signals[REGISTER_PROPERTIES], 0, priv->prop_list); + } + else if (ibus_message_is_signal (message, IBUS_INTERFACE_ENGINE, "UpdateProperty")) { + IBusProperty *prop; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_PROPERTY, &prop, + G_TYPE_INVALID); + + if (!retval) + goto failed; + + g_signal_emit (engine, engine_signals[UPDATE_PROPERTY], 0, prop); + g_object_unref (prop); + } + else { + return FALSE; + } + +handled: + g_signal_stop_emission_by_name (engine, "ibus-signal"); + return TRUE; + +failed: + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + return FALSE; +} + +typedef struct { + GFunc func; + gpointer user_data; +}CallData; + +static void +bus_engine_proxy_process_key_event_reply_cb (IBusPendingCall *pending, + CallData *call_data) +{ + IBusMessage *reply_message; + IBusError *error; + gboolean retval; + + reply_message = dbus_pending_call_steal_reply (pending); + + if ((error = ibus_error_new_from_message (reply_message)) != NULL) { + g_warning ("%s: %s", error->name, error->message); + ibus_message_unref (reply_message); + ibus_error_free (error); + call_data->func(FALSE, call_data->user_data); + return; + } + + if (!ibus_message_get_args (reply_message, + &error, + G_TYPE_BOOLEAN, &retval, + G_TYPE_INVALID)) { + g_warning ("%s: %s", error->name, error->message); + ibus_message_unref (reply_message); + ibus_error_free (error); + call_data->func(FALSE, call_data->user_data); + return; + } + + call_data->func((gpointer *)retval, call_data->user_data); + g_slice_free (CallData, call_data); +} + +void +bus_engine_proxy_process_key_event (BusEngineProxy *engine, + guint keyval, + guint state, + GFunc return_cb, + gpointer user_data) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (return_cb); + + IBusPendingCall *pending = NULL; + CallData *call_data; + IBusError *error; + gboolean retval; + + retval = ibus_proxy_call_with_reply ((IBusProxy *) engine, + "ProcessKeyEvent", + &pending, + -1, + &error, + G_TYPE_UINT, &keyval, + G_TYPE_UINT, &state, + G_TYPE_INVALID); + if (!retval) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + return_cb (FALSE, user_data); + return; + } + + call_data = g_slice_new0 (CallData); + call_data->func = return_cb; + call_data->user_data = user_data; + + retval = ibus_pending_call_set_notify (pending, + (IBusPendingCallNotifyFunction) bus_engine_proxy_process_key_event_reply_cb, + call_data, + NULL); + ibus_pending_call_unref (pending); + + if (!retval) { + g_warning ("%s : ProcessKeyEvent", DBUS_ERROR_NO_MEMORY); + return_cb (FALSE, user_data); + return; + } +} + +void +bus_engine_proxy_set_cursor_location (BusEngineProxy *engine, + gint x, + gint y, + gint w, + gint h) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + + ibus_proxy_call ((IBusProxy *) engine, + "SetCursorLocation", + G_TYPE_INT, &x, + G_TYPE_INT, &y, + G_TYPE_INT, &w, + G_TYPE_INT, &h, + G_TYPE_INVALID); +} + +void +bus_engine_proxy_set_capabilities (BusEngineProxy *engine, + guint caps) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + + ibus_proxy_call ((IBusProxy *) engine, + "SetCapabilites", + G_TYPE_UINT, &caps, + G_TYPE_INVALID); + +} + +void +bus_engine_proxy_property_activate (BusEngineProxy *engine, + const gchar *prop_name, + guint prop_state) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (prop_name != NULL); + + ibus_proxy_call ((IBusProxy *) engine, + "PropertyActivate", + G_TYPE_STRING, &prop_name, + G_TYPE_UINT, &prop_state, + G_TYPE_INVALID); +} + +void +bus_engine_proxy_property_show (BusEngineProxy *engine, + const gchar *prop_name) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (prop_name != NULL); + + ibus_proxy_call ((IBusProxy *) engine, + "PropertyShow", + G_TYPE_STRING, &prop_name, + G_TYPE_INVALID); +} + +void bus_engine_proxy_property_hide (BusEngineProxy *engine, + const gchar *prop_name) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (prop_name != NULL); + + ibus_proxy_call ((IBusProxy *) engine, + "PropertyHide", + G_TYPE_STRING, &prop_name, + G_TYPE_INVALID); +} + +#define DEFINE_FUNCTION(Name, name) \ + void bus_engine_proxy_##name (BusEngineProxy *engine) \ + { \ + g_assert (BUS_IS_ENGINE_PROXY (engine)); \ + ibus_proxy_call ((IBusProxy *) engine, \ + #Name, \ + DBUS_TYPE_INVALID); \ + } + +DEFINE_FUNCTION (FocusIn, focus_in) +DEFINE_FUNCTION (FocusOut, focus_out) +DEFINE_FUNCTION (Reset, reset) +DEFINE_FUNCTION (PageUp, page_up) +DEFINE_FUNCTION (PageDown, page_down) +DEFINE_FUNCTION (CursorUp, cursor_up) +DEFINE_FUNCTION (CursorDown, cursor_down) +DEFINE_FUNCTION (Enable, enable) +DEFINE_FUNCTION (Disable, disable) + +#undef DEFINE_FUNCTION + + +IBusEngineDesc * +bus_engine_proxy_get_desc (BusEngineProxy *engine) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + + BusEngineProxyPrivate *priv; + priv = BUS_ENGINE_PROXY_GET_PRIVATE (engine); + + return priv->desc; +} |