diff options
author | Daiki Ueno <daiki.ueno@gmail.com> | 2011-04-05 10:11:49 -0400 |
---|---|---|
committer | Peng Huang <shawn.p.huang@gmail.com> | 2011-04-05 10:11:49 -0400 |
commit | 06e6abee9f221bdf7c277538ce136154465619d7 (patch) | |
tree | 2d91a9dd312428e2164d19cbbb3dcc8d3fb700bc /client | |
parent | 6a39a86f84fb59c06a246c1bb3f50abbf6c9f8d1 (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.c | 113 |
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 |