824 lines
29 KiB
Diff
824 lines
29 KiB
Diff
From d4b10b2e9aec0e1fb0674bab70c439ccc91ea07b Mon Sep 17 00:00:00 2001
|
|
From: Daiki Ueno <ueno@unixuser.org>
|
|
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,
|
|
" <arg name=\"desc\" direction=\"out\" type=\"v\"/>\n"
|
|
" </method>\n"
|
|
" <method name=\"Destroy\"/>\n"
|
|
+ " <method name=\"SetSurroundingText\">\n"
|
|
+ " <arg name=\"text\" direction=\"in\" type=\"v\"/>\n"
|
|
+ " <arg name=\"cursor_pos\" direction=\"in\" type=\"u\"/>\n"
|
|
+ " </method>\n"
|
|
|
|
/* signals */
|
|
" <signal name=\"CommitText\">\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.
|
|
+ *
|
|
+ * <note><para>Argument @user_data is ignored in this function.</para></note>
|
|
+ */
|
|
+ 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
|
|
|