File ibus-sync-ibus_input_context_process_key_event_X11.patch of Package ibus

From 7502abbe7eb4289d0d727e53cdfac572baf405d5 Mon Sep 17 00:00:00 2001
From: fujiwarat <takao.fujiwara1@gmail.com>
Date: Wed, 12 Jul 2023 07:52:21 +0900
Subject: [PATCH] client/x11: Fix sync ibus_input_context_process_key_event()

Fix the synchronous "ProcessKeyEvent" D-Bus method in ibus-x11 too.

Fixes: https://github.com/ibus/ibus/commit/38f09c6

BUG=https://github.com/ibus/ibus/issues/2486
---

--- a/client/x11/main.c
+++ b/client/x11/main.c
@@ -126,7 +126,7 @@
 
 static IBusBus *_bus = NULL;
 
-static char _use_sync_mode = 2;
+static char _use_sync_mode = 1;
 
 static void
 _xim_preedit_start (XIMS xims, const X11IC *x11ic)
@@ -380,9 +380,9 @@
 
     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);
+    if (_use_sync_mode == 1)
+        ibus_input_context_set_post_process_key_event (x11ic->context, TRUE);
 
     g_hash_table_insert (_x11_ic_table,
                          GINT_TO_POINTER (x11ic->icid), (gpointer)x11ic);
@@ -584,18 +584,126 @@
 }
 
 static int
+_process_key_event_sync (X11IC                *x11ic,
+                         IMForwardEventStruct *call_data,
+                         GdkEventKey          *event)
+{
+    gboolean retval;
+
+    g_assert (x11ic);
+    g_assert (call_data);
+    g_assert (event);
+    retval = ibus_input_context_process_key_event (
+            x11ic->context,
+            event->keyval,
+            event->hardware_keycode - 8,
+            event->state);
+    ibus_input_context_post_process_key_event (x11ic->context);
+    _xim_forward_key_event_done (x11ic, &call_data->event, retval);
+    return 1;
+}
+
+static int
+_process_key_event_async (X11IC                *x11ic,
+                          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);
@@ -611,99 +719,15 @@
     }
 
     switch (_use_sync_mode) {
-    case 1: {
-        retval = ibus_input_context_process_key_event (
-                                      x11ic->context,
-                                      event.keyval,
-                                      event.hardware_keycode - 8,
-                                      event.state);
-        _xim_forward_key_event_done (x11ic, &call_data->event, retval);
-        retval = 1;
-        break;
-    }
-    case 2: {
-        GSource *source = g_timeout_source_new (1);
-        ProcessKeyEventReplyData *data = NULL;
-
-        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 {
-            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 = *((XEvent*)xevent);
-            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);
-            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;
-            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, retval);
-        retval = 1;
-        break;
-    }
-    default: {
-        ProcessKeyEventReplyData *data;
-
-        if (!(data = g_slice_new0 (ProcessKeyEventReplyData))) {
-            g_warning ("Cannot allocate async data");
-            _xim_forward_key_event_done (x11ic, &call_data->event, 0);
-            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);
+    case 2:
+        return _process_key_event_hybrid_async (x11ic, call_data, &event);
+    default:
+        return _process_key_event_async (x11ic, call_data, &event);
     }
-    return retval;
+    g_assert_not_reached ();
+    return 0;
 }
 
 
@@ -1189,7 +1213,7 @@
                         G_CALLBACK (_bus_disconnected_cb), NULL);
 
     /* https://github.com/ibus/ibus/issues/1713 */
-    _use_sync_mode = _get_char_env ("IBUS_ENABLE_SYNC_MODE", 2);
+    _use_sync_mode = _get_char_env ("IBUS_ENABLE_SYNC_MODE", 1);
 }
 
 static void
openSUSE Build Service is sponsored by