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