public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Takao Fujiwara <tfujiwar@redhat.com>
To: git-commits@fedoraproject.org
Subject: [rpms/ibus] autotool: Implement new process_key_event for ibus-x11
Date: Sun, 31 May 2026 02:08:00 GMT [thread overview]
Message-ID: <178019328086.1.12971573730071995190.rpms-ibus-82f34afdef47@fedoraproject.org> (raw)
A new commit has been pushed.
Repo : rpms/ibus
Branch : autotool
Commit : 82f34afdef475e28efbac46e42eff79304dcf36d
Author : Takao Fujiwara <tfujiwar@redhat.com>
Date : 2022-11-24T17:59:03+09:00
Stats : +436/-1 in 2 file(s)
URL : https://src.fedoraproject.org/rpms/ibus/c/82f34afdef475e28efbac46e42eff79304dcf36d?branch=autotool
Log:
Implement new process_key_event for ibus-x11
---
diff --git a/ibus-HEAD.patch b/ibus-HEAD.patch
index 9f57a0d..c95240e 100644
--- a/ibus-HEAD.patch
+++ b/ibus-HEAD.patch
@@ -318,3 +318,435 @@ index a4529c88..9400e9ba 100644
--
2.37.3
+From 506ac9993d5166196b7c4e9bfa9fb0f9d3792ffa Mon Sep 17 00:00:00 2001
+From: fujiwarat <takao.fujiwara1@gmail.com>
+Date: Thu, 10 Nov 2022 18:38:05 +0900
+Subject: [PATCH] client/x11: Implement new process_key_event for ibus-x11
+
+The new process_key_event is ported from GTK4 to X11 because
+hangul maintainers wish to delete forward_key_event as much as possible
+and currently we could apply forward_key_event to the sync mode only
+and the new process_key_event is a new async key event process in X11
+and hangul might disable forward_key_event by default.
+
+Now the definition of IBUS_CAP_SYNC_PROCESS_KEY_V2 capability is changed
+to set only if the sync mode.
+
+Also switch a heavy GMainLoop to the light GSource.
+
+Fixes: https://github.com/ibus/ibus/commit/c957c5f
+---
+ client/gtk2/ibusimcontext.c | 61 ++++++++++----
+ client/x11/main.c | 157 +++++++++++++++++++++++++++++++-----
+ src/ibustypes.h | 1 +
+ 3 files changed, 184 insertions(+), 35 deletions(-)
+
+diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c
+index 6e338157..1f3723e6 100644
+--- a/client/gtk2/ibusimcontext.c
++++ b/client/gtk2/ibusimcontext.c
+@@ -382,8 +382,9 @@ typedef struct {
+ } ProcessKeyEventData;
+
+ typedef struct {
+- GMainLoop *loop;
+- gboolean retval;
++ int count;
++ guint count_cb_id;
++ gboolean retval;
+ } ProcessKeyEventReplyData;
+
+ static void
+@@ -453,7 +454,23 @@ _process_key_event_reply_done (GObject *object,
+ }
+ g_return_if_fail (data);
+ data->retval = retval;
+- g_main_loop_quit (data->loop);
++ data->count = 0;
++ g_source_remove (data->count_cb_id);
++}
++
++static gboolean
++_process_key_event_count_cb (gpointer user_data)
++{
++ ProcessKeyEventReplyData *data = (ProcessKeyEventReplyData *)user_data;
++ g_return_val_if_fail (data, G_SOURCE_REMOVE);
++ if (!data->count)
++ return G_SOURCE_REMOVE;
++ /* Wait for about 10 secs. */
++ if (data->count++ == 10000) {
++ data->count = 0;
++ return G_SOURCE_REMOVE;
++ }
++ return G_SOURCE_CONTINUE;
+ }
+
+ static gboolean
+@@ -496,10 +513,10 @@ _process_key_event (IBusInputContext *context,
+ break;
+ }
+ case 2: {
+- GMainLoop *loop = g_main_loop_new (NULL, TRUE);
++ GSource *source = g_timeout_source_new (1);
+ ProcessKeyEventReplyData *data = NULL;
+
+- if (loop)
++ if (source)
+ data = g_slice_new0 (ProcessKeyEventReplyData);
+ if (!data) {
+ g_warning ("Cannot wait for the reply of the process key event.");
+@@ -507,11 +524,14 @@ _process_key_event (IBusInputContext *context,
+ keyval,
+ keycode - 8,
+ state);
+- if (loop)
+- g_main_loop_quit (loop);
++ if (source)
++ g_source_destroy (source);
+ break;
+ }
+- data->loop = loop;
++ 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,
+@@ -520,7 +540,14 @@ _process_key_event (IBusInputContext *context,
+ NULL,
+ _process_key_event_reply_done,
+ data);
+- g_main_loop_run (loop);
++ 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) {
++ /* g_source_get_id() could causes a SEGV */
++ g_info ("Broken GSource.ref_count and maybe a timing issue in %p.",
++ source);
++ }
+ retval = data->retval;
+ g_slice_free (ProcessKeyEventReplyData, data);
+ break;
+@@ -994,8 +1021,8 @@ ibus_im_context_init (GObject *obj)
+ #else
+ ibusimcontext->caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS;
+ #endif
+- if (_use_sync_mode != 1)
+- ibusimcontext->caps |= IBUS_CAP_SYNC_PROCESS_KEY;
++ if (_use_sync_mode == 1)
++ ibusimcontext->caps |= IBUS_CAP_SYNC_PROCESS_KEY_V2;
+
+ ibusimcontext->events_queue = g_queue_new ();
+
+@@ -1338,7 +1365,7 @@ ibus_im_context_reset (GtkIMContext *context)
+ * IBus uses button-press-event instead until GTK is fixed.
+ * https://gitlab.gnome.org/GNOME/gtk/issues/1534
+ */
+- if (_use_sync_mode == 1)
++ if (_use_sync_mode != 0)
+ ibus_im_context_clear_preedit_text (ibusimcontext);
+ ibus_input_context_reset (ibusimcontext->ibuscontext);
+ }
+@@ -1453,7 +1480,7 @@ ibus_im_context_set_client_window (GtkIMContext *context,
+
+ if (ibusimcontext->client_window) {
+ #if !GTK_CHECK_VERSION (3, 98, 4)
+- if (ibusimcontext->use_button_press_event && _use_sync_mode != 1)
++ if (ibusimcontext->use_button_press_event && _use_sync_mode == 0)
+ _connect_button_press_event (ibusimcontext, FALSE);
+ #endif
+ g_object_unref (ibusimcontext->client_window);
+@@ -1463,7 +1490,7 @@ ibus_im_context_set_client_window (GtkIMContext *context,
+ if (client != NULL) {
+ ibusimcontext->client_window = g_object_ref (client);
+ #if !GTK_CHECK_VERSION (3, 98, 4)
+- if (!ibusimcontext->use_button_press_event && _use_sync_mode != 1)
++ if (!ibusimcontext->use_button_press_event && _use_sync_mode == 0)
+ _connect_button_press_event (ibusimcontext, TRUE);
+ #endif
+ }
+@@ -2085,7 +2112,7 @@ _ibus_context_update_preedit_text_cb (IBusInputContext *ibuscontext,
+ #if !GTK_CHECK_VERSION (3, 98, 4)
+ if (!ibusimcontext->use_button_press_event &&
+ mode == IBUS_ENGINE_PREEDIT_COMMIT &&
+- _use_sync_mode != 1) {
++ _use_sync_mode == 0) {
+ if (ibusimcontext->client_window) {
+ _connect_button_press_event (ibusimcontext, TRUE);
+ }
+@@ -2459,8 +2486,8 @@ _create_fake_input_context_done (IBusBus *bus,
+ NULL);
+
+ guint32 caps = IBUS_CAP_PREEDIT_TEXT | IBUS_CAP_FOCUS | IBUS_CAP_SURROUNDING_TEXT;
+- if (_use_sync_mode != 1)
+- caps |= IBUS_CAP_SYNC_PROCESS_KEY;
++ if (_use_sync_mode == 1)
++ caps |= IBUS_CAP_SYNC_PROCESS_KEY_V2;
+ ibus_input_context_set_capabilities (_fake_context, caps);
+
+ /* focus in/out the fake context */
+diff --git a/client/x11/main.c b/client/x11/main.c
+index 6057cc03..905fd251 100644
+--- a/client/x11/main.c
++++ b/client/x11/main.c
+@@ -124,7 +124,7 @@ static gint g_debug_level = 0;
+
+ static IBusBus *_bus = NULL;
+
+-static gboolean _use_sync_mode = TRUE;
++static char _use_sync_mode = 2;
+
+ static void
+ _xim_preedit_start (XIMS xims, const X11IC *x11ic)
+@@ -331,6 +331,7 @@ xim_create_ic (XIMS xims, IMChangeICStruct *call_data)
+ {
+ static int base_icid = 1;
+ X11IC *x11ic;
++ guint32 capabilities = IBUS_CAP_FOCUS;
+
+ call_data->icid = base_icid ++;
+
+@@ -375,12 +376,11 @@ xim_create_ic (XIMS xims, IMChangeICStruct *call_data)
+ G_CALLBACK (_context_disabled_cb), x11ic);
+
+
+- if (x11ic->input_style & XIMPreeditCallbacks) {
+- ibus_input_context_set_capabilities (x11ic->context, IBUS_CAP_FOCUS | IBUS_CAP_PREEDIT_TEXT);
+- }
+- else {
+- ibus_input_context_set_capabilities (x11ic->context, IBUS_CAP_FOCUS);
+- }
++ if (x11ic->input_style & XIMPreeditCallbacks)
++ capabilities |= IBUS_CAP_PREEDIT_TEXT;
++ if (_use_sync_mode == 1)
++ capabilities |= IBUS_CAP_SYNC_PROCESS_KEY_V2;
++ ibus_input_context_set_capabilities (x11ic->context, capabilities);
+
+ g_hash_table_insert (_x11_ic_table,
+ GINT_TO_POINTER (x11ic->icid), (gpointer)x11ic);
+@@ -461,6 +461,13 @@ xim_unset_ic_focus (XIMS xims, IMChangeFocusStruct *call_data)
+
+ }
+
++typedef struct {
++ IMForwardEventStruct *pfe;
++ int count;
++ guint count_cb_id;
++ gboolean retval;
++} ProcessKeyEventReplyData;
++
+ static void
+ _process_key_event_done (GObject *object,
+ GAsyncResult *res,
+@@ -493,6 +500,43 @@ _process_key_event_done (GObject *object,
+ g_slice_free (IMForwardEventStruct, pfe);
+ }
+
++static void
++_process_key_event_reply_done (GObject *object,
++ GAsyncResult *res,
++ gpointer user_data)
++{
++ IBusInputContext *context = (IBusInputContext *)object;
++ ProcessKeyEventReplyData *data = (ProcessKeyEventReplyData *)user_data;
++ GError *error = NULL;
++ gboolean retval = ibus_input_context_process_key_event_async_finish (
++ context,
++ res,
++ &error);
++ if (error != NULL) {
++ g_warning ("Process Key Event failed: %s.", error->message);
++ g_error_free (error);
++ }
++ g_return_if_fail (data);
++ data->retval = retval;
++ data->count = 0;
++ g_source_remove (data->count_cb_id);
++}
++
++static gboolean
++_process_key_event_count_cb (gpointer user_data)
++{
++ ProcessKeyEventReplyData *data = (ProcessKeyEventReplyData *)user_data;
++ g_return_val_if_fail (data, G_SOURCE_REMOVE);
++ if (!data->count)
++ return G_SOURCE_REMOVE;
++ /* Wait for about 10 secs. */
++ if (data->count++ == 10000) {
++ data->count = 0;
++ return G_SOURCE_REMOVE;
++ }
++ return G_SOURCE_CONTINUE;
++}
++
+ static int
+ xim_forward_event (XIMS xims, IMForwardEventStruct *call_data)
+ {
+@@ -520,14 +564,15 @@ xim_forward_event (XIMS xims, IMForwardEventStruct *call_data)
+ event.state |= IBUS_RELEASE_MASK;
+ }
+
+- if (_use_sync_mode) {
++ switch (_use_sync_mode) {
++ case 1: {
+ retval = ibus_input_context_process_key_event (
+ x11ic->context,
+ event.keyval,
+ event.hardware_keycode - 8,
+ event.state);
+ if (retval) {
+- if (! x11ic->has_preedit_area) {
++ if (!x11ic->has_preedit_area) {
+ _xim_set_cursor_location (x11ic);
+ }
+ return 1;
+@@ -546,8 +591,80 @@ xim_forward_event (XIMS xims, IMForwardEventStruct *call_data)
+ IMForwardEvent (_xims, (XPointer) &fe);
+
+ retval = 1;
++ break;
+ }
+- else {
++ case 2: {
++ GSource *source = g_timeout_source_new (1);
++ ProcessKeyEventReplyData *data = NULL;
++ IMForwardEventStruct fe;
++
++ 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 (
++ x11ic->context,
++ event.keyval,
++ event.hardware_keycode - 8,
++ event.state);
++ if (source)
++ g_source_destroy (source);
++ } else {
++ CARD16 connect_id = x11ic->connect_id;
++ 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 (
++ 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)
++ g_main_context_iteration (NULL, TRUE);
++ if (source->ref_count > 0) {
++ /* g_source_get_id() could causes a SEGV */
++ g_info ("Broken GSource.ref_count and maybe a timing "
++ "issue in %p.", source);
++ }
++ retval = data->retval;
++ g_slice_free (ProcessKeyEventReplyData, data);
++
++ if (g_hash_table_lookup (_connections,
++ GINT_TO_POINTER ((gint)connect_id))
++ == NULL) {
++ return 1;
++ }
++ }
++
++ if (retval) {
++ if (! x11ic->has_preedit_area) {
++ _xim_set_cursor_location (x11ic);
++ }
++ return 1;
++ }
++
++ memset (&fe, 0, sizeof (fe));
++
++ fe.major_code = XIM_FORWARD_EVENT;
++ fe.icid = x11ic->icid;
++ fe.connect_id = x11ic->connect_id;
++ fe.sync_bit = 0;
++ fe.serial_number = 0L;
++ fe.event = call_data->event;
++
++ IMForwardEvent (_xims, (XPointer) &fe);
++
++ retval = 1;
++ break;
++ }
++ default: {
+ IMForwardEventStruct *pfe;
+
+ pfe = g_slice_new0 (IMForwardEventStruct);
+@@ -569,6 +686,7 @@ xim_forward_event (XIMS xims, IMForwardEventStruct *call_data)
+ pfe);
+ retval = 1;
+ }
++ }
+ return retval;
+ }
+
+@@ -1026,23 +1144,26 @@ _context_disabled_cb (IBusInputContext *context,
+ _xim_preedit_end (_xims, x11ic);
+ }
+
+-static gboolean
+-_get_boolean_env(const gchar *name,
+- gboolean defval)
++static char
++_get_char_env (const gchar *name,
++ char defval)
+ {
+ const gchar *value = g_getenv (name);
+
+ if (value == NULL)
+- return defval;
++ return defval;
+
+ if (g_strcmp0 (value, "") == 0 ||
+ g_strcmp0 (value, "0") == 0 ||
+ g_strcmp0 (value, "false") == 0 ||
+ g_strcmp0 (value, "False") == 0 ||
+- g_strcmp0 (value, "FALSE") == 0)
+- return FALSE;
++ g_strcmp0 (value, "FALSE") == 0) {
++ return 0;
++ } else if (!g_strcmp0 (value, "2")) {
++ return 2;
++ }
+
+- return TRUE;
++ return 1;
+ }
+
+ static void
+@@ -1059,7 +1180,7 @@ _init_ibus (void)
+ G_CALLBACK (_bus_disconnected_cb), NULL);
+
+ /* https://github.com/ibus/ibus/issues/1713 */
+- _use_sync_mode = _get_boolean_env ("IBUS_ENABLE_SYNC_MODE", TRUE);
++ _use_sync_mode = _get_char_env ("IBUS_ENABLE_SYNC_MODE", 2);
+ }
+
+ static void
+diff --git a/src/ibustypes.h b/src/ibustypes.h
+index a8eee319..ba2a0010 100644
+--- a/src/ibustypes.h
++++ b/src/ibustypes.h
+@@ -124,6 +124,7 @@ typedef enum {
+ IBUS_CAP_SURROUNDING_TEXT = 1 << 5,
+ IBUS_CAP_OSK = 1 << 6,
+ IBUS_CAP_SYNC_PROCESS_KEY = 1 << 7,
++ IBUS_CAP_SYNC_PROCESS_KEY_V2 = IBUS_CAP_SYNC_PROCESS_KEY,
+ } IBusCapabilite;
+
+ /**
+--
+2.37.3
+
diff --git a/ibus.spec b/ibus.spec
index 01e1d49..92dbc75 100644
--- a/ibus.spec
+++ b/ibus.spec
@@ -39,7 +39,7 @@
Name: ibus
Version: 1.5.27
-Release: 5%{?dist}
+Release: 6%{?dist}
Summary: Intelligent Input Bus for Linux OS
License: LGPL-2.0-or-later
URL: https://github.com/ibus/%name/wiki
@@ -523,6 +523,9 @@ dconf update || :
%{_datadir}/installed-tests/ibus
%changelog
+* Thu Nov 24 2022 Takao Fujiwara <tfujiwar@redhat.com> - 1.5.27-6
+- Implement new process_key_event for ibus-x11
+
* Wed Nov 16 2022 Takao Fujiwara <tfujiwar@redhat.com> - 1.5.27-5
- Migrate license tag to SPDX
reply other threads:[~2026-05-31 2:08 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=178019328086.1.12971573730071995190.rpms-ibus-82f34afdef47@fedoraproject.org \
--to=tfujiwar@redhat.com \
--cc=git-commits@fedoraproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox