Add preedit D-Bus signals to PostProcessKeyEvent

This commit is contained in:
Takao Fujiwara 2023-10-25 17:55:00 +09:00
parent 900c828556
commit 1c5ffb1a7e
2 changed files with 518 additions and 1 deletions

View File

@ -1412,3 +1412,516 @@ index def23b25..c6a030fe 100644
--
2.41.0
From ef0d29d8bf4e533c428b2cd9d3ee9fa42e9e20e7 Mon Sep 17 00:00:00 2001
From: fujiwarat <takao.fujiwara1@gmail.com>
Date: Wed, 25 Oct 2023 16:46:07 +0900
Subject: [PATCH] src: Add preedit D-Bus signals to PostProcessKeyEvent
ibus-hangul calls UpdatePreeditText signal during pressing Enter key
to hide the current preedit text and this also causes the reorder issue
in sync process-key-event and need to move the preedit signals
to PostProcessKeyEvent.
Also refactor PostProcessKeyEvent codes.
Fixes: https://github.com/ibus/ibus/commit/38f09c6
BUG=https://github.com/ibus/ibus/pull/2575
---
bus/inputcontext.c | 176 +++++++++++++++++++++++++++--------------
src/ibusinputcontext.c | 162 +++++++++++++++++++++++++++++--------
2 files changed, 248 insertions(+), 90 deletions(-)
diff --git a/bus/inputcontext.c b/bus/inputcontext.c
index 64430fe4..c914fbd2 100644
--- a/bus/inputcontext.c
+++ b/bus/inputcontext.c
@@ -48,11 +48,25 @@ struct _SetEngineByDescData {
};
typedef struct _SetEngineByDescData SetEngineByDescData;
+typedef struct _DeleteSurroundingData {
+ gint offset;
+ guint nchars;
+} DeleteSurroundingData;
+
typedef struct _SyncForwardingData {
- gchar key;
- IBusText *text;
+ char key;
+ IBusText *text;
} SyncForwardingData;
+typedef struct _SyncForwardingPreData {
+ char key;
+ IBusText *text;
+ union {
+ guint uints[3];
+ DeleteSurroundingData deleting;
+ } u;
+} SyncForwardingPreData;
+
struct _BusInputContext {
IBusService parent;
@@ -943,6 +957,7 @@ _ic_process_key_event (BusInputContext *context,
*/
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(b)", TRUE));
+ context->processing_key_event = FALSE;
return;
}
if (G_UNLIKELY (!context->has_focus)) {
@@ -1005,6 +1020,7 @@ _ic_process_key_event (BusInputContext *context,
else {
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(b)", FALSE));
+ context->processing_key_event = FALSE;
}
}
@@ -1654,6 +1670,71 @@ bus_input_context_service_set_property (IBusService *service,
}
+static gboolean
+bus_input_context_make_post_process_key_event (BusInputContext *context,
+ SyncForwardingPreData *pre_data)
+{
+ SyncForwardingData *data;
+ if (context->processing_key_event && g_queue_get_length (
+ context->queue_during_process_key_event) <= MAX_SYNC_DATA) {
+ if (g_queue_get_length (context->queue_during_process_key_event)
+ == MAX_SYNC_DATA) {
+ g_warning ("Exceed max number of post process_key_event data");
+ }
+ data = g_slice_new (SyncForwardingData);
+ data->key = pre_data->key;
+ switch (pre_data->key) {
+ case 'c':
+ data->text = g_object_ref (pre_data->text);
+ break;
+ case 'd':
+ data->text = ibus_text_new_from_printf (
+ "%d,%u",
+ pre_data->u.deleting.offset,
+ pre_data->u.deleting.nchars);
+ break;
+ case 'f':
+ data->text = ibus_text_new_from_printf ("%u,%u,%u",
+ pre_data->u.uints[0],
+ pre_data->u.uints[1],
+ pre_data->u.uints[2]);
+ break;
+ case 'h':
+ case 'r':
+ case 's':
+ data->text = ibus_text_new_from_static_string ("");
+ break;
+ case 'u':
+ case 'm':
+ data->text = g_object_ref (pre_data->text);
+ g_queue_push_tail (context->queue_during_process_key_event, data);
+ data = g_slice_new (SyncForwardingData);
+ data->key = pre_data->key;
+ if (pre_data->key == 'u') {
+ data->text = ibus_text_new_from_printf (
+ "%u,%u",
+ pre_data->u.uints[0],
+ pre_data->u.uints[1]);
+ } else {
+ data->text = ibus_text_new_from_printf (
+ "%u,%u,%u",
+ pre_data->u.uints[0],
+ pre_data->u.uints[1],
+ pre_data->u.uints[2]);
+ }
+ break;
+ default:
+ g_warning ("Type %c of SyncForwardingData is not supported",
+ pre_data->key);
+ g_slice_free (SyncForwardingData, data);
+ return FALSE;
+ }
+ g_queue_push_tail (context->queue_during_process_key_event, data);
+ return TRUE;
+ }
+ return FALSE;
+}
+
gboolean
bus_input_context_has_focus (BusInputContext *context)
{
@@ -1893,6 +1974,9 @@ bus_input_context_show_preedit_text (BusInputContext *context,
}
if (PREEDIT_CONDITION) {
+ SyncForwardingPreData pre_data = { 's', };
+ if (bus_input_context_make_post_process_key_event (context, &pre_data))
+ return;
bus_input_context_emit_signal (context,
"ShowPreeditText",
NULL,
@@ -1933,6 +2017,9 @@ bus_input_context_hide_preedit_text (BusInputContext *context,
}
if (PREEDIT_CONDITION) {
+ SyncForwardingPreData pre_data = { 'h', };
+ if (bus_input_context_make_post_process_key_event (context, &pre_data))
+ return;
bus_input_context_emit_signal (context,
"HidePreeditText",
NULL,
@@ -2375,27 +2462,18 @@ _engine_forward_key_event_cb (BusEngineProxy *engine,
guint state,
BusInputContext *context)
{
+ SyncForwardingPreData pre_data = { 'f', };
+
g_assert (BUS_IS_ENGINE_PROXY (engine));
g_assert (BUS_IS_INPUT_CONTEXT (context));
-
g_assert (context->engine == engine);
g_assert (context->queue_during_process_key_event);
- if (context->processing_key_event && g_queue_get_length (
- context->queue_during_process_key_event) <= MAX_SYNC_DATA) {
- SyncForwardingData *data;
- IBusText *text = ibus_text_new_from_printf ("%u,%u,%u",
- keyval, keycode, state);
- if (g_queue_get_length (context->queue_during_process_key_event)
- == MAX_SYNC_DATA) {
- g_warning ("Exceed max number of post process_key_event data");
- }
- data = g_slice_new (SyncForwardingData);
- data->key = 'f';
- data->text = text;
- g_queue_push_tail (context->queue_during_process_key_event, data);
+ pre_data.u.uints[0] = keyval;
+ pre_data.u.uints[1] = keycode;
+ pre_data.u.uints[2] = state;
+ if (bus_input_context_make_post_process_key_event (context, &pre_data))
return;
- }
bus_input_context_emit_signal (context,
"ForwardKeyEvent",
g_variant_new ("(uuu)",
@@ -2415,26 +2493,16 @@ _engine_delete_surrounding_text_cb (BusEngineProxy *engine,
guint nchars,
BusInputContext *context)
{
+ SyncForwardingPreData pre_data = { 'd', };
+
g_assert (BUS_IS_ENGINE_PROXY (engine));
g_assert (BUS_IS_INPUT_CONTEXT (context));
-
g_assert (context->engine == engine);
- if (context->processing_key_event && g_queue_get_length (
- context->queue_during_process_key_event) <= MAX_SYNC_DATA) {
- SyncForwardingData *data;
- IBusText *text = ibus_text_new_from_printf ("%d,%u",
- offset_from_cursor, nchars);
- if (g_queue_get_length (context->queue_during_process_key_event)
- == MAX_SYNC_DATA) {
- g_warning ("Exceed max number of sync process_key_event data");
- }
- data = g_slice_new (SyncForwardingData);
- data->key = 'd';
- data->text = g_object_ref (text);
- g_queue_push_tail (context->queue_during_process_key_event, data);
+ pre_data.u.deleting.offset = offset_from_cursor;
+ pre_data.u.deleting.nchars = nchars;
+ if (bus_input_context_make_post_process_key_event (context, &pre_data))
return;
- }
bus_input_context_emit_signal (context,
"DeleteSurroundingText",
g_variant_new ("(iu)",
@@ -2452,25 +2520,14 @@ static void
_engine_require_surrounding_text_cb (BusEngineProxy *engine,
BusInputContext *context)
{
+ SyncForwardingPreData pre_data = { 'r', };
+
g_assert (BUS_IS_ENGINE_PROXY (engine));
g_assert (BUS_IS_INPUT_CONTEXT (context));
-
g_assert (context->engine == engine);
- if (context->processing_key_event && g_queue_get_length (
- context->queue_during_process_key_event) <= MAX_SYNC_DATA) {
- SyncForwardingData *data;
- IBusText *text = ibus_text_new_from_static_string ("");
- if (g_queue_get_length (context->queue_during_process_key_event)
- == MAX_SYNC_DATA) {
- g_warning ("Exceed max number of post process_key_event data");
- }
- data = g_slice_new (SyncForwardingData);
- data->key = 'r';
- data->text = text;
- g_queue_push_tail (context->queue_during_process_key_event, data);
+ if (bus_input_context_make_post_process_key_event (context, &pre_data))
return;
- }
bus_input_context_emit_signal (context,
"RequireSurroundingText",
NULL,
@@ -3178,6 +3235,8 @@ bus_input_context_commit_text_use_extension (BusInputContext *context,
IBusText *text,
gboolean use_extension)
{
+ SyncForwardingPreData pre_data = { 'c', text, };
+
g_assert (BUS_IS_INPUT_CONTEXT (context));
g_assert (context->queue_during_process_key_event);
@@ -3186,17 +3245,9 @@ bus_input_context_commit_text_use_extension (BusInputContext *context,
if (use_extension && context->emoji_extension) {
bus_panel_proxy_commit_text_received (context->emoji_extension, text);
- } else if (context->processing_key_event && g_queue_get_length (
- context->queue_during_process_key_event) <= MAX_SYNC_DATA) {
- SyncForwardingData *data;
- if (g_queue_get_length (context->queue_during_process_key_event)
- == MAX_SYNC_DATA) {
- g_warning ("Exceed max number of sync process_key_event data");
- }
- data = g_slice_new (SyncForwardingData);
- data->key = 'c';
- data->text = g_object_ref (text);
- g_queue_push_tail (context->queue_during_process_key_event, data);
+ } else if (bus_input_context_make_post_process_key_event (context,
+ &pre_data)) {
+ return;
} else {
GVariant *variant = ibus_serializable_serialize (
(IBusSerializable *)text);
@@ -3245,9 +3296,18 @@ bus_input_context_update_preedit_text (BusInputContext *context,
context->preedit_cursor_pos,
context->preedit_visible);
} else if (PREEDIT_CONDITION) {
+ SyncForwardingPreData pre_data = { 'u', context->preedit_text, };
GVariant *variant = ibus_serializable_serialize (
(IBusSerializable *)context->preedit_text);
- if (context->client_commit_preedit) {
+ pre_data.u.uints[0] = context->preedit_cursor_pos;
+ pre_data.u.uints[1] = extension_visible ? 1 : 0;
+ pre_data.u.uints[2] = context->preedit_mode;
+ if (context->client_commit_preedit)
+ pre_data.key = 'm';
+ if (bus_input_context_make_post_process_key_event (context,
+ &pre_data)) {
+ return;
+ } else if (context->client_commit_preedit) {
bus_input_context_emit_signal (
context,
"UpdatePreeditTextWithMode",
diff --git a/src/ibusinputcontext.c b/src/ibusinputcontext.c
index c6a030fe..1b62f656 100644
--- a/src/ibusinputcontext.c
+++ b/src/ibusinputcontext.c
@@ -1403,10 +1403,104 @@ ibus_input_context_set_post_process_key_event (IBusInputContext *context,
g_variant_unref (var_post);
}
+
+static void
+ibus_input_context_fwd_text_to_commit (IBusInputContext *context,
+ IBusText *text)
+{
+ g_signal_emit (context, context_signals[COMMIT_TEXT], 0, text);
+}
+
+
+static void
+ibus_input_context_fwd_text_to_forward_key_event (IBusInputContext *context,
+ IBusText *text)
+{
+ gchar **array = NULL;
+ guint keyval, keycode, state;
+ array = g_strsplit (text->text, ",", -1);
+ keyval = g_ascii_strtoull (array[0], NULL, 10);
+ keycode = g_ascii_strtoull (array[1], NULL, 10);
+ state = g_ascii_strtoull (array[2], NULL, 10);
+ g_strfreev (array);
+ g_signal_emit (context,
+ context_signals[FORWARD_KEY_EVENT],
+ 0,
+ keyval,
+ keycode,
+ state | IBUS_FORWARD_MASK);
+}
+
+
+static void
+ibus_input_context_fwd_text_to_require_surrounding (IBusInputContext *context,
+ IBusText *text)
+{
+ IBusInputContextPrivate *priv;
+ g_assert (IBUS_IS_INPUT_CONTEXT (context));
+ priv = IBUS_INPUT_CONTEXT_GET_PRIVATE (IBUS_INPUT_CONTEXT (context));
+ priv->needs_surrounding_text = TRUE;
+ g_signal_emit (context, context_signals[REQUIRE_SURROUNDING_TEXT], 0);
+}
+
+
+static void
+ibus_input_context_fwd_text_to_delete_surrounding (IBusInputContext *context,
+ IBusText *text)
+{
+ gchar **array = NULL;
+ gint offset_from_cursor;
+ guint nchars;
+ array = g_strsplit (text->text, ",", -1);
+ offset_from_cursor = g_ascii_strtoll (array[0], NULL, 10);
+ nchars = g_ascii_strtoull (array[1], NULL, 10);
+ g_strfreev (array);
+ g_signal_emit (context,
+ context_signals[DELETE_SURROUNDING_TEXT],
+ 0,
+ offset_from_cursor,
+ nchars);
+}
+
+
+static void
+ibus_input_context_fwd_text_to_update_preedit (IBusInputContext *context,
+ IBusText *text,
+ IBusText *position,
+ char type)
+{
+ gchar **array = NULL;
+ guint32 cursor_pos;
+ gboolean visible;
+ guint mode = 0;
+
+ array = g_strsplit (position->text, ",", -1);
+ cursor_pos = g_ascii_strtoull (array[0], NULL, 10);
+ visible = g_ascii_strtoull (array[1], NULL, 10) ? TRUE : FALSE;
+ if (type == 'u') {
+ g_signal_emit (context,
+ context_signals[UPDATE_PREEDIT_TEXT],
+ 0,
+ text,
+ cursor_pos,
+ visible);
+ } else {
+ mode = g_ascii_strtoull (array[2], NULL, 10);
+ g_signal_emit (context,
+ context_signals[UPDATE_PREEDIT_TEXT_WITH_MODE],
+ 0,
+ text,
+ cursor_pos,
+ visible,
+ mode);
+ }
+ g_strfreev (array);
+}
+
+
void
ibus_input_context_post_process_key_event (IBusInputContext *context)
{
- IBusInputContextPrivate *priv;
GVariant *cached_var_post;
gboolean enable = FALSE;
GVariant *result;
@@ -1419,7 +1513,6 @@ ibus_input_context_post_process_key_event (IBusInputContext *context)
g_assert (IBUS_IS_INPUT_CONTEXT (context));
- priv = IBUS_INPUT_CONTEXT_GET_PRIVATE (IBUS_INPUT_CONTEXT (context));
cached_var_post =
g_dbus_proxy_get_cached_property ((GDBusProxy *)context,
"EffectivePostProcessKeyEvent");
@@ -1454,7 +1547,7 @@ ibus_input_context_post_process_key_event (IBusInputContext *context)
g_assert (variant);
g_variant_iter_init (&iter, variant);
size = g_variant_iter_n_children (&iter);
- while (size >0 && g_variant_iter_loop (&iter, "(yv)", &type, &vtext)) {
+ while (size > 0 && g_variant_iter_loop (&iter, "(yv)", &type, &vtext)) {
IBusText *text =
(IBusText *)ibus_serializable_deserialize_object (vtext);
if (!IBUS_IS_TEXT (text)) {
@@ -1463,43 +1556,48 @@ ibus_input_context_post_process_key_event (IBusInputContext *context)
}
switch (type) {
case 'c':
- g_signal_emit (context, context_signals[COMMIT_TEXT], 0, text);
+ ibus_input_context_fwd_text_to_commit (context, text);
break;
case 'f': {
- gchar **array = NULL;
- guint keyval, keycode, state;
- array = g_strsplit (text->text, ",", -1);
- keyval = g_ascii_strtoull (array[0], NULL, 10);
- keycode = g_ascii_strtoull (array[1], NULL, 10);
- state = g_ascii_strtoull (array[2], NULL, 10);
- g_strfreev (array);
- g_signal_emit (context,
- context_signals[FORWARD_KEY_EVENT],
- 0,
- keyval,
- keycode,
- state | IBUS_FORWARD_MASK);
+ ibus_input_context_fwd_text_to_forward_key_event (context, text);
break;
}
case 'r': {
- priv->needs_surrounding_text = TRUE;
- g_signal_emit (context,
- context_signals[REQUIRE_SURROUNDING_TEXT], 0);
+ ibus_input_context_fwd_text_to_require_surrounding (context, text);
break;
}
case 'd': {
- gchar **array = NULL;
- gint offset_from_cursor;
- guint nchars;
- array = g_strsplit (text->text, ",", -1);
- offset_from_cursor = g_ascii_strtoll (array[0], NULL, 10);
- nchars = g_ascii_strtoull (array[1], NULL, 10);
- g_strfreev (array);
- g_signal_emit (context,
- context_signals[DELETE_SURROUNDING_TEXT],
- 0,
- offset_from_cursor,
- nchars);
+ ibus_input_context_fwd_text_to_delete_surrounding (context, text);
+ break;
+ }
+ case 'u':
+ case 'm': {
+ IBusText *position;
+ g_clear_pointer (&vtext, g_variant_unref);
+ if (!g_variant_iter_loop (&iter, "(yv)", &type, &vtext)) {
+ g_warning ("%s: %s", G_STRFUNC,
+ "Type 'u' requires next type 'u'");
+ break;
+ }
+ if (type != 'u' && type != 'm') {
+ g_warning ("%s: %s", G_STRFUNC,
+ "The next of type 'u' should be type 'u'");
+ break;
+ }
+ position =
+ (IBusText *)ibus_serializable_deserialize_object (vtext);
+ if (!IBUS_IS_TEXT (position)) {
+ g_warning ("%s: %s", G_STRFUNC, "text is not IBusText");
+ break;
+ }
+ ibus_input_context_fwd_text_to_update_preedit (context,
+ text,
+ position,
+ type);
+ if (g_object_is_floating (position)) {
+ g_object_ref_sink (position);
+ g_object_unref (position);
+ }
break;
}
default:
--
2.41.0

View File

@ -58,7 +58,7 @@
Name: ibus
Version: 1.5.29~rc1
Release: 5%{?dist}
Release: 6%{?dist}
Summary: Intelligent Input Bus for Linux OS
License: LGPL-2.1-or-later
URL: https://github.com/ibus/%name/wiki
@ -257,6 +257,7 @@ This package contains IBus IM module for Wayland
%package panel
Summary: IBus Panel icon
Requires: %{name}%{?_isa} = %{version}-%{release}
Requires: %{name}-libs%{?_isa} = %{version}-%{release}
BuildRequires: libdbusmenu-gtk3-devel
%description panel
@ -579,6 +580,9 @@ dconf update || :
%{_datadir}/installed-tests/ibus
%changelog
* Wed Oct 25 2023 Takao Fujiwara <tfujiwar@redhat.com> - 1.5.29~rc1-6
- Add preedit D-Bus signals to PostProcessKeyEvent
* Mon Oct 23 2023 Takao Fujiwara <tfujiwar@redhat.com> - 1.5.29~rc1-5
- Add DeleteSurroundingText to PostProcessKeyEvent