Skip to content

Commit

Permalink
Detect mouse click to commit Hangul preedit
Browse files Browse the repository at this point in the history
If preedit text is not committed with the mouse click, preedit text
is moved to the new cursor position in Hangul typing.
Since set_cursor_location() is received before the reset() signal is
sent to ibus-daemon and commit_text() signal is received from
ibus-daemon, UpdatePreeditTextWithMode D-Bus method is newly added
and now ibus clients commit the preedit.

BUG=ibus#1980
  • Loading branch information
fujiwarat committed Nov 9, 2018
1 parent 3172c3b commit a40631e
Show file tree
Hide file tree
Showing 6 changed files with 338 additions and 44 deletions.
11 changes: 11 additions & 0 deletions bus/ibusimpl.c
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,17 @@ bus_ibus_impl_set_focused_context (BusIBusImpl *ibus,
engine = bus_input_context_get_engine (ibus->focused_context);
if (engine) {
g_object_ref (engine);
/* _ic_focus_in() can be called before _ic_focus_out() is
* called under the async processes of two ibus clients.
* E.g. gedit is a little slower v.s. a simple GtkTextView
* application is the fastest when you click a Hangul
* preedit text between the applications.
* preedit will be committed with focus-out in the ibus client
* likes ibus-im.so
* so do not commit preedit here in focus-in event.
*/
bus_input_context_clear_preedit_text (ibus->focused_context,
FALSE);
bus_input_context_set_engine (ibus->focused_context, NULL);
bus_input_context_set_emoji_extension (ibus->focused_context,
NULL);
Expand Down
108 changes: 85 additions & 23 deletions bus/inputcontext.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ struct _BusInputContext {
guint preedit_cursor_pos;
gboolean preedit_visible;
guint preedit_mode;
gboolean client_commit_preedit;

/* auxiliary text */
IBusText *auxiliary_text;
Expand Down Expand Up @@ -212,6 +213,9 @@ static IBusPropList *props_empty = NULL;
static const gchar introspection_xml[] =
"<node>"
" <interface name='org.freedesktop.IBus.InputContext'>"
/* properties */
" <property name='ContentType' type='(uu)' access='write' />"
" <property name='ClientCommitPreedit' type='(b)' access='write' />\n"
/* methods */
" <method name='ProcessKeyEvent'>"
" <arg direction='in' type='u' name='keyval' />"
Expand Down Expand Up @@ -273,6 +277,12 @@ static const gchar introspection_xml[] =
" <arg type='u' name='cursor_pos' />"
" <arg type='b' name='visible' />"
" </signal>"
" <signal name='UpdatePreeditTextWithMode'>"
" <arg type='v' name='text' />"
" <arg type='u' name='cursor_pos' />"
" <arg type='b' name='visible' />"
" <arg type='u' name='mode' />"
" </signal>"
" <signal name='ShowPreeditText'/>"
" <signal name='HidePreeditText'/>"
" <signal name='UpdateAuxiliaryText'>"
Expand All @@ -297,9 +307,6 @@ static const gchar introspection_xml[] =
" <signal name='UpdateProperty'>"
" <arg type='v' name='prop' />"
" </signal>"

/* properties */
" <property name='ContentType' type='(uu)' access='write' />"
" </interface>"
"</node>";

Expand Down Expand Up @@ -1069,6 +1076,12 @@ _ic_reset (BusInputContext *context,
GDBusMethodInvocation *invocation)
{
if (context->engine) {
if (context->preedit_mode == IBUS_ENGINE_PREEDIT_COMMIT) {
if (context->client_commit_preedit)
bus_input_context_clear_preedit_text (context, FALSE);
else
bus_input_context_clear_preedit_text (context, TRUE);
}
bus_engine_proxy_reset (context->engine);
}
g_dbus_method_invocation_return_value (invocation, NULL);
Expand Down Expand Up @@ -1354,6 +1367,13 @@ _ic_set_content_type (BusInputContext *context,
}
}

static void
_ic_set_client_commit_preedit (BusInputContext *context,
GVariant *value)
{
g_variant_get (value, "(b)", &context->client_commit_preedit);
}

static gboolean
bus_input_context_service_set_property (IBusService *service,
GDBusConnection *connection,
Expand All @@ -1379,9 +1399,14 @@ bus_input_context_service_set_property (IBusService *service,
if (!bus_input_context_service_authorized_method (service, connection))
return FALSE;

g_return_val_if_fail (BUS_IS_INPUT_CONTEXT (service), FALSE);

if (g_strcmp0 (property_name, "ContentType") == 0) {
BusInputContext *context = (BusInputContext *) service;
_ic_set_content_type (context, value);
_ic_set_content_type (BUS_INPUT_CONTEXT (service), value);
return TRUE;
}
if (g_strcmp0 (property_name, "ClientCommitPreedit") == 0) {
_ic_set_client_commit_preedit (BUS_INPUT_CONTEXT (service), value);
return TRUE;
}

Expand Down Expand Up @@ -1453,22 +1478,44 @@ bus_input_context_focus_in (BusInputContext *context)

/**
* bus_input_context_clear_preedit_text:
* @context: A #BusInputContext
* @with_signal: %FALSE if the preedit is already updated in ibus clients
* likes ibus-im.so. Otherwise %TRUE.
*
* Clear context->preedit_text. If the preedit mode is IBUS_ENGINE_PREEDIT_COMMIT, commit it before clearing.
* Clear context->preedit_text. If the preedit mode is
* IBUS_ENGINE_PREEDIT_COMMIT, commit it before clearing.
*/
static void
bus_input_context_clear_preedit_text (BusInputContext *context)
void
bus_input_context_clear_preedit_text (BusInputContext *context,
gboolean with_signal)
{
IBusText *preedit_text;
guint preedit_mode;
gboolean preedit_visible;

g_assert (BUS_IS_INPUT_CONTEXT (context));

if (context->preedit_visible &&
context->preedit_mode == IBUS_ENGINE_PREEDIT_COMMIT) {
bus_input_context_commit_text (context, context->preedit_text);
if (!with_signal) {
g_object_unref (context->preedit_text);
context->preedit_mode = IBUS_ENGINE_PREEDIT_CLEAR;
context->preedit_text = (IBusText *) g_object_ref_sink (text_empty);
context->preedit_cursor_pos = 0;
context->preedit_visible = FALSE;
return;
}

/* always clear preedit text */
/* always clear preedit text to reset the cursor position in the
* client application before commit the preeit text. */
preedit_text = g_object_ref (context->preedit_text);
preedit_mode = context->preedit_mode;
preedit_visible = context->preedit_visible;
bus_input_context_update_preedit_text (context,
text_empty, 0, FALSE, IBUS_ENGINE_PREEDIT_CLEAR, TRUE);

if (preedit_visible && preedit_mode == IBUS_ENGINE_PREEDIT_COMMIT) {
bus_input_context_commit_text (context, preedit_text);
}
g_object_unref (preedit_text);
}

void
Expand All @@ -1479,7 +1526,10 @@ bus_input_context_focus_out (BusInputContext *context)
if (!context->has_focus)
return;

bus_input_context_clear_preedit_text (context);
if (context->client_commit_preedit)
bus_input_context_clear_preedit_text (context, FALSE);
else
bus_input_context_clear_preedit_text (context, TRUE);
bus_input_context_update_auxiliary_text (context, text_empty, FALSE);
bus_input_context_update_lookup_table (context,
lookup_table_empty,
Expand Down Expand Up @@ -2338,7 +2388,7 @@ bus_input_context_disable (BusInputContext *context)
{
g_assert (BUS_IS_INPUT_CONTEXT (context));

bus_input_context_clear_preedit_text (context);
bus_input_context_clear_preedit_text (context, TRUE);
bus_input_context_update_auxiliary_text (context, text_empty, FALSE);
bus_input_context_update_lookup_table (context,
lookup_table_empty,
Expand Down Expand Up @@ -2385,7 +2435,7 @@ bus_input_context_unset_engine (BusInputContext *context)
{
g_assert (BUS_IS_INPUT_CONTEXT (context));

bus_input_context_clear_preedit_text (context);
bus_input_context_clear_preedit_text (context, TRUE);
bus_input_context_update_auxiliary_text (context, text_empty, FALSE);
bus_input_context_update_lookup_table (context,
lookup_table_empty,
Expand Down Expand Up @@ -2807,14 +2857,26 @@ bus_input_context_update_preedit_text (BusInputContext *context,
} else if (PREEDIT_CONDITION) {
GVariant *variant = ibus_serializable_serialize (
(IBusSerializable *)context->preedit_text);
bus_input_context_emit_signal (context,
"UpdatePreeditText",
g_variant_new (
"(vub)",
variant,
context->preedit_cursor_pos,
extension_visible),
NULL);
if (context->client_commit_preedit) {
bus_input_context_emit_signal (
context,
"UpdatePreeditTextWithMode",
g_variant_new ("(vubu)",
variant,
context->preedit_cursor_pos,
extension_visible,
context->preedit_mode),
NULL);
} else {
bus_input_context_emit_signal (
context,
"UpdatePreeditText",
g_variant_new ("(vub)",
variant,
context->preedit_cursor_pos,
extension_visible),
NULL);
}
} else {
g_signal_emit (context,
context_signals[UPDATE_PREEDIT_TEXT],
Expand Down
19 changes: 17 additions & 2 deletions bus/inputcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
/* vim:set et sts=4: */
/* ibus - The Input Bus
* Copyright (C) 2008-2014 Peng Huang <[email protected]>
* Copyright (C) 2017 Takao Fujiwara <[email protected]>
* Copyright (C) 2008-2014 Red Hat, Inc.
* Copyright (C) 2017-2018 Takao Fujiwara <[email protected]>
* Copyright (C) 2008-2018 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
Expand Down Expand Up @@ -377,5 +377,20 @@ void bus_input_context_update_lookup_table
void bus_input_context_panel_extension_received
(BusInputContext *context,
IBusExtensionEvent *event);

/**
* bus_input_context_clear_preedit_text:
*
* Clear context->preedit_text. If the preedit mode is
* IBUS_ENGINE_PREEDIT_COMMIT and with_signal is %TRUE, commit it before
* clearing.
* If with_signal is %FALSE, this just clears the preedit coditions
* and the actual preedit is handled in ibus clients.
*/
void bus_input_context_clear_preedit_text
(BusInputContext *context,
gboolean
with_signal);

G_END_DECLS
#endif
Loading

0 comments on commit a40631e

Please sign in to comment.