Fix sync ibus_input_context_process_key_event() #2

This commit is contained in:
Takao Fujiwara 2023-07-09 19:24:21 +09:00
parent 25ad70d245
commit 38fc0edf90
3 changed files with 471 additions and 121 deletions

View File

@ -1,6 +1,6 @@
From f5790e1244fc6c83615ca4bc29494c7f16c73b6f Mon Sep 17 00:00:00 2001 From db158389251d9360518abcbdd1770d0e82dbb855 Mon Sep 17 00:00:00 2001
From: fujiwarat <takao.fujiwara1@gmail.com> From: fujiwarat <takao.fujiwara1@gmail.com>
Date: Sun, 11 Jun 2023 20:20:06 +0900 Date: Sun, 9 Jul 2023 19:04:44 +0900
Subject: [PATCH] Fix SEGV in bus_panel_proxy_focus_in() Subject: [PATCH] Fix SEGV in bus_panel_proxy_focus_in()
rhbz#1350291 SEGV in BUS_IS_CONNECTION(skip_connection) in rhbz#1350291 SEGV in BUS_IS_CONNECTION(skip_connection) in
@ -285,7 +285,7 @@ index e6001ebf..00828fbc 100644
panel->panel_type = panel_type; panel->panel_type = panel_type;
return panel; return panel;
diff --git a/client/x11/main.c b/client/x11/main.c diff --git a/client/x11/main.c b/client/x11/main.c
index 83d95cb7..804e40ed 100644 index b7eb5961..3075d5d0 100644
--- a/client/x11/main.c --- a/client/x11/main.c
+++ b/client/x11/main.c +++ b/client/x11/main.c
@@ -45,6 +45,7 @@ @@ -45,6 +45,7 @@
@ -386,7 +386,7 @@ index 83d95cb7..804e40ed 100644
g_free (x11ic->preedit_string); g_free (x11ic->preedit_string);
x11ic->preedit_string = NULL; x11ic->preedit_string = NULL;
@@ -438,6 +467,8 @@ xim_set_ic_focus (XIMS xims, IMChangeFocusStruct *call_data) @@ -439,6 +468,8 @@ xim_set_ic_focus (XIMS xims, IMChangeFocusStruct *call_data)
x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table, x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table,
GINT_TO_POINTER ((gint) call_data->icid)); GINT_TO_POINTER ((gint) call_data->icid));
g_return_val_if_fail (x11ic != NULL, 0); g_return_val_if_fail (x11ic != NULL, 0);
@ -395,7 +395,7 @@ index 83d95cb7..804e40ed 100644
ibus_input_context_focus_in (x11ic->context); ibus_input_context_focus_in (x11ic->context);
_xim_set_cursor_location (x11ic); _xim_set_cursor_location (x11ic);
@@ -456,6 +487,8 @@ xim_unset_ic_focus (XIMS xims, IMChangeFocusStruct *call_data) @@ -458,6 +489,8 @@ xim_unset_ic_focus (XIMS xims, IMChangeFocusStruct *call_data)
x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table, x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table,
GINT_TO_POINTER ((gint) call_data->icid)); GINT_TO_POINTER ((gint) call_data->icid));
g_return_val_if_fail (x11ic != NULL, 0); g_return_val_if_fail (x11ic != NULL, 0);
@ -404,8 +404,8 @@ index 83d95cb7..804e40ed 100644
ibus_input_context_focus_out (x11ic->context); ibus_input_context_focus_out (x11ic->context);
@@ -594,6 +627,8 @@ xim_forward_event (XIMS xims, IMForwardEventStruct *call_data) @@ -712,6 +745,8 @@ xim_forward_event (XIMS xims, IMForwardEventStruct *call_data)
x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table, _x11_ic_table,
GINT_TO_POINTER ((gint) call_data->icid)); GINT_TO_POINTER ((gint) call_data->icid));
g_return_val_if_fail (x11ic != NULL, 0); g_return_val_if_fail (x11ic != NULL, 0);
+ if (!x11ic->ibus_connected) + if (!x11ic->ibus_connected)
@ -413,7 +413,7 @@ index 83d95cb7..804e40ed 100644
xevent = (XKeyEvent*) &(call_data->event); xevent = (XKeyEvent*) &(call_data->event);
@@ -836,6 +871,8 @@ _xim_set_cursor_location (X11IC *x11ic) @@ -870,6 +905,8 @@ _xim_set_cursor_location (X11IC *x11ic)
} }
} }
@ -422,7 +422,7 @@ index 83d95cb7..804e40ed 100644
ibus_input_context_set_cursor_location (x11ic->context, ibus_input_context_set_cursor_location (x11ic->context,
preedit_area.x, preedit_area.x,
preedit_area.y, preedit_area.y,
@@ -916,6 +953,8 @@ xim_reset_ic (XIMS xims, IMResetICStruct *call_data) @@ -950,6 +987,8 @@ xim_reset_ic (XIMS xims, IMResetICStruct *call_data)
x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table, x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table,
GINT_TO_POINTER ((gint) call_data->icid)); GINT_TO_POINTER ((gint) call_data->icid));
g_return_val_if_fail (x11ic != NULL, 0); g_return_val_if_fail (x11ic != NULL, 0);
@ -431,7 +431,7 @@ index 83d95cb7..804e40ed 100644
ibus_input_context_reset (x11ic->context); ibus_input_context_reset (x11ic->context);
@@ -1275,7 +1314,12 @@ _atexit_cb () @@ -1309,7 +1348,12 @@ _atexit_cb ()
static void static void
_sighandler (int sig) _sighandler (int sig)
{ {
@ -611,5 +611,5 @@ index 9400e9ba..2ecbdac1 100644
#if VALA_0_34 #if VALA_0_34
seat.ungrab(); seat.ungrab();
-- --
2.40.0 2.41.0

View File

@ -2336,9 +2336,9 @@ index 68dde2f3..fee0b3ee 100644
-- --
2.41.0 2.41.0
From 8a1bd5ff72b7edf47526cfa19325f7e1dab85f59 Mon Sep 17 00:00:00 2001 From a73ea2c335145cd5d00ebfade83204d055aa268c Mon Sep 17 00:00:00 2001
From: fujiwarat <takao.fujiwara1@gmail.com> From: fujiwarat <takao.fujiwara1@gmail.com>
Date: Fri, 7 Jul 2023 08:49:49 +0900 Date: Sun, 9 Jul 2023 18:46:21 +0900
Subject: [PATCH 1/2] src: Fix sync ibus_input_context_process_key_event() Subject: [PATCH 1/2] src: Fix sync ibus_input_context_process_key_event()
The synchronous "ProcessKeyEvent" D-Bus method cannot receive The synchronous "ProcessKeyEvent" D-Bus method cannot receive
@ -2354,10 +2354,10 @@ method and ibus-daemon does not handle those signals.
BUG=https://github.com/ibus/ibus/issues/2486 BUG=https://github.com/ibus/ibus/issues/2486
--- ---
bus/inputcontext.c | 587 +++++++++++++++++++++++++++--------- bus/inputcontext.c | 587 +++++++++++++++++++++++++++---------
client/gtk2/ibusimcontext.c | 51 ++-- client/gtk2/ibusimcontext.c | 225 ++++++++++----
src/ibusinputcontext.c | 162 +++++++++- src/ibusinputcontext.c | 162 +++++++++-
src/ibusinputcontext.h | 30 +- src/ibusinputcontext.h | 30 +-
4 files changed, 652 insertions(+), 178 deletions(-) 4 files changed, 781 insertions(+), 223 deletions(-)
diff --git a/bus/inputcontext.c b/bus/inputcontext.c diff --git a/bus/inputcontext.c b/bus/inputcontext.c
index e76bbdfc..2110af87 100644 index e76bbdfc..2110af87 100644
@ -3658,7 +3658,7 @@ index e76bbdfc..2110af87 100644
GVariant *variant = ibus_serializable_serialize ( GVariant *variant = ibus_serializable_serialize (
(IBusSerializable *)text); (IBusSerializable *)text);
diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c
index ea8270bb..8ee85149 100644 index ea8270bb..d57575ce 100644
--- a/client/gtk2/ibusimcontext.c --- a/client/gtk2/ibusimcontext.c
+++ b/client/gtk2/ibusimcontext.c +++ b/client/gtk2/ibusimcontext.c
@@ -111,7 +111,7 @@ static guint _signal_delete_surrounding_id = 0; @@ -111,7 +111,7 @@ static guint _signal_delete_surrounding_id = 0;
@ -3670,10 +3670,35 @@ index ea8270bb..8ee85149 100644
#else #else
static const gchar *_no_snooper_apps = NO_SNOOPER_APPS; static const gchar *_no_snooper_apps = NO_SNOOPER_APPS;
static gboolean _use_key_snooper = ENABLE_SNOOPER; static gboolean _use_key_snooper = ENABLE_SNOOPER;
@@ -386,6 +386,23 @@ typedef struct { @@ -386,6 +386,7 @@ typedef struct {
gboolean retval; gboolean retval;
} ProcessKeyEventReplyData; } ProcessKeyEventReplyData;
+
static void
_process_key_event_done (GObject *object,
GAsyncResult *res,
@@ -435,6 +436,7 @@ _process_key_event_done (GObject *object,
#endif
}
+
static void
_process_key_event_reply_done (GObject *object,
GAsyncResult *res,
@@ -457,6 +459,7 @@ _process_key_event_reply_done (GObject *object,
g_source_remove (data->count_cb_id);
}
+
static gboolean
_process_key_event_count_cb (gpointer user_data)
{
@@ -472,6 +475,101 @@ _process_key_event_count_cb (gpointer user_data)
return G_SOURCE_CONTINUE;
}
+
+static gboolean +static gboolean
+_process_key_event_sync (IBusInputContext *context, +_process_key_event_sync (IBusInputContext *context,
+ guint keyval, + guint keyval,
@ -3691,10 +3716,87 @@ index ea8270bb..8ee85149 100644
+ return retval; + return retval;
+} +}
+ +
static void +
_process_key_event_done (GObject *object, +static gboolean
GAsyncResult *res, +_process_key_event_async (IBusInputContext *context,
@@ -505,10 +522,7 @@ _process_key_event (IBusInputContext *context, + guint keyval,
+ guint keycode,
+ guint state,
+ GdkEvent *event,
+ IBusIMContext *ibusimcontext)
+{
+ ProcessKeyEventData *data = g_slice_new0 (ProcessKeyEventData);
+
+ g_assert (event);
+ if (!data) {
+ g_warning ("Cannot allocate async data");
+ return _process_key_event_sync (context, keyval, keycode, state);
+ }
+#if GTK_CHECK_VERSION (3, 98, 4)
+ data->event = gdk_event_ref (event);
+#else
+ data->event = gdk_event_copy (event);
+#endif
+ data->ibusimcontext = ibusimcontext;
+ ibus_input_context_process_key_event_async (context,
+ keyval,
+ keycode - 8,
+ state,
+ -1,
+ NULL,
+ _process_key_event_done,
+ data);
+
+ return TRUE;
+}
+
+
+static gboolean
+_process_key_event_hybrid_async (IBusInputContext *context,
+ guint keyval,
+ guint keycode,
+ guint state)
+{
+ GSource *source = g_timeout_source_new (1);
+ ProcessKeyEventReplyData *data = NULL;
+ gboolean retval = FALSE;
+
+ if (source)
+ data = g_slice_new0 (ProcessKeyEventReplyData);
+ if (!data) {
+ g_warning ("Cannot wait for the reply of the process key event.");
+ retval = _process_key_event_sync (context, keyval, keycode, state);
+ if (source)
+ g_source_destroy (source);
+ return retval;
+ }
+ data->count = 1;
+ g_source_attach (source, NULL);
+ g_source_unref (source);
+ data->count_cb_id = g_source_get_id (source);
+ ibus_input_context_process_key_event_async (context,
+ keyval,
+ keycode - 8,
+ state,
+ -1,
+ NULL,
+ _process_key_event_reply_done,
+ data);
+ g_source_set_callback (source, _process_key_event_count_cb, data, NULL);
+ while (data->count)
+ g_main_context_iteration (NULL, TRUE);
+ /* #2498 Checking source->ref_count might cause Nautilus hang up
+ */
+ retval = data->retval;
+ g_slice_free (ProcessKeyEventReplyData, data);
+ return retval;
+}
+
+
static gboolean
_process_key_event (IBusInputContext *context,
#if GTK_CHECK_VERSION (3, 98, 4)
@@ -505,70 +603,20 @@ _process_key_event (IBusInputContext *context,
switch (_use_sync_mode) { switch (_use_sync_mode) {
case 1: { case 1: {
@ -3706,53 +3808,131 @@ index ea8270bb..8ee85149 100644
break; break;
} }
case 2: { case 2: {
@@ -519,10 +533,7 @@ _process_key_event (IBusInputContext *context, - GSource *source = g_timeout_source_new (1);
data = g_slice_new0 (ProcessKeyEventReplyData); - ProcessKeyEventReplyData *data = NULL;
if (!data) { -
g_warning ("Cannot wait for the reply of the process key event."); - if (source)
- data = g_slice_new0 (ProcessKeyEventReplyData);
- if (!data) {
- g_warning ("Cannot wait for the reply of the process key event.");
- retval = ibus_input_context_process_key_event (context, - retval = ibus_input_context_process_key_event (context,
- keyval, - keyval,
- keycode - 8, - keycode - 8,
- state); - state);
+ retval = _process_key_event_sync (context, keyval, keycode, state); - if (source)
if (source) - g_source_destroy (source);
g_source_destroy (source); - break;
break; - }
@@ -542,17 +553,19 @@ _process_key_event (IBusInputContext *context, - data->count = 1;
g_source_set_callback (source, _process_key_event_count_cb, data, NULL); - g_source_attach (source, NULL);
while (data->count) - g_source_unref (source);
g_main_context_iteration (NULL, TRUE); - data->count_cb_id = g_source_get_id (source);
- ibus_input_context_process_key_event_async (context,
- keyval,
- keycode - 8,
- state,
- -1,
- NULL,
- _process_key_event_reply_done,
- data);
- g_source_set_callback (source, _process_key_event_count_cb, data, NULL);
- while (data->count)
- g_main_context_iteration (NULL, TRUE);
- if (source->ref_count > 0) { - if (source->ref_count > 0) {
- /* g_source_get_id() could causes a SEGV */ - /* g_source_get_id() could causes a SEGV */
- g_info ("Broken GSource.ref_count and maybe a timing issue in %p.", - g_info ("Broken GSource.ref_count and maybe a timing issue in %p.",
- source); - source);
- } - }
+ /* #2498 Checking source->ref_count might cause Nautilus hang up - retval = data->retval;
+ */ - g_slice_free (ProcessKeyEventReplyData, data);
retval = data->retval; + retval = _process_key_event_hybrid_async (context,
g_slice_free (ProcessKeyEventReplyData, data); + keyval, keycode, state);
break; break;
} }
default: { default: {
ProcessKeyEventData *data = g_slice_new0 (ProcessKeyEventData); - ProcessKeyEventData *data = g_slice_new0 (ProcessKeyEventData);
+ if (!data) { -#if GTK_CHECK_VERSION (3, 98, 4)
+ g_warning ("Cannot allocate async data"); - data->event = gdk_event_ref (event);
+ retval = _process_key_event_sync (context, keyval, keycode, state); -#else
- data->event = gdk_event_copy ((GdkEvent *)event);
-#endif
- data->ibusimcontext = ibusimcontext;
- ibus_input_context_process_key_event_async (context,
- keyval,
- keycode - 8,
- state,
- -1,
- NULL,
- _process_key_event_done,
- data);
-
- retval = TRUE;
+ retval = _process_key_event_async (context,
+ keyval, keycode, state,
+ (GdkEvent *)event,
+ ibusimcontext);
+ break; + break;
+ } }
#if GTK_CHECK_VERSION (3, 98, 4) }
data->event = gdk_event_ref (event);
#else @@ -877,7 +925,55 @@ ibus_im_context_class_init (IBusIMContextClass *class)
@@ -877,7 +890,7 @@ ibus_im_context_class_init (IBusIMContextClass *class)
g_assert (_signal_retrieve_surrounding_id != 0); g_assert (_signal_retrieve_surrounding_id != 0);
#if GTK_CHECK_VERSION (3, 98, 4) #if GTK_CHECK_VERSION (3, 98, 4)
- _use_sync_mode = _get_char_env ("IBUS_ENABLE_SYNC_MODE", 2); - _use_sync_mode = _get_char_env ("IBUS_ENABLE_SYNC_MODE", 2);
+ /* IBus GtkIMModule, QtIMModlue, ibus-x11, ibus-wayland are called as
+ * IBus clients.
+ * Each GTK application, each QT application, Xorg server, Wayland
+ * comppsitor are called as IBus event owners here.
+ *
+ * The IBus client processes the key events between the IBus event owner
+ * and the IBus daemon and the procedure step is to:
+ *
+ * receive the key event from the IBus event owner and forward the
+ * event to the IBus daemon with the "ProcessKeyEvent" D-Bus method at
+ * first,
+ *
+ * receive the return value from the IBus daemon with the "ProessKeyEvent"
+ * D-Bus method and forward the value to the IBus event owner secondly and
+ * the return value includes if the key event is processed normally or not.
+ *
+ * The procedure behavior can be changed by the "IBUS_ENABLE_SYNC_MODE"
+ * environment variable with the synchronous procedure or asynchronous
+ * one and value is:
+ *
+ * 1: Synchronous process key event:
+ * Wait for the return of the IBus "ProcessKeyEvent" D-Bus method
+ * synchronously and forward the return value to the IBus event owner
+ * synchronously.
+ * 0: Asynchronous process key event:
+ * Return to the IBus event owner as the key event is processed normally
+ * at first as soon as the IBus client receives the event from the
+ * IBus event owner and also forward the event to the IBus daemon with
+ * the "ProcessKeyEvent" D-Bus method and wait for the return value of
+ * the D-Bus method *asynchronously*.
+ * If the return value indicates the key event is disposed by IBus,
+ * the IBus client does not perform anything. Otherwise the IBus client
+ * forwards the key event with the gdk_event_put() in GTK3,
+ * gtk_im_context_filter_key() in GTK4, IMForwardEvent() in XIM API.
+ * 2: Hybrid asynchronous process key event:
+ * Wait for the return of the IBus "ProcessKeyEvent" D-Bus method
+ * *asynchronously* with a GSource loop and forward the return value
+ * to the IBus event owner synchronously. So IBus clients perform
+ * virtually synchronously to cover problems of IBus synchronous APIs.
+ *
+ * The purpose of the asynchronous process is that each IBus input
+ * method can process the key events without D-Bus timeout and also
+ * the IBus synchronous process has a problem that the IBus
+ * "ProcessKeyEvent" D-Bus method cannot send the commit-text and
+ * forwar-key-event D-Bus signals until the D-Bus method is finished.
+ *
+ * Relative issues: #1713, #2486
+ */
+ _use_sync_mode = _get_char_env ("IBUS_ENABLE_SYNC_MODE", 1); + _use_sync_mode = _get_char_env ("IBUS_ENABLE_SYNC_MODE", 1);
#else #else
_use_key_snooper = !_get_boolean_env ("IBUS_DISABLE_SNOOPER", _use_key_snooper = !_get_boolean_env ("IBUS_DISABLE_SNOOPER",
!(ENABLE_SNOOPER)); !(ENABLE_SNOOPER));
@@ -1004,8 +1017,6 @@ ibus_im_context_init (GObject *obj) @@ -1004,8 +1100,6 @@ ibus_im_context_init (GObject *obj)
#else #else
ibusimcontext->caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS; ibusimcontext->caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS;
#endif #endif
@ -3761,15 +3941,16 @@ index ea8270bb..8ee85149 100644
ibusimcontext->events_queue = g_queue_new (); ibusimcontext->events_queue = g_queue_new ();
@@ -2265,6 +2276,7 @@ _create_input_context_done (IBusBus *bus, @@ -2265,6 +2359,8 @@ _create_input_context_done (IBusBus *bus,
else { else {
gboolean requested_surrounding_text = FALSE; gboolean requested_surrounding_text = FALSE;
ibus_input_context_set_client_commit_preedit (context, TRUE); ibus_input_context_set_client_commit_preedit (context, TRUE);
+ if (_use_sync_mode == 1)
+ ibus_input_context_set_post_process_key_event (context, TRUE); + ibus_input_context_set_post_process_key_event (context, TRUE);
ibusimcontext->ibuscontext = context; ibusimcontext->ibuscontext = context;
g_signal_connect (ibusimcontext->ibuscontext, g_signal_connect (ibusimcontext->ibuscontext,
@@ -2489,9 +2501,8 @@ _create_fake_input_context_done (IBusBus *bus, @@ -2489,9 +2585,8 @@ _create_fake_input_context_done (IBusBus *bus,
G_CALLBACK (_ibus_fake_context_destroy_cb), G_CALLBACK (_ibus_fake_context_destroy_cb),
NULL); NULL);
@ -4061,23 +4242,23 @@ index 09992148..1cb5126a 100644
-- --
2.41.0 2.41.0
From 1092bfa619749a931d65f80ec49e93b7b31f60f5 Mon Sep 17 00:00:00 2001 From dd7e85890ced5e53d982f02f5b11ef5a36e2eab8 Mon Sep 17 00:00:00 2001
From: fujiwarat <takao.fujiwara1@gmail.com> From: fujiwarat <takao.fujiwara1@gmail.com>
Date: Fri, 7 Jul 2023 08:52:51 +0900 Date: Sun, 9 Jul 2023 18:48:21 +0900
Subject: [PATCH 2/2] client/x11: Fix sync Subject: [PATCH 2/2] client/x11: Fix sync
ibus_input_context_process_key_event() ibus_input_context_process_key_event()
Fix the synchronous "ProcessKeyEvent" D-Bus method in ibus-x11 too. Fix the synchronous "ProcessKeyEvent" D-Bus method in ibus-x11 too.
Fixes: https://github.com/ibus/ibus/commit/8a1bd5f Fixes: https://github.com/ibus/ibus/commit/a73ea2c
BUG=https://github.com/ibus/ibus/issues/2486 BUG=https://github.com/ibus/ibus/issues/2486
--- ---
client/x11/main.c | 104 ++++++++++++++++++++++++---------------------- client/x11/main.c | 234 ++++++++++++++++++++++++++--------------------
1 file changed, 54 insertions(+), 50 deletions(-) 1 file changed, 134 insertions(+), 100 deletions(-)
diff --git a/client/x11/main.c b/client/x11/main.c diff --git a/client/x11/main.c b/client/x11/main.c
index 83d95cb7..13e7a1cf 100644 index 83d95cb7..b7eb5961 100644
--- a/client/x11/main.c --- a/client/x11/main.c
+++ b/client/x11/main.c +++ b/client/x11/main.c
@@ -126,7 +126,7 @@ static gint g_debug_level = 0; @@ -126,7 +126,7 @@ static gint g_debug_level = 0;
@ -4089,27 +4270,77 @@ index 83d95cb7..13e7a1cf 100644
static void static void
_xim_preedit_start (XIMS xims, const X11IC *x11ic) _xim_preedit_start (XIMS xims, const X11IC *x11ic)
@@ -380,9 +380,8 @@ xim_create_ic (XIMS xims, IMChangeICStruct *call_data) @@ -380,9 +380,9 @@ xim_create_ic (XIMS xims, IMChangeICStruct *call_data)
if (x11ic->input_style & XIMPreeditCallbacks) if (x11ic->input_style & XIMPreeditCallbacks)
capabilities |= IBUS_CAP_PREEDIT_TEXT; capabilities |= IBUS_CAP_PREEDIT_TEXT;
- if (_use_sync_mode == 1) - if (_use_sync_mode == 1)
- capabilities |= IBUS_CAP_SYNC_PROCESS_KEY_V2; - capabilities |= IBUS_CAP_SYNC_PROCESS_KEY_V2;
ibus_input_context_set_capabilities (x11ic->context, capabilities); ibus_input_context_set_capabilities (x11ic->context, capabilities);
+ if (_use_sync_mode == 1)
+ ibus_input_context_set_post_process_key_event (x11ic->context, TRUE); + ibus_input_context_set_post_process_key_event (x11ic->context, TRUE);
g_hash_table_insert (_x11_ic_table, g_hash_table_insert (_x11_ic_table,
GINT_TO_POINTER (x11ic->icid), (gpointer)x11ic); GINT_TO_POINTER (x11ic->icid), (gpointer)x11ic);
@@ -498,6 +497,26 @@ typedef struct { @@ -427,6 +427,7 @@ xim_destroy_ic (XIMS xims, IMChangeICStruct *call_data)
return 1;
}
+
static int
xim_set_ic_focus (XIMS xims, IMChangeFocusStruct *call_data)
{
@@ -445,6 +446,7 @@ xim_set_ic_focus (XIMS xims, IMChangeFocusStruct *call_data)
return 1;
}
+
static int
xim_unset_ic_focus (XIMS xims, IMChangeFocusStruct *call_data)
{
@@ -463,6 +465,7 @@ xim_unset_ic_focus (XIMS xims, IMChangeFocusStruct *call_data)
}
+
static void
_xim_forward_key_event_done (X11IC *x11ic,
XEvent *event,
@@ -498,6 +501,7 @@ typedef struct {
XEvent event; XEvent event;
} ProcessKeyEventReplyData; } ProcessKeyEventReplyData;
+static gboolean +
static void
_process_key_event_done (GObject *object,
GAsyncResult *res,
@@ -529,6 +533,7 @@ _process_key_event_done (GObject *object,
g_slice_free (ProcessKeyEventReplyData, data);
}
+
static void
_process_key_event_reply_done (GObject *object,
GAsyncResult *res,
@@ -566,6 +571,7 @@ _process_key_event_reply_done (GObject *object,
g_source_remove (data->count_cb_id);
}
+
static gboolean
_process_key_event_count_cb (gpointer user_data)
{
@@ -580,19 +586,131 @@ _process_key_event_count_cb (gpointer user_data)
return G_SOURCE_CONTINUE;
}
+
+static int
+_process_key_event_sync (X11IC *x11ic, +_process_key_event_sync (X11IC *x11ic,
+ IMForwardEventStruct *call_data, + IMForwardEventStruct *call_data,
+ GdkEventKey *event) + GdkEventKey *event)
+{ +{
+ gboolean retval = FALSE; + gboolean retval;
+ +
+ g_assert (x11ic); + g_assert (x11ic);
+ g_assert (call_data); + g_assert (call_data);
@ -4121,16 +4352,125 @@ index 83d95cb7..13e7a1cf 100644
+ event->state); + event->state);
+ ibus_input_context_post_process_key_event (x11ic->context); + ibus_input_context_post_process_key_event (x11ic->context);
+ _xim_forward_key_event_done (x11ic, &call_data->event, retval); + _xim_forward_key_event_done (x11ic, &call_data->event, retval);
+ return TRUE; + return 1;
+} +}
+ +
static void +
_process_key_event_done (GObject *object, +static int
GAsyncResult *res, +_process_key_event_async (X11IC *x11ic,
@@ -609,14 +628,7 @@ xim_forward_event (XIMS xims, IMForwardEventStruct *call_data) + IMForwardEventStruct *call_data,
+ GdkEventKey *event)
+{
+ ProcessKeyEventReplyData *data;
+
+ g_assert (x11ic);
+ g_assert (call_data);
+ g_assert (event);
+ if (!(data = g_slice_new0 (ProcessKeyEventReplyData))) {
+ g_warning ("Cannot allocate async data");
+ return _process_key_event_sync (x11ic, call_data, event);
+ }
+ data->connect_id = call_data->connect_id;
+ data->x11ic = x11ic;
+ data->event = call_data->event;
+ ibus_input_context_process_key_event_async (x11ic->context,
+ event->keyval,
+ event->hardware_keycode - 8,
+ event->state,
+ -1,
+ NULL,
+ _process_key_event_done,
+ data);
+ return 1;
+}
+
+
+static int
+_process_key_event_hybrid_async (X11IC *x11ic,
+ IMForwardEventStruct *call_data,
+ GdkEventKey *event)
+{
+ GSource *source;
+ ProcessKeyEventReplyData *data = NULL;
+ gboolean bus_retval;
+
+ g_assert (x11ic);
+ g_assert (call_data);
+ g_assert (event);
+ source = g_timeout_source_new (1);
+ if (source)
+ data = g_slice_new0 (ProcessKeyEventReplyData);
+ if (!data) {
+ int xim_retval;
+ g_warning ("Cannot wait for the reply of the process key event.");
+ xim_retval = _process_key_event_sync (x11ic, call_data, event);
+ if (source)
+ g_source_destroy (source);
+ return xim_retval;
+ }
+ data->count = 1;
+ g_source_attach (source, NULL);
+ g_source_unref (source);
+ data->count_cb_id = g_source_get_id (source);
+ data->connect_id = call_data->connect_id;
+ data->x11ic = x11ic;
+ data->event = call_data->event;
+ ibus_input_context_process_key_event_async (x11ic->context,
+ event->keyval,
+ event->hardware_keycode - 8,
+ event->state,
+ -1,
+ NULL,
+ _process_key_event_reply_done,
+ data);
+ g_source_set_callback (source, _process_key_event_count_cb,
+ data, NULL);
+ while (data->count > 0 && data->count < MAX_WAIT_KEY_TIME)
+ g_main_context_iteration (NULL, TRUE);
+ /* #2498 Checking source->ref_count might cause Nautilus hang up
+ */
+ bus_retval = data->retval;
+ if (data->count == 0) {
+ g_slice_free (ProcessKeyEventReplyData, data);
+ return 1;
+ }
+
+ g_slice_free (ProcessKeyEventReplyData, data);
+ if (g_hash_table_lookup (_connections,
+ GINT_TO_POINTER ((gint)call_data->connect_id))
+ == NULL) {
+ return 1;
+ }
+ _xim_forward_key_event_done (x11ic, &call_data->event, bus_retval);
+ return 1;
+}
+
+
static int
xim_forward_event (XIMS xims, IMForwardEventStruct *call_data)
{
X11IC *x11ic;
XKeyEvent *xevent;
GdkEventKey event;
- gboolean retval;
LOG (1, "XIM_FORWARD_EVENT ic=%d connect_id=%d",
- call_data->icid, call_data->connect_id);
+ call_data->icid, call_data->connect_id);
- x11ic = (X11IC *) g_hash_table_lookup (_x11_ic_table,
- GINT_TO_POINTER ((gint) call_data->icid));
+ x11ic = (X11IC *) g_hash_table_lookup (
+ _x11_ic_table,
+ GINT_TO_POINTER ((gint) call_data->icid));
g_return_val_if_fail (x11ic != NULL, 0);
xevent = (XKeyEvent*) &(call_data->event);
@@ -608,99 +726,15 @@ xim_forward_event (XIMS xims, IMForwardEventStruct *call_data)
}
switch (_use_sync_mode) { switch (_use_sync_mode) {
case 1: { - case 1: {
- retval = ibus_input_context_process_key_event ( - retval = ibus_input_context_process_key_event (
- x11ic->context, - x11ic->context,
- event.keyval, - event.keyval,
@ -4139,22 +4479,22 @@ index 83d95cb7..13e7a1cf 100644
- _xim_forward_key_event_done (x11ic, &call_data->event, retval); - _xim_forward_key_event_done (x11ic, &call_data->event, retval);
- retval = 1; - retval = 1;
- break; - break;
+ return _process_key_event_sync (x11ic, call_data, &event); - }
} - case 2: {
case 2: { - GSource *source = g_timeout_source_new (1);
GSource *source = g_timeout_source_new (1); - ProcessKeyEventReplyData *data = NULL;
@@ -626,44 +638,37 @@ xim_forward_event (XIMS xims, IMForwardEventStruct *call_data) -
data = g_slice_new0 (ProcessKeyEventReplyData); - if (source)
if (!data) { - data = g_slice_new0 (ProcessKeyEventReplyData);
g_warning ("Cannot wait for the reply of the process key event."); - if (!data) {
- g_warning ("Cannot wait for the reply of the process key event.");
- retval = ibus_input_context_process_key_event ( - retval = ibus_input_context_process_key_event (
- x11ic->context, - x11ic->context,
- event.keyval, - event.keyval,
- event.hardware_keycode - 8, - event.hardware_keycode - 8,
- event.state); - event.state);
+ retval = _process_key_event_sync (x11ic, call_data, &event); - if (source)
if (source) - g_source_destroy (source);
g_source_destroy (source);
- } else { - } else {
- data->count = 1; - data->count = 1;
- g_source_attach (source, NULL); - g_source_attach (source, NULL);
@ -4186,48 +4526,55 @@ index 83d95cb7..13e7a1cf 100644
- g_slice_free (ProcessKeyEventReplyData, data); - g_slice_free (ProcessKeyEventReplyData, data);
- return 1; - return 1;
- } - }
+ break; - }
+ } -
+ data->count = 1; - g_slice_free (ProcessKeyEventReplyData, data);
+ g_source_attach (source, NULL); - if (g_hash_table_lookup (_connections,
+ g_source_unref (source); - GINT_TO_POINTER ((gint)call_data->connect_id))
+ data->count_cb_id = g_source_get_id (source); - == NULL) {
+ data->connect_id = call_data->connect_id; - return 1;
+ data->x11ic = x11ic; - }
+ data->event = *((XEvent*)xevent); - _xim_forward_key_event_done (x11ic, &call_data->event, retval);
+ ibus_input_context_process_key_event_async ( - retval = 1;
+ x11ic->context, - break;
+ event.keyval, - }
+ event.hardware_keycode - 8, - default: {
+ event.state, - ProcessKeyEventReplyData *data;
+ -1, -
+ NULL, - if (!(data = g_slice_new0 (ProcessKeyEventReplyData))) {
+ _process_key_event_reply_done, - g_warning ("Cannot allocate async data");
+ data);
+ g_source_set_callback (source, _process_key_event_count_cb,
+ data, NULL);
+ while (data->count > 0 && data->count < MAX_WAIT_KEY_TIME)
+ g_main_context_iteration (NULL, TRUE);
+ /* #2498 Checking source->ref_count might cause Nautilus hang up
+ */
+ retval = data->retval;
+ if (data->count == 0) {
+ g_slice_free (ProcessKeyEventReplyData, data);
+ return 1;
}
g_slice_free (ProcessKeyEventReplyData, data);
@@ -681,8 +686,7 @@ xim_forward_event (XIMS xims, IMForwardEventStruct *call_data)
if (!(data = g_slice_new0 (ProcessKeyEventReplyData))) {
g_warning ("Cannot allocate async data");
- _xim_forward_key_event_done (x11ic, &call_data->event, 0); - _xim_forward_key_event_done (x11ic, &call_data->event, 0);
- return 1; - return 1;
- }
- data->connect_id = call_data->connect_id;
- data->x11ic = x11ic;
- data->event = call_data->event;
-
- ibus_input_context_process_key_event_async (
- x11ic->context,
- event.keyval,
- event.hardware_keycode - 8,
- event.state,
- -1,
- NULL,
- _process_key_event_done,
- data);
- retval = 1;
- }
+ case 1:
+ return _process_key_event_sync (x11ic, call_data, &event); + return _process_key_event_sync (x11ic, call_data, &event);
+ case 2:
+ return _process_key_event_hybrid_async (x11ic, call_data, &event);
+ default:
+ return _process_key_event_async (x11ic, call_data, &event);
} }
data->connect_id = call_data->connect_id; - return retval;
data->x11ic = x11ic; + g_assert_not_reached ();
@@ -1186,7 +1190,7 @@ _init_ibus (void) + return 0;
}
@@ -1186,7 +1220,7 @@ _init_ibus (void)
G_CALLBACK (_bus_disconnected_cb), NULL); G_CALLBACK (_bus_disconnected_cb), NULL);
/* https://github.com/ibus/ibus/issues/1713 */ /* https://github.com/ibus/ibus/issues/1713 */

View File

@ -50,7 +50,7 @@
Name: ibus Name: ibus
Version: 1.5.28 Version: 1.5.28
Release: 11%{?dist} Release: 12%{?dist}
Summary: Intelligent Input Bus for Linux OS Summary: Intelligent Input Bus for Linux OS
License: LGPL-2.0-or-later License: LGPL-2.0-or-later
URL: https://github.com/ibus/%name/wiki URL: https://github.com/ibus/%name/wiki
@ -557,6 +557,9 @@ dconf update || :
%{_datadir}/installed-tests/ibus %{_datadir}/installed-tests/ibus
%changelog %changelog
* Sun Jul 09 2023 Takao Fujiwara <tfujiwar@redhat.com> - 1.5.28-12
- Fix sync ibus_input_context_process_key_event() #2
* Fri Jul 07 2023 Takao Fujiwara <tfujiwar@redhat.com> - 1.5.28-11 * Fri Jul 07 2023 Takao Fujiwara <tfujiwar@redhat.com> - 1.5.28-11
- Fix sync ibus_input_context_process_key_event() - Fix sync ibus_input_context_process_key_event()