From d4b10b2e9aec0e1fb0674bab70c439ccc91ea07b Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 29 Sep 2010 13:40:58 +0900 Subject: [PATCH] Support surrounding-text retrieval. This change adds a new API function ibus_engine_get_surrounding_text(). In the implementation, engines do not proactively requests surrounding-text to target applications via the GTK+ client (IBusIMContext) every time the function is called. Instead, IBusIMContext retrieves surrounding-text when certain events occur in the input context (IBusInputContext) and maintains it within the input context. This logic is similar to Qt's QInputContext. The following events trigger surrounding-text retrieval: - focus_in - commit_text - show_preedit_text - (just before) process_key_event Also, - destroy resets the current surrounding-text. --- bus/engineproxy.c | 34 +++++++++++ bus/engineproxy.h | 7 ++ bus/inputcontext.c | 48 ++++++++++++++++ client/gtk2/ibusimcontext.c | 80 ++++++++++++++++++++++++-- ibus/engine.py | 6 ++ ibus/interface/iengine.py | 3 + ibus/interface/iinputcontext.py | 3 + src/ibusengine.c | 119 +++++++++++++++++++++++++++++++++++++++ src/ibusengine.h | 21 +++++++- src/ibusinputcontext.c | 43 ++++++++++++++ src/ibusinputcontext.h | 11 ++++ src/ibusmarshalers.list | 1 + 12 files changed, 368 insertions(+), 8 deletions(-) diff --git a/bus/engineproxy.c b/bus/engineproxy.c index 03592d7..915f999 100644 --- a/bus/engineproxy.c +++ b/bus/engineproxy.c @@ -52,6 +52,8 @@ enum { static guint engine_signals[LAST_SIGNAL] = { 0 }; // static guint engine_signals[LAST_SIGNAL] = { 0 }; +static IBusText *text_empty = NULL; + /* functions prototype */ static void bus_engine_proxy_real_destroy (BusEngineProxy *engine); @@ -302,6 +304,8 @@ bus_engine_proxy_class_init (BusEngineProxyClass *klass) 1, IBUS_TYPE_PROPERTY); + text_empty = ibus_text_new_from_static_string (""); + g_object_ref_sink (text_empty); } static void @@ -316,6 +320,8 @@ bus_engine_proxy_init (BusEngineProxy *engine) engine->enabled = FALSE; engine->desc = NULL; engine->keymap = NULL; + engine->surrounding_text = g_object_ref_sink (text_empty); + engine->surrounding_cursor_pos = 0; } static void @@ -337,6 +343,11 @@ bus_engine_proxy_real_destroy (BusEngineProxy *engine) engine->keymap = NULL; } + if (engine->surrounding_text) { + g_object_unref (engine->surrounding_text); + engine->surrounding_text = NULL; + } + IBUS_OBJECT_CLASS(bus_engine_proxy_parent_class)->destroy (IBUS_OBJECT (engine)); } @@ -733,6 +744,29 @@ void bus_engine_proxy_property_hide (BusEngineProxy *engine, G_TYPE_INVALID); } +void bus_engine_proxy_set_surrounding_text (BusEngineProxy *engine, + IBusText *text, + guint cursor_pos) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + g_assert (text != NULL); + + if (!engine->surrounding_text || + g_strcmp0 (text->text, engine->surrounding_text->text) != 0 || + cursor_pos != engine->surrounding_cursor_pos) { + if (engine->surrounding_text) + g_object_unref (engine->surrounding_text); + engine->surrounding_text = (IBusText *) g_object_ref_sink (text); + engine->surrounding_cursor_pos = cursor_pos; + + ibus_proxy_call ((IBusProxy *) engine, + "SetSurroundingText", + IBUS_TYPE_TEXT, &text, + G_TYPE_UINT, &cursor_pos, + G_TYPE_INVALID); + } +} + #define DEFINE_FUNCTION(Name, name) \ void \ bus_engine_proxy_##name (BusEngineProxy *engine) \ diff --git a/bus/engineproxy.h b/bus/engineproxy.h index 254b00c..b0e211d 100644 --- a/bus/engineproxy.h +++ b/bus/engineproxy.h @@ -59,6 +59,9 @@ struct _BusEngineProxy { gint y; gint w; gint h; + /* surrounding text */ + IBusText *surrounding_text; + guint surrounding_cursor_pos; IBusEngineDesc *desc; IBusKeymap *keymap; @@ -112,5 +115,9 @@ void bus_engine_proxy_property_show (BusEngineProxy *engine, void bus_engine_proxy_property_hide (BusEngineProxy *engine, const gchar *prop_name); gboolean bus_engine_proxy_is_enabled (BusEngineProxy *engine); +void bus_engine_proxy_set_surrounding_text + (BusEngineProxy *engine, + IBusText *text, + guint cursor_pos); G_END_DECLS #endif diff --git a/bus/inputcontext.c b/bus/inputcontext.c index b5ab201..1aa9f21 100644 --- a/bus/inputcontext.c +++ b/bus/inputcontext.c @@ -569,6 +569,10 @@ _ibus_introspect (BusInputContext *context, " \n" " \n" " \n" + " \n" + " \n" + " \n" + " \n" /* signals */ " \n" @@ -1098,6 +1102,49 @@ _ic_destroy (BusInputContext *context, return NULL; } +static IBusMessage * +_ic_set_surrounding_text (BusInputContext *context, + IBusMessage *message, + BusConnection *connection) +{ + g_assert (BUS_IS_INPUT_CONTEXT (context)); + g_assert (message != NULL); + g_assert (BUS_IS_CONNECTION (connection)); + + IBusMessage *reply; + IBusText *text; + guint cursor_pos = 0; + gboolean retval; + IBusError *error; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_TEXT, &text, + G_TYPE_UINT, &cursor_pos, + G_TYPE_INVALID); + + if (!retval) { + reply = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + return reply; + } + + if ((context->capabilities & IBUS_CAP_SURROUNDING_TEXT) && + context->has_focus && context->enabled && context->engine) { + bus_engine_proxy_set_surrounding_text (context->engine, + text, + cursor_pos); + } + + if (g_object_is_floating (text)) + g_object_unref (text); + + reply = ibus_message_new_method_return (message); + return reply; +} + static gboolean bus_input_context_ibus_message (BusInputContext *context, BusConnection *connection, @@ -1132,6 +1179,7 @@ bus_input_context_ibus_message (BusInputContext *context, { IBUS_INTERFACE_INPUT_CONTEXT, "SetEngine", _ic_set_engine }, { IBUS_INTERFACE_INPUT_CONTEXT, "GetEngine", _ic_get_engine }, { IBUS_INTERFACE_INPUT_CONTEXT, "Destroy", _ic_destroy }, + { IBUS_INTERFACE_INPUT_CONTEXT, "SetSurroundingText",_ic_set_surrounding_text }, }; ibus_message_set_sender (message, bus_connection_get_unique_name (connection)); diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c index c104f38..86350f5 100644 --- a/client/gtk2/ibusimcontext.c +++ b/client/gtk2/ibusimcontext.c @@ -107,6 +107,12 @@ static void ibus_im_context_set_cursor_location static void ibus_im_context_set_use_preedit (GtkIMContext *context, gboolean use_preedit); +static void ibus_im_context_set_surrounding + (GtkIMContext *slave, + const gchar *text, + gint len, + gint cursor_index); + /* static methods*/ static void _create_input_context (IBusIMContext *context); @@ -125,15 +131,16 @@ static void _slave_preedit_start_cb (GtkIMContext *slave, IBusIMContext *context); static void _slave_preedit_end_cb (GtkIMContext *slave, IBusIMContext *context); -static void _slave_retrieve_surrounding_cb +static gboolean _slave_retrieve_surrounding_cb (GtkIMContext *slave, IBusIMContext *context); -static void _slave_delete_surrounding_cb +static gboolean _slave_delete_surrounding_cb (GtkIMContext *slave, gint offset_from_cursor, guint nchars, IBusIMContext *context); static void _create_fake_input_context (void); +static void _request_surrounding_text (IBusIMContext *context); @@ -200,6 +207,16 @@ ibus_im_context_new (void) return IBUS_IM_CONTEXT (obj); } +static void +_request_surrounding_text (IBusIMContext *context) +{ + if (context->enable) { + gboolean return_value; + g_signal_emit (context, _signal_retrieve_surrounding_id, 0, + &return_value); + } +} + static gint _key_snooper_cb (GtkWidget *widget, GdkEventKey *event, @@ -239,6 +256,8 @@ _key_snooper_cb (GtkWidget *widget, _input_window = event->window; } + _request_surrounding_text (ibusimcontext); + switch (event->type) { case GDK_KEY_RELEASE: retval = ibus_input_context_process_key_event (ibuscontext, @@ -285,6 +304,7 @@ ibus_im_context_class_init (IBusIMContextClass *klass) im_context_class->set_client_window = ibus_im_context_set_client_window; im_context_class->set_cursor_location = ibus_im_context_set_cursor_location; im_context_class->set_use_preedit = ibus_im_context_set_use_preedit; + im_context_class->set_surrounding = ibus_im_context_set_surrounding; gobject_class->finalize = ibus_im_context_finalize; _signal_commit_id = @@ -477,6 +497,8 @@ ibus_im_context_filter_keypress (GtkIMContext *context, if (ibusimcontext->client_window == NULL && event->window != NULL) gtk_im_context_set_client_window ((GtkIMContext *)ibusimcontext, event->window); + _request_surrounding_text (ibusimcontext); + switch (event->type) { case GDK_KEY_RELEASE: retval = ibus_input_context_process_key_event (ibusimcontext->ibuscontext, @@ -541,6 +563,8 @@ ibus_im_context_focus_in (GtkIMContext *context) g_object_weak_ref ((GObject *) context, _weak_notify_cb, NULL); _focus_im_context = context; } + + _request_surrounding_text (ibusimcontext); } static void @@ -706,6 +730,39 @@ ibus_im_context_set_use_preedit (GtkIMContext *context, gboolean use_preedit) } static void +ibus_im_context_set_surrounding (GtkIMContext *context, + const gchar *text, + gint len, + gint cursor_index) +{ + g_return_if_fail (context != NULL); + g_return_if_fail (IBUS_IS_IM_CONTEXT (context)); + g_return_if_fail (text != NULL); + g_return_if_fail (strlen (text) >= len); + g_return_if_fail (0 <= cursor_index && cursor_index <= len); + + IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (context); + + if (ibusimcontext->enable && ibusimcontext->ibuscontext) { + IBusText *ibustext; + guint cursor_pos; + gchar *p; + + p = g_strndup (text, len); + cursor_pos = g_utf8_strlen (p, cursor_index); + ibustext = ibus_text_new_from_string (p); + g_free (p); + ibus_input_context_set_surrounding_text (ibusimcontext->ibuscontext, + ibustext, + cursor_pos); + } + gtk_im_context_set_surrounding (ibusimcontext->slave, + text, + len, + cursor_index); +} + +static void _bus_connected_cb (IBusBus *bus, IBusIMContext *ibusimcontext) { @@ -724,6 +781,8 @@ _ibus_context_commit_text_cb (IBusInputContext *ibuscontext, IDEBUG ("%s", __FUNCTION__); g_signal_emit (ibusimcontext, _signal_commit_id, 0, text->text); + + _request_surrounding_text (ibusimcontext); } static gboolean @@ -954,6 +1013,8 @@ _ibus_context_show_preedit_text_cb (IBusInputContext *ibuscontext, ibusimcontext->preedit_visible = TRUE; g_signal_emit (ibusimcontext, _signal_preedit_start_id, 0); g_signal_emit (ibusimcontext, _signal_preedit_changed_id, 0); + + _request_surrounding_text (ibusimcontext); } static void @@ -1118,17 +1179,21 @@ _slave_preedit_end_cb (GtkIMContext *slave, g_signal_emit (ibusimcontext, _signal_preedit_end_id, 0); } -static void +static gboolean _slave_retrieve_surrounding_cb (GtkIMContext *slave, IBusIMContext *ibusimcontext) { + gboolean return_value; + if (ibusimcontext->enable && ibusimcontext->ibuscontext) { - return; + return FALSE; } - g_signal_emit (ibusimcontext, _signal_retrieve_surrounding_id, 0); + g_signal_emit (ibusimcontext, _signal_retrieve_surrounding_id, 0, + &return_value); + return return_value; } -static void +static gboolean _slave_delete_surrounding_cb (GtkIMContext *slave, gint offset_from_cursor, guint nchars, @@ -1137,9 +1202,10 @@ _slave_delete_surrounding_cb (GtkIMContext *slave, gboolean return_value; if (ibusimcontext->enable && ibusimcontext->ibuscontext) { - return; + return FALSE; } g_signal_emit (ibusimcontext, _signal_delete_surrounding_id, 0, offset_from_cursor, nchars, &return_value); + return return_value; } #ifdef OS_CHROMEOS diff --git a/ibus/engine.py b/ibus/engine.py index b1df2fe..ec42fa4 100644 --- a/ibus/engine.py +++ b/ibus/engine.py @@ -46,6 +46,9 @@ class EngineBase(object.Object): def set_cursor_location(self, x, y, w, h): pass + def set_surrounding_text(self, text, cursor_index): + pass + def set_capabilities(self, cap): pass @@ -163,6 +166,9 @@ class EngineProxy(interface.IEngine): def SetCursorLocation(self, x, y, w, h): return self.__engine.set_cursor_location(x, y, w, h) + def SetSurroundingText(self, text, cursor_index): + return self.__engine.set_surrounding_text(text, cursor_index) + def SetCapabilities(self, caps): return self.__engine.set_capabilities(caps) diff --git a/ibus/interface/iengine.py b/ibus/interface/iengine.py index 4d42c2d..ee23efe 100644 --- a/ibus/interface/iengine.py +++ b/ibus/interface/iengine.py @@ -50,6 +50,9 @@ class IEngine(dbus.service.Object): @method(in_signature="iiii") def SetCursorLocation(self, x, y, w, h): pass + @method(in_signature="vu") + def SetSurroundingText(self, text, cursor_index): pass + @method(in_signature="u") def SetCapabilities(self, cap): pass diff --git a/ibus/interface/iinputcontext.py b/ibus/interface/iinputcontext.py index 89f6dbd..2db1c9b 100644 --- a/ibus/interface/iinputcontext.py +++ b/ibus/interface/iinputcontext.py @@ -49,6 +49,9 @@ class IInputContext(dbus.service.Object): @method(in_signature="iiii") def SetCursorLocation(self, x, y, w, h): pass + @method(in_signature="vu") + def SetSurroundingText(self, text, cursor_index): pass + @method() def FocusIn(self): pass diff --git a/src/ibusengine.c b/src/ibusengine.c index b5f53d4..da1e643 100644 --- a/src/ibusengine.c +++ b/src/ibusengine.c @@ -45,6 +45,7 @@ enum { PROPERTY_SHOW, PROPERTY_HIDE, CANDIDATE_CLICKED, + SET_SURROUNDING_TEXT, LAST_SIGNAL, }; @@ -59,11 +60,16 @@ enum { struct _IBusEnginePrivate { gchar *name; IBusConnection *connection; + + IBusText *surrounding_text; + guint surrounding_cursor_pos; }; typedef struct _IBusEnginePrivate IBusEnginePrivate; static guint engine_signals[LAST_SIGNAL] = { 0 }; +static IBusText *text_empty = NULL; + /* functions prototype */ static void ibus_engine_destroy (IBusEngine *engine); static void ibus_engine_set_property (IBusEngine *engine, @@ -113,6 +119,10 @@ static void ibus_engine_property_show (IBusEngine *engine, const gchar *prop_name); static void ibus_engine_property_hide (IBusEngine *engine, const gchar *prop_name); +static void ibus_engine_set_surrounding_text + (IBusEngine *engine, + IBusText *text, + guint cursor_pos); G_DEFINE_TYPE (IBusEngine, ibus_engine, IBUS_TYPE_SERVICE) @@ -167,6 +177,7 @@ ibus_engine_class_init (IBusEngineClass *klass) klass->property_hide = ibus_engine_property_hide; klass->set_cursor_location = ibus_engine_set_cursor_location; klass->set_capabilities = ibus_engine_set_capabilities; + klass->set_surrounding_text = ibus_engine_set_surrounding_text; /* install properties */ @@ -544,6 +555,29 @@ ibus_engine_class_init (IBusEngineClass *klass) 1, G_TYPE_STRING); + /** + * IBusEngine::set-surrounding-text: + * @engine: An IBusEngine. + * + * Emitted when a surrounding text is set. + * Implement the member function set_surrounding_text() in extended class to receive this signal. + * + * Argument @user_data is ignored in this function. + */ + engine_signals[SET_SURROUNDING_TEXT] = + g_signal_new (I_("set-surrounding-text"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, set_surrounding_text), + NULL, NULL, + ibus_marshal_VOID__OBJECT_UINT, + G_TYPE_NONE, + 2, + G_TYPE_OBJECT, + G_TYPE_UINT); + + text_empty = ibus_text_new_from_static_string (""); + g_object_ref_sink (text_empty); } static void @@ -554,6 +588,9 @@ ibus_engine_init (IBusEngine *engine) priv->name = NULL; priv->connection = NULL; + + priv->surrounding_text = g_object_ref_sink (text_empty); + priv->surrounding_cursor_pos = 0; } static void @@ -569,6 +606,11 @@ ibus_engine_destroy (IBusEngine *engine) priv->connection = NULL; } + if (priv->surrounding_text) { + g_object_unref (priv->surrounding_text); + priv->surrounding_text = NULL; + } + IBUS_OBJECT_CLASS(ibus_engine_parent_class)->destroy (IBUS_OBJECT (engine)); } @@ -879,6 +921,33 @@ ibus_engine_ibus_message (IBusEngine *engine, ibus_object_destroy ((IBusObject *) engine); return TRUE; } + else if (g_strcmp0 (name, "SetSurroundingText") == 0) { + IBusText *text; + guint cursor_pos; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_TEXT, &text, + G_TYPE_UINT, &cursor_pos, + G_TYPE_INVALID); + + if (!retval) { + reply = ibus_message_new_error_printf (message, + DBUS_ERROR_INVALID_ARGS, + "%s.%s: Can not match signature (u) of method", + IBUS_INTERFACE_ENGINE, "SetSurroundingText"); + ibus_error_free (error); + } + else { + g_signal_emit (engine, engine_signals[SET_SURROUNDING_TEXT], 0, + text, + cursor_pos); + if (g_object_is_floating (text)) { + g_object_unref (text); + } + reply = ibus_message_new_method_return (message); + } + } else { reply = ibus_message_new_error_printf (message, DBUS_ERROR_UNKNOWN_METHOD, @@ -1003,6 +1072,26 @@ ibus_engine_property_hide (IBusEngine *engine, const gchar *prop_name) } static void +ibus_engine_set_surrounding_text (IBusEngine *engine, + IBusText *text, + guint cursor_pos) +{ + g_assert (IBUS_IS_ENGINE (engine)); + + IBusEnginePrivate *priv; + + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + if (priv->surrounding_text) { + g_object_unref (priv->surrounding_text); + } + + priv->surrounding_text = (IBusText *) g_object_ref_sink (text ? text : text_empty); + priv->surrounding_cursor_pos = cursor_pos; + // g_debug ("set-surrounding-text ('%s', %d)", text->text, cursor_pos); +} + +static void _send_signal (IBusEngine *engine, const gchar *name, GType first_arg_type, @@ -1203,6 +1292,19 @@ void ibus_engine_delete_surrounding_text (IBusEngine *engine, gint offset_from_cursor, guint nchars) { + g_assert (IBUS_IS_ENGINE (engine)); + + IBusEnginePrivate *priv; + + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + /* Clear the current surrounding-text buffer. */ + if (priv->surrounding_text) { + g_object_unref (priv->surrounding_text); + priv->surrounding_text = g_object_ref_sink (text_empty); + priv->surrounding_cursor_pos = 0; + } + _send_signal (engine, "DeleteSurroundingText", G_TYPE_INT, &offset_from_cursor, @@ -1211,6 +1313,23 @@ void ibus_engine_delete_surrounding_text (IBusEngine *engine, } void +ibus_engine_get_surrounding_text (IBusEngine *engine, + IBusText **text, + guint *cursor_pos) +{ + IBusEnginePrivate *priv; + + g_return_if_fail (IBUS_IS_ENGINE (engine)); + g_return_if_fail (text != NULL); + g_return_if_fail (cursor_pos != NULL); + + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + *text = g_object_ref (priv->surrounding_text); + *cursor_pos = priv->surrounding_cursor_pos; +} + +void ibus_engine_register_properties (IBusEngine *engine, IBusPropList *prop_list) { diff --git a/src/ibusengine.h b/src/ibusengine.h index 95be408..2c6e1d3 100644 --- a/src/ibusengine.h +++ b/src/ibusengine.h @@ -124,10 +124,14 @@ struct _IBusEngineClass { guint index, guint button, guint state); + void (* set_surrounding_text) + (IBusEngine *engine, + IBusText *text, + guint cursor_index); /*< private >*/ /* padding */ - gpointer pdummy[8]; + gpointer pdummy[7]; }; GType ibus_engine_get_type (void); @@ -367,6 +371,21 @@ void ibus_engine_delete_surrounding_text(IBusEngine *engine, guint nchars); /** + * ibus_engine_get_surrounding_text: + * @engine: An IBusEngine. + * @text: Location to store surrounding text. + * @cursor_pos: Cursor position in characters in @text. + * + * Get surrounding text. + * + * @see_also #IBusEngine::set-surrounding-text + */ +void ibus_engine_get_surrounding_text(IBusEngine *engine, + IBusText **text, + guint *cursor_pos); + + +/** * ibus_engine_get_name: * @engine: An IBusEngine. * @returns: Name of IBusEngine. diff --git a/src/ibusinputcontext.c b/src/ibusinputcontext.c index b00ad3b..158979e 100644 --- a/src/ibusinputcontext.c +++ b/src/ibusinputcontext.c @@ -58,12 +58,18 @@ enum { /* BusInputContextPriv */ struct _IBusInputContextPrivate { gboolean own; + + /* surrounding text */ + IBusText *surrounding_text; + guint surrounding_cursor_pos; }; typedef struct _IBusInputContextPrivate IBusInputContextPrivate; static guint context_signals[LAST_SIGNAL] = { 0 }; // static guint context_signals[LAST_SIGNAL] = { 0 }; +static IBusText *text_empty = NULL; + /* functions prototype */ static void ibus_input_context_real_destroy (IBusInputContext *context); static gboolean ibus_input_context_ibus_signal (IBusProxy *proxy, @@ -474,6 +480,9 @@ ibus_input_context_class_init (IBusInputContextClass *klass) G_TYPE_NONE, 1, IBUS_TYPE_PROPERTY); + + text_empty = ibus_text_new_from_static_string (""); + g_object_ref_sink (text_empty); } static void @@ -482,6 +491,8 @@ ibus_input_context_init (IBusInputContext *context) IBusInputContextPrivate *priv; priv = IBUS_INPUT_CONTEXT_GET_PRIVATE (context); priv->own = TRUE; + priv->surrounding_text = g_object_ref_sink (text_empty); + priv->surrounding_cursor_pos = 0; } static void @@ -496,6 +507,11 @@ ibus_input_context_real_destroy (IBusInputContext *context) G_TYPE_INVALID); } + if (priv->surrounding_text) { + g_object_unref (priv->surrounding_text); + priv->surrounding_text = NULL; + } + IBUS_OBJECT_CLASS(ibus_input_context_parent_class)->destroy (IBUS_OBJECT (context)); } @@ -914,6 +930,33 @@ ibus_input_context_property_hide (IBusInputContext *context, G_TYPE_INVALID); } +void +ibus_input_context_set_surrounding_text (IBusInputContext *context, + IBusText *text, + guint32 cursor_pos) +{ + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + g_assert (IBUS_IS_TEXT (text)); + + IBusInputContextPrivate *priv; + priv = IBUS_INPUT_CONTEXT_GET_PRIVATE (context); + + if (priv->surrounding_text == NULL || + g_strcmp0 (text->text, priv->surrounding_text->text) != 0 || + cursor_pos != priv->surrounding_cursor_pos) { + 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; + + ibus_proxy_call ((IBusProxy *) context, + "SetSurroundingText", + IBUS_TYPE_TEXT, &text, + G_TYPE_UINT, &cursor_pos, + G_TYPE_INVALID); + } +} + gboolean ibus_input_context_is_enabled (IBusInputContext *context) { diff --git a/src/ibusinputcontext.h b/src/ibusinputcontext.h index 0d508a1..7f3d3f6 100644 --- a/src/ibusinputcontext.h +++ b/src/ibusinputcontext.h @@ -36,6 +36,7 @@ #include "ibusproxy.h" #include "ibusenginedesc.h" +#include "ibustext.h" /* * Type macros. @@ -267,6 +268,16 @@ IBusEngineDesc void ibus_input_context_set_engine (IBusInputContext *context, const gchar *name); +/** + * ibus_input_context_set_surrounding_text: + * @context: An IBusInputContext. + * @text: An IBusText surrounding the current cursor on the application. + * @cursor_po: Current cursor position in characters in @text. +*/ +void ibus_input_context_set_surrounding_text + (IBusInputContext *context, + IBusText *text, + guint32 cursor_pos); G_END_DECLS #endif diff --git a/src/ibusmarshalers.list b/src/ibusmarshalers.list index 4473dab..6f80970 100644 --- a/src/ibusmarshalers.list +++ b/src/ibusmarshalers.list @@ -13,6 +13,7 @@ VOID:INT,INT,INT,INT VOID:UINT,UINT VOID:INT,UINT VOID:UINT,UINT,UINT +VOID:OBJECT,UINT VOID:OBJECT,UINT,BOOL VOID:OBJECT,UINT,BOOL,UINT VOID:OBJECT,BOOL -- 1.7.2.1