summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorDaiki Ueno <daiki.ueno@gmail.com>2011-04-05 10:11:49 -0400
committerPeng Huang <shawn.p.huang@gmail.com>2011-04-05 10:11:49 -0400
commit06e6abee9f221bdf7c277538ce136154465619d7 (patch)
tree2d91a9dd312428e2164d19cbbb3dcc8d3fb700bc /client
parent6a39a86f84fb59c06a246c1bb3f50abbf6c9f8d1 (diff)
Support surrounding-text retrieval.
Unlike the GtkIMContext API, IBus automatically retrieves surrounding-text when certain events occurred to the client ("before filter_keypress", for example). This makes the engine API simpler but causes periodical emission of D-Bus signals for updating surrounding-text information, which is unwanted for typical engines. For this reason, the surrounding-text support is currently disabled by default. To enable it, pass --enable-surrounding-text to configure. Also, even surrounding-text support is compiled in, IBus does not start polling until an engine requests surrounding-text using ibus_engine_get_surrounding_text(). To make the function work for the first time, clients should retrieve initial surrounding-text when the engine is enabled (see ibus_im_context_focus_in() and _ibus_context_enabled_cb() in client/gtk2/ibusimcontext.c). BUG=Issue#778 TEST=manual Review URL: http://codereview.appspot.com/4276082 Patch from Daiki Ueno <daiki.ueno@gmail.com>.
Diffstat (limited to 'client')
-rw-r--r--client/gtk2/ibusimcontext.c113
1 files changed, 101 insertions, 12 deletions
diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c
index 0cb9c313..dcd356f3 100644
--- a/client/gtk2/ibusimcontext.c
+++ b/client/gtk2/ibusimcontext.c
@@ -24,6 +24,7 @@
# include <config.h>
#endif
+#include <string.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <ibus.h>
@@ -114,6 +115,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);
@@ -132,14 +139,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
+ IBusIMContext *context);
+static gboolean _slave_delete_surrounding_cb
(GtkIMContext *slave,
- gint offset_from_cursor,
- guint nchars,
- IBusIMContext *context);
+ gint offset_from_cursor,
+ guint nchars,
+ IBusIMContext *context);
+static void _request_surrounding_text (IBusIMContext *context,
+ gboolean force);
static void _create_fake_input_context (void);
@@ -251,6 +260,28 @@ _process_key_event_done (GObject *object,
}
+/* emit "retrieve-surrounding" glib signal of GtkIMContext, if
+ * context->caps has IBUS_CAP_SURROUNDING_TEXT and the current IBus
+ * engine needs surrounding-text.
+ *
+ * if "force" is TRUE, emit the signal regardless of whether the
+ * engine needs surrounding-text.
+ */
+static void
+_request_surrounding_text (IBusIMContext *context, gboolean force)
+{
+ if (context->enable &&
+ (context->caps & IBUS_CAP_SURROUNDING_TEXT) != 0 &&
+ (force ||
+ ibus_input_context_needs_surrounding_text (context->ibuscontext))) {
+ gboolean return_value;
+ IDEBUG ("requesting surrounding text");
+ g_signal_emit (context, _signal_retrieve_surrounding_id, 0,
+ &return_value);
+ }
+}
+
+
static gint
_key_snooper_cb (GtkWidget *widget,
GdkEventKey *event,
@@ -337,6 +368,8 @@ _key_snooper_cb (GtkWidget *widget,
} while (0);
+ _request_surrounding_text (ibusimcontext, FALSE);
+
if (ibusimcontext != NULL) {
ibusimcontext->time = event->time;
}
@@ -414,6 +447,7 @@ ibus_im_context_class_init (IBusIMContextClass *class)
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 =
@@ -545,7 +579,11 @@ ibus_im_context_init (GObject *obj)
ibusimcontext->ibuscontext = NULL;
ibusimcontext->has_focus = FALSE;
ibusimcontext->time = GDK_CURRENT_TIME;
+#ifdef ENABLE_SURROUNDING
ibusimcontext->caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS | IBUS_CAP_SURROUNDING_TEXT;
+#else
+ ibusimcontext->caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS;
+#endif
// Create slave im context
@@ -642,6 +680,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, FALSE);
+
if (ibusimcontext != NULL) {
ibusimcontext->time = event->time;
}
@@ -721,6 +761,10 @@ ibus_im_context_focus_in (GtkIMContext *context)
g_object_ref (context),
(GDestroyNotify) g_object_unref);
+ /* retrieve the initial surrounding-text (regardless of whether
+ * the current IBus engine needs surrounding-text) */
+ _request_surrounding_text (ibusimcontext, TRUE);
+
g_object_add_weak_pointer ((GObject *) context,
(gpointer *) &_focus_im_context);
_focus_im_context = context;
@@ -899,12 +943,44 @@ ibus_im_context_set_use_preedit (GtkIMContext *context, gboolean use_preedit)
else {
ibusimcontext->caps &= ~IBUS_CAP_PREEDIT_TEXT;
}
- ibus_input_context_set_capabilities (ibusimcontext->ibuscontext, ibusimcontext->caps);
}
gtk_im_context_set_use_preedit (ibusimcontext->slave, 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)
{
@@ -923,6 +999,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, FALSE);
}
static gboolean
@@ -1217,6 +1295,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, FALSE);
}
static void
@@ -1240,6 +1320,10 @@ _ibus_context_enabled_cb (IBusInputContext *ibuscontext,
IDEBUG ("%s", __FUNCTION__);
ibusimcontext->enable = TRUE;
+
+ /* retrieve the initial surrounding-text (regardless of whether
+ * the current IBus engine needs surrounding-text) */
+ _request_surrounding_text (ibusimcontext, TRUE);
}
static void
@@ -1417,17 +1501,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,
@@ -1436,9 +1524,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