/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* vim:set et sts=4: */ /* ibus - The Input Bus * Copyright (C) 2008-2013 Peng Huang * Copyright (C) 2008-2013 Red Hat, Inc. * * 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA */ #include "ibusinputcontext.h" #include #include "ibusshare.h" #include "ibusinternal.h" #include "ibusmarshalers.h" #include "ibusattribute.h" #include "ibuslookuptable.h" #include "ibusproplist.h" #include "ibuserror.h" #define IBUS_INPUT_CONTEXT_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_INPUT_CONTEXT, IBusInputContextPrivate)) enum { ENABLED, DISABLED, COMMIT_TEXT, FORWARD_KEY_EVENT, DELETE_SURROUNDING_TEXT, 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, }; /* IBusInputContextPrivate */ struct _IBusInputContextPrivate { /* TRUE if the current engine needs surrounding text; FALSE otherwise */ gboolean needs_surrounding_text; /* cached surrounding text (see also IBusEnginePrivate and BusEngineProxy) */ IBusText *surrounding_text; guint surrounding_cursor_pos; guint selection_anchor_pos; }; typedef struct _IBusInputContextPrivate IBusInputContextPrivate; static guint context_signals[LAST_SIGNAL] = { 0 }; static IBusText *text_empty = NULL; /* functions prototype */ static void ibus_input_context_real_destroy (IBusProxy *context); static void ibus_input_context_g_signal (GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters); G_DEFINE_TYPE (IBusInputContext, ibus_input_context, IBUS_TYPE_PROXY) static void ibus_input_context_class_init (IBusInputContextClass *class) { IBusProxyClass *ibus_proxy_class = IBUS_PROXY_CLASS (class); GDBusProxyClass *g_dbus_proxy_class = G_DBUS_PROXY_CLASS (class); g_type_class_add_private (class, sizeof (IBusInputContextPrivate)); ibus_proxy_class->destroy = ibus_input_context_real_destroy; g_dbus_proxy_class->g_signal = ibus_input_context_g_signal; /* install signals */ /** * IBusInputContext::enabled: * @context: An IBusInputContext. * * Emitted when an IME is enabled. */ context_signals[ENABLED] = g_signal_new (I_("enabled"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IBusInputContext::disabled: * @context: An IBusInputContext. * * Emitted when an IME is disabled. */ context_signals[DISABLED] = g_signal_new (I_("disabled"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IBusInputContext::commit-text: * @context: An IBusInputContext. * @text: Text to be committed. * * Emitted when the text is going to be committed. * * (Note: The text object is floating, and it will be released after the * signal. If signal handler wants to keep the object, the handler should * use g_object_ref_sink() to get the ownership of the object.) */ context_signals[COMMIT_TEXT] = g_signal_new (I_("commit-text"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__OBJECT, G_TYPE_NONE, 1, IBUS_TYPE_TEXT); /** * IBusInputContext::forward-key-event: * @context: An IBusInputContext. * @keyval: Key symbol of the keyboard event. * @keycode: Key symbol of the keyboard event. * @modifiers: Key modifier flags. * * Emitted to forward key event from IME to client of IME. */ context_signals[FORWARD_KEY_EVENT] = g_signal_new (I_("forward-key-event"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__UINT_UINT_UINT, G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT); /** * IBusInputContext::delete-surrounding-text: * @context: An IBusInputContext. * @offset: the character offset from the cursor position of the text to be deleted. * A negative value indicates a position before the cursor. * @n_chars: the number of characters to be deleted. * * Emitted to delete surrounding text event from IME to client of IME. */ context_signals[DELETE_SURROUNDING_TEXT] = g_signal_new (I_("delete-surrounding-text"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__INT_UINT, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_UINT); /** * IBusInputContext::update-preedit-text: * @context: An IBusInputContext. * @text: Text to be updated. * @cursor_pos: Cursor position. * @visible: Whether the update is visible. * * Emitted to update preedit text. * * (Note: The text object is floating, and it will be released after the * signal. If signal handler wants to keep the object, the handler should * use g_object_ref_sink() to get the ownership of the object.) */ context_signals[UPDATE_PREEDIT_TEXT] = g_signal_new (I_("update-preedit-text"), G_TYPE_FROM_CLASS (class), 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); /** * IBusInputContext::show-preedit-text: * @context: An IBusInputContext. * * Emitted to show preedit text. */ context_signals[SHOW_PREEDIT_TEXT] = g_signal_new (I_("show-preedit-text"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IBusInputContext::hide-preedit-text: * @context: An IBusInputContext. * * Emitted to hide preedit text. */ context_signals[HIDE_PREEDIT_TEXT] = g_signal_new (I_("hide-preedit-text"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IBusInputContext::update-auxiliary-text: * @context: An IBusInputContext. * @text: An auxiliary text * @visible: The visibility of @text * * Emitted to hide auxilary text. * * (Note: The text object is floating, and it will be released after the * signal. If signal handler wants to keep the object, the handler should * use g_object_ref_sink() to get the ownership of the object.) */ context_signals[UPDATE_AUXILIARY_TEXT] = g_signal_new (I_("update-auxiliary-text"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__OBJECT_BOOLEAN, G_TYPE_NONE, 2, IBUS_TYPE_TEXT, G_TYPE_BOOLEAN); /** * IBusInputContext::show-auxiliary-text: * @context: An IBusInputContext. * * Emitted to show auxiliary text. */ context_signals[SHOW_AUXILIARY_TEXT] = g_signal_new (I_("show-auxiliary-text"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IBusInputContext::hide-auxiliary-text: * @context: An IBusInputContext. * * Emitted to hide auxiliary text. */ context_signals[HIDE_AUXILIARY_TEXT] = g_signal_new (I_("hide-auxiliary-text"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IBusInputContext::update-lookup-table: * @context: An IBusInputContext. * @table: An IBusLookupTable to be updated. * @visible: Whether the table should be visible. * * Emitted to update lookup table. * * (Note: The table object is floating, and it will be released after the * signal. If signal handler wants to keep the object, the handler should * use g_object_ref_sink() to get the ownership of the object.) */ context_signals[UPDATE_LOOKUP_TABLE] = g_signal_new (I_("update-lookup-table"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__OBJECT_BOOLEAN, G_TYPE_NONE, 2, IBUS_TYPE_LOOKUP_TABLE, G_TYPE_BOOLEAN); /** * IBusInputContext::show-lookup-table: * @context: An IBusInputContext. * * Emitted to show lookup table. */ context_signals[SHOW_LOOKUP_TABLE] = g_signal_new (I_("show-lookup-table"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IBusInputContext::hide-lookup-table: * @context: An IBusInputContext. * * Emitted to hide lookup table. */ context_signals[HIDE_LOOKUP_TABLE] = g_signal_new (I_("hide-lookup-table"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IBusInputContext::page-up-lookup-table: * @context: An IBusInputContext. * * Emitted to view the previous page of lookup table. */ context_signals[PAGE_UP_LOOKUP_TABLE] = g_signal_new (I_("page-up-lookup-table"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IBusInputContext::page-down-lookup-table: * @context: An IBusInputContext. * * Emitted to view the next page of lookup table. */ context_signals[PAGE_DOWN_LOOKUP_TABLE] = g_signal_new (I_("page-down-lookup-table"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IBusInputContext::cursor-up-lookup-table: * @context: An IBusInputContext. * * Emitted to select previous candidate of lookup table. */ context_signals[CURSOR_UP_LOOKUP_TABLE] = g_signal_new (I_("cursor-up-lookup-table"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IBusInputContext::cursor-down-lookup-table: * @context: An IBusInputContext. * * Emitted to select next candidate of lookup table. */ context_signals[CURSOR_DOWN_LOOKUP_TABLE] = g_signal_new (I_("cursor-down-lookup-table"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IBusInputContext::register-properties: * @context: An IBusInputContext. * @props: An IBusPropList that contains properties. * * Emitted to register the properties in @props. * * (Note: The props object is floating, and it will be released after the * signal. If signal handler wants to keep the object, the handler should * use g_object_ref_sink() to get the ownership of the object.) */ context_signals[REGISTER_PROPERTIES] = g_signal_new (I_("register-properties"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__OBJECT, G_TYPE_NONE, 1, IBUS_TYPE_PROP_LIST); /** * IBusInputContext::update-property: * @context: An IBusInputContext. * @prop: The IBusProperty to be updated. * * Emitted to update the property @prop. * * (Note: The prop object is floating, and it will be released after the * signal. If signal handler wants to keep the object, the handler should * use g_object_ref_sink() to get the ownership of the object.) */ context_signals[UPDATE_PROPERTY] = g_signal_new (I_("update-property"), G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _ibus_marshal_VOID__OBJECT, G_TYPE_NONE, 1, IBUS_TYPE_PROPERTY); text_empty = ibus_text_new_from_static_string (""); g_object_ref_sink (text_empty); } static void ibus_input_context_init (IBusInputContext *context) { IBusInputContextPrivate *priv; priv = IBUS_INPUT_CONTEXT_GET_PRIVATE (context); priv->surrounding_text = g_object_ref_sink (text_empty); } static void ibus_input_context_real_destroy (IBusProxy *context) { IBusInputContextPrivate *priv; priv = IBUS_INPUT_CONTEXT_GET_PRIVATE (IBUS_INPUT_CONTEXT (context)); if (priv->surrounding_text) { g_object_unref (priv->surrounding_text); priv->surrounding_text = NULL; } IBUS_PROXY_CLASS(ibus_input_context_parent_class)->destroy (context); } static void ibus_input_context_g_signal (GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters) { g_assert (IBUS_IS_INPUT_CONTEXT (proxy)); IBusInputContext *context; context = IBUS_INPUT_CONTEXT (proxy); static const struct { const gchar *signal_name; 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 }, }; if (g_strcmp0 (signal_name, "CommitText") == 0) { GVariant *variant = NULL; g_variant_get (parameters, "(v)", &variant); IBusText *text = IBUS_TEXT (ibus_serializable_deserialize (variant)); g_variant_unref (variant); g_signal_emit (context, context_signals[COMMIT_TEXT], 0, text); if (g_object_is_floating (text)) g_object_unref (text); return; } if (g_strcmp0 (signal_name, "UpdatePreeditText") == 0) { GVariant *variant = NULL; gint32 cursor_pos; gboolean visible; g_variant_get (parameters, "(vub)", &variant, &cursor_pos, &visible); IBusText *text = IBUS_TEXT (ibus_serializable_deserialize (variant)); g_variant_unref (variant); g_signal_emit (context, context_signals[UPDATE_PREEDIT_TEXT], 0, text, cursor_pos, visible); if (g_object_is_floating (text)) g_object_unref (text); return; } /* lookup signal in table */ gint i; for (i = 0; i < G_N_ELEMENTS (signals) && g_strcmp0 (signal_name, signals[i].signal_name) != 0; i++); if (i < G_N_ELEMENTS (signals)) { g_signal_emit (context, context_signals[signals[i].signal_id], 0); return; } if (g_strcmp0 (signal_name, "UpdateAuxiliaryText") == 0) { GVariant *variant = NULL; gboolean visible; g_variant_get (parameters, "(vb)", &variant, &visible); IBusText *text = IBUS_TEXT (ibus_serializable_deserialize (variant)); g_variant_unref (variant); g_signal_emit (context, context_signals[UPDATE_AUXILIARY_TEXT], 0, text, visible); if (g_object_is_floating (text)) g_object_unref (text); return; } if (g_strcmp0 (signal_name, "UpdateLookupTable") == 0) { GVariant *variant = NULL; gboolean visible; g_variant_get (parameters, "(vb)", &variant, &visible); IBusLookupTable *table = IBUS_LOOKUP_TABLE (ibus_serializable_deserialize (variant)); g_variant_unref (variant); g_signal_emit (context, context_signals[UPDATE_LOOKUP_TABLE], 0, table, visible); if (g_object_is_floating (table)) g_object_unref (table); return; } if (g_strcmp0 (signal_name, "RegisterProperties") == 0) { GVariant *variant = NULL; g_variant_get (parameters, "(v)", &variant); IBusPropList *prop_list = IBUS_PROP_LIST (ibus_serializable_deserialize (variant)); g_variant_unref (variant); g_signal_emit (context, context_signals[REGISTER_PROPERTIES], 0, prop_list); if (g_object_is_floating (prop_list)) g_object_unref (prop_list); return; } if (g_strcmp0 (signal_name, "UpdateProperty") == 0) { GVariant *variant = NULL; g_variant_get (parameters, "(v)", &variant); IBusProperty *prop = IBUS_PROPERTY (ibus_serializable_deserialize (variant)); g_variant_unref (variant); g_signal_emit (context, context_signals[UPDATE_PROPERTY], 0, prop); if (g_object_is_floating (prop)) g_object_unref (prop); return; } if (g_strcmp0 (signal_name, "ForwardKeyEvent") == 0) { guint32 keyval; guint32 keycode; guint32 state; g_variant_get (parameters, "(uuu)", &keyval, &keycode, &state); /* Forward key event back with IBUS_FORWARD_MASK. And process_key_event will * not process key event with IBUS_FORWARD_MASK again. */ g_signal_emit (context, context_signals[FORWARD_KEY_EVENT], 0, keyval, keycode, state | IBUS_FORWARD_MASK); return; } if (g_strcmp0 (signal_name, "DeleteSurroundingText") == 0) { gint offset_from_cursor; guint nchars; g_variant_get (parameters, "(iu)", &offset_from_cursor, &nchars); g_signal_emit (context, context_signals[DELETE_SURROUNDING_TEXT], 0, offset_from_cursor, nchars); return; } IBusInputContextPrivate *priv; priv = IBUS_INPUT_CONTEXT_GET_PRIVATE (IBUS_INPUT_CONTEXT (context)); if (g_strcmp0 (signal_name, "Enabled") == 0) { priv->needs_surrounding_text = FALSE; g_signal_emit (context, context_signals[ENABLED], 0); return; } if (g_strcmp0 (signal_name, "Disabled") == 0) { priv->needs_surrounding_text = FALSE; g_signal_emit (context, context_signals[DISABLED], 0); return; } if (g_strcmp0 (signal_name, "RequireSurroundingText") == 0) { priv->needs_surrounding_text = TRUE; return; } G_DBUS_PROXY_CLASS (ibus_input_context_parent_class)->g_signal ( proxy, sender_name, signal_name, parameters); } IBusInputContext * ibus_input_context_new (const gchar *path, GDBusConnection *connection, GCancellable *cancellable, GError **error) { g_assert (path != NULL); g_assert (G_IS_DBUS_CONNECTION (connection)); const gchar *service_name = IBUS_SERVICE_IBUS; GInitable *initable; GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START; if (g_object_get_data (G_OBJECT (connection), "ibus-portal-connection")) service_name = IBUS_SERVICE_PORTAL; initable = g_initable_new (IBUS_TYPE_INPUT_CONTEXT, cancellable, error, "g-connection", connection, "g-name", service_name, "g-flags", flags, "g-interface-name", IBUS_INTERFACE_INPUT_CONTEXT, "g-object-path", path, "g-default-timeout", ibus_get_timeout (), NULL); if (initable != NULL) return IBUS_INPUT_CONTEXT (initable); return NULL; } void ibus_input_context_new_async (const gchar *path, GDBusConnection *connection, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_assert (path != NULL); g_assert (G_IS_DBUS_CONNECTION (connection)); g_assert (callback != NULL); const gchar *service_name = IBUS_SERVICE_IBUS; GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START; if (g_object_get_data (G_OBJECT (connection), "ibus-portal-connection")) service_name = IBUS_SERVICE_PORTAL; g_async_initable_new_async (IBUS_TYPE_INPUT_CONTEXT, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-connection", connection, "g-name", service_name, "g-flags", flags, "g-interface-name", IBUS_INTERFACE_INPUT_CONTEXT, "g-object-path", path, "g-default-timeout", ibus_get_timeout (), NULL); } IBusInputContext * ibus_input_context_new_async_finish (GAsyncResult *res, GError **error) { GObject *object = NULL; GObject *source_object = NULL; source_object = g_async_result_get_source_object (res); g_assert (source_object != NULL); object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error); g_object_unref (source_object); if (object != NULL) { return IBUS_INPUT_CONTEXT (object); } else { return NULL; } } IBusInputContext * ibus_input_context_get_input_context (const gchar *path, GDBusConnection *connection) { IBusInputContext *context = NULL; GError *error = NULL; context = ibus_input_context_new (path, connection, NULL, &error); if (context == NULL) { g_warning ("ibus_input_context_get_input_context: %s", error->message); g_error_free (error); return NULL; } /* Do not call "org.freedesktop.IBus.Service.Destroy" when the input * context object is disposed. */ IBUS_PROXY (context)->own = FALSE; return context; } void ibus_input_context_get_input_context_async (const gchar *path, GDBusConnection *connection, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { ibus_input_context_new_async (path, connection, cancellable, callback, user_data); } IBusInputContext * ibus_input_context_get_input_context_async_finish (GAsyncResult *res, GError **error) { IBusInputContext *context = NULL; context = ibus_input_context_new_async_finish (res, error); if (context == NULL) { return NULL; } /* Do not call "org.freedesktop.IBus.Service.Destroy" when the input * context object is disposed. */ IBUS_PROXY (context)->own = FALSE; return context; } void ibus_input_context_process_hand_writing_event (IBusInputContext *context, const gdouble *coordinates, guint coordinates_len) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); g_return_if_fail (coordinates != NULL); g_return_if_fail (coordinates_len >= 4); /* The array should contain at least one line. */ g_return_if_fail ((coordinates_len & 1) == 0); guint i; GVariantBuilder builder; g_variant_builder_init (&builder, G_VARIANT_TYPE ("ad")); for (i = 0; i < coordinates_len; i++) { g_variant_builder_add (&builder, "d", coordinates[i]); } g_dbus_proxy_call ((GDBusProxy *) context, "ProcessHandWritingEvent", /* method_name */ g_variant_new ("(ad)", &builder), /* parameters */ G_DBUS_CALL_FLAGS_NONE, /* flags */ -1, /* timeout */ NULL, /* cancellable */ NULL, /* callback */ NULL /* user_data */ ); } void ibus_input_context_cancel_hand_writing (IBusInputContext *context, guint n_strokes) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); g_dbus_proxy_call ((GDBusProxy *) context, "CancelHandWriting", /* method_name */ g_variant_new ("(u)", n_strokes), /* parameters */ G_DBUS_CALL_FLAGS_NONE, /* flags */ -1, /* timeout */ NULL, /* cancellable */ NULL, /* callback */ NULL /* user_data */ ); } void ibus_input_context_process_key_event_async (IBusInputContext *context, guint32 keyval, guint32 keycode, guint32 state, gint timeout_msec, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); g_dbus_proxy_call ((GDBusProxy *) context, "ProcessKeyEvent", /* method_name */ g_variant_new ("(uuu)", keyval, keycode, state), /* parameters */ G_DBUS_CALL_FLAGS_NONE, /* flags */ timeout_msec, /* timeout */ cancellable, /* cancellable */ callback, /* callback */ user_data /* user_data */ ); } gboolean ibus_input_context_process_key_event_async_finish (IBusInputContext *context, GAsyncResult *res, GError **error) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); g_assert (G_IS_ASYNC_RESULT (res)); g_assert (error == NULL || *error == NULL); gboolean processed = FALSE; GVariant *variant = g_dbus_proxy_call_finish ((GDBusProxy *) context, res, error); if (variant != NULL) { g_variant_get (variant, "(b)", &processed); g_variant_unref (variant); } return processed; } gboolean ibus_input_context_process_key_event (IBusInputContext *context, guint32 keyval, guint32 keycode, guint32 state) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); GVariant *result = g_dbus_proxy_call_sync ((GDBusProxy *) context, "ProcessKeyEvent", /* method_name */ g_variant_new ("(uuu)", keyval, keycode, state), /* parameters */ G_DBUS_CALL_FLAGS_NONE, /* flags */ -1, /* timeout */ NULL, /* cancellable */ NULL); if (result != NULL) { gboolean processed = FALSE; g_variant_get (result, "(b)", &processed); g_variant_unref (result); return processed; } return FALSE; } void ibus_input_context_set_cursor_location (IBusInputContext *context, gint32 x, gint32 y, gint32 w, gint32 h) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); g_dbus_proxy_call ((GDBusProxy *) context, "SetCursorLocation", /* method_name */ g_variant_new ("(iiii)", x, y, w, h),/* parameters */ G_DBUS_CALL_FLAGS_NONE, /* flags */ -1, /* timeout */ NULL, /* cancellable */ NULL, /* callback */ NULL /* user_data */ ); } void ibus_input_context_set_cursor_location_relative (IBusInputContext *context, gint32 x, gint32 y, gint32 w, gint32 h) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); g_dbus_proxy_call ((GDBusProxy *) context, "SetCursorLocationRelative", /* method_name */ g_variant_new ("(iiii)", x, y, w, h),/* parameters */ G_DBUS_CALL_FLAGS_NONE, /* flags */ -1, /* timeout */ NULL, /* cancellable */ NULL, /* callback */ NULL /* user_data */ ); } void ibus_input_context_set_capabilities (IBusInputContext *context, guint32 capabilites) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); g_dbus_proxy_call ((GDBusProxy *) context, "SetCapabilities", /* method_name */ g_variant_new ("(u)", capabilites), /* parameters */ G_DBUS_CALL_FLAGS_NONE, /* flags */ -1, /* timeout */ NULL, /* cancellable */ NULL, /* callback */ NULL /* user_data */ ); } void ibus_input_context_property_activate (IBusInputContext *context, const gchar *prop_name, guint32 state) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); g_dbus_proxy_call ((GDBusProxy *) context, "PropertyActivate", /* method_name */ g_variant_new ("(su)", prop_name, state), /* parameters */ G_DBUS_CALL_FLAGS_NONE, /* flags */ -1, /* timeout */ NULL, /* cancellable */ NULL, /* callback */ NULL /* user_data */ ); } void ibus_input_context_property_show (IBusInputContext *context, const gchar *prop_name) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); g_dbus_proxy_call ((GDBusProxy *) context, "PropertyShow", /* method_name */ g_variant_new ("(s)", prop_name), /* parameters */ G_DBUS_CALL_FLAGS_NONE, /* flags */ -1, /* timeout */ NULL, /* cancellable */ NULL, /* callback */ NULL /* user_data */ ); } void ibus_input_context_property_hide (IBusInputContext *context, const gchar *prop_name) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); g_dbus_proxy_call ((GDBusProxy *) context, "PropertyHide", /* method_name */ g_variant_new ("(s)", prop_name), /* parameters */ G_DBUS_CALL_FLAGS_NONE, /* flags */ -1, /* timeout */ NULL, /* cancellable */ NULL, /* callback */ NULL /* user_data */ ); } void ibus_input_context_set_surrounding_text (IBusInputContext *context, IBusText *text, guint32 cursor_pos, guint32 anchor_pos) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); g_assert (IBUS_IS_TEXT (text)); IBusInputContextPrivate *priv; priv = IBUS_INPUT_CONTEXT_GET_PRIVATE (context); if (cursor_pos != priv->surrounding_cursor_pos || anchor_pos != priv->selection_anchor_pos || priv->surrounding_text == NULL || g_strcmp0 (text->text, priv->surrounding_text->text) != 0) { if (priv->surrounding_text) g_object_unref (priv->surrounding_text); priv->surrounding_text = (IBusText *) g_object_ref_sink (text); priv->surrounding_cursor_pos = cursor_pos; priv->selection_anchor_pos = anchor_pos; if (priv->needs_surrounding_text) { GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)text); g_dbus_proxy_call ((GDBusProxy *) context, "SetSurroundingText", /* method_name */ g_variant_new ("(vuu)", variant, cursor_pos, anchor_pos), /* parameters */ G_DBUS_CALL_FLAGS_NONE, /* flags */ -1, /* timeout */ NULL, /* cancellable */ NULL, /* callback */ NULL /* user_data */ ); } } } gboolean ibus_input_context_needs_surrounding_text (IBusInputContext *context) { IBusInputContextPrivate *priv; priv = IBUS_INPUT_CONTEXT_GET_PRIVATE (IBUS_INPUT_CONTEXT (context)); return priv->needs_surrounding_text; } void ibus_input_context_set_content_type (IBusInputContext *context, guint purpose, guint hints) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); GVariant *cached_content_type = g_dbus_proxy_get_cached_property ((GDBusProxy *) context, "ContentType"); GVariant *content_type = g_variant_new ("(uu)", purpose, hints); g_variant_ref_sink (content_type); if (cached_content_type == NULL || !g_variant_equal (content_type, cached_content_type)) { g_dbus_proxy_call ((GDBusProxy *) context, "org.freedesktop.DBus.Properties.Set", g_variant_new ("(ssv)", IBUS_INTERFACE_INPUT_CONTEXT, "ContentType", content_type), G_DBUS_CALL_FLAGS_NONE, -1, NULL, /* cancellable */ NULL, /* callback */ NULL /* user_data */ ); } if (cached_content_type != NULL) g_variant_unref (cached_content_type); g_variant_unref (content_type); } void ibus_input_context_get_engine_async (IBusInputContext *context, gint timeout_msec, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); g_dbus_proxy_call ((GDBusProxy *) context, "GetEngine", /* method_name */ NULL, /* parameters */ G_DBUS_CALL_FLAGS_NONE, /* flags */ timeout_msec, cancellable, callback, user_data); } IBusEngineDesc * ibus_input_context_get_engine_async_finish (IBusInputContext *context, GAsyncResult *res, GError **error) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); g_assert (G_IS_ASYNC_RESULT (res)); g_assert (error == NULL || *error == NULL); GVariant *variant = g_dbus_proxy_call_finish ((GDBusProxy *) context, res, error); if (variant == NULL) { return NULL; } GVariant *engine_desc_variant = g_variant_get_child_value (variant, 0); IBusEngineDesc *desc = IBUS_ENGINE_DESC (ibus_serializable_deserialize (engine_desc_variant)); g_variant_unref (engine_desc_variant); g_variant_unref (variant); return desc; } IBusEngineDesc * ibus_input_context_get_engine (IBusInputContext *context) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); GVariant *result = NULL; GError *error = NULL; result = g_dbus_proxy_call_sync ((GDBusProxy *) context, "GetEngine", /* method_name */ NULL, /* parameters */ G_DBUS_CALL_FLAGS_NONE, /* flags */ -1, /* timeout */ NULL, /* cancellable */ &error /* error */ ); if (result == NULL) { if (g_error_matches (error, IBUS_ERROR, IBUS_ERROR_NO_ENGINE)) { g_debug ("%s.GetEngine: %s", IBUS_INTERFACE_INPUT_CONTEXT, error->message); } else { g_warning ("%s.GetEngine: %s", IBUS_INTERFACE_INPUT_CONTEXT, error->message); } g_error_free (error); return NULL; } GVariant *engine_desc_variant = g_variant_get_child_value (result, 0); IBusEngineDesc *desc = IBUS_ENGINE_DESC (ibus_serializable_deserialize (engine_desc_variant)); g_variant_unref (engine_desc_variant); g_variant_unref (result); return desc; } void ibus_input_context_set_engine (IBusInputContext *context, const gchar *name) { g_assert (IBUS_IS_INPUT_CONTEXT (context)); g_assert (name); g_dbus_proxy_call ((GDBusProxy *) context, "SetEngine", /* method_name */ g_variant_new ("(s)", name), /* parameters */ G_DBUS_CALL_FLAGS_NONE, /* flags */ -1, /* timeout */ NULL, /* cancellable */ NULL, /* callback */ NULL /* user_data */ ); } #define DEFINE_FUNC(name, Name) \ void \ ibus_input_context_##name (IBusInputContext *context) \ { \ g_assert (IBUS_IS_INPUT_CONTEXT (context)); \ g_dbus_proxy_call ((GDBusProxy *) context, \ #Name, /* method_name */ \ NULL, /* parameters */ \ G_DBUS_CALL_FLAGS_NONE, /* flags */ \ -1, /* timeout */ \ NULL, /* cancellable */ \ NULL, /* callback */ \ NULL /* user_data */ \ ); \ } DEFINE_FUNC(focus_in, FocusIn); DEFINE_FUNC(focus_out, FocusOut); DEFINE_FUNC(reset, Reset); DEFINE_FUNC(page_up, PageUp); DEFINE_FUNC(page_down, PageDown); DEFINE_FUNC(cursor_up, CursorUp); DEFINE_FUNC(cursor_down, CursorDown); #undef DEFINE_FUNC