Implement new process_key_event for ibus-x11
This commit is contained in:
parent
c0c536452c
commit
82f34afdef
432
ibus-HEAD.patch
432
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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user