Backport fixes for XIM input sometimes jumbled

Resolves: https://issues.redhat.com/browse/RHEL-69791
This commit is contained in:
Olivier Fourdan 2024-12-04 15:32:53 +01:00
parent 8cd8488ac7
commit 1011d87cb7
8 changed files with 960 additions and 1 deletions

View File

@ -0,0 +1,200 @@
From a91e5a5e6fca25f23c7dd24c6694ab1b80b6030e Mon Sep 17 00:00:00 2001
From: Takao Fujiwara <tfujiwar@redhat.com>
Date: Fri, 12 Apr 2024 10:21:41 +0900
Subject: [PATCH libX11 1/7] ximcp: Unmark to fabricate key events with
XKeyEvent serial
_XimProtoKeypressFilter() and _XimProtoKeyreleaseFilter() can
receive XKeyEvent from both the typing on the keyboard and the
callback of XIM_FORWARD_EVENT.
If the filter functions unmark to fabricate XKeyEvent from the typing
on the keyboard during receiving XKeyEvent from the callback of
XIM_FORWARD_EVENT with typing keys very quickly likes an bar code
scanner (or evemu-play), XIM server cannot receive some key events and
it causes the key typing order to get scrambled.
Now XIM client saves the serial in XKeyEvent and the filter functions
unmark to fabricate XKeyEvent from the callback of XIM_FORWARD_EVENT
only.
This and 024d229f are same patches but the regression issues will be
fixed by the later patches.
Closes: #198
Fixes: 024d229f ("ximcp: Unmark to fabricate key events with XKeyEvent serial")
Part-of: <https://gitlab.freedesktop.org/xorg/lib/libx11/-/merge_requests/246>
(cherry picked from commit 13e9ac4d458069c81d795f6b4842814d30431b4b)
---
modules/im/ximcp/imDefFlt.c | 8 ++---
modules/im/ximcp/imDefIm.c | 1 +
modules/im/ximcp/imDefLkup.c | 58 ++++++++++++++++++++++++++++++++----
src/xlibi18n/XimintP.h | 17 +++++++++++
4 files changed, 75 insertions(+), 9 deletions(-)
diff --git a/modules/im/ximcp/imDefFlt.c b/modules/im/ximcp/imDefFlt.c
index f89d2cb0..a7948df8 100644
--- a/modules/im/ximcp/imDefFlt.c
+++ b/modules/im/ximcp/imDefFlt.c
@@ -142,9 +142,9 @@ _XimProtoKeypressFilter(
{
Xim im = (Xim)ic->core.im;
- if ((ev->keycode == 0) || IS_FABRICATED(im)) {
+ if ((ev->keycode == 0) || _XimIsFabricatedSerial(im, ev->serial)) {
_XimPendingFilter(ic);
- UNMARK_FABRICATED(im);
+ _XimUnfabricateSerial(im, ev->serial);
return NOTFILTERD;
}
@@ -203,9 +203,9 @@ _XimProtoKeyreleaseFilter(
{
Xim im = (Xim)ic->core.im;
- if (IS_FABRICATED(im)) {
+ if (_XimIsFabricatedSerial(im, ev->serial)) {
_XimPendingFilter(ic);
- UNMARK_FABRICATED(im);
+ _XimUnfabricateSerial(im, ev->serial);
return NOTFILTERD;
}
diff --git a/modules/im/ximcp/imDefIm.c b/modules/im/ximcp/imDefIm.c
index ccdf14c1..a231a0ac 100644
--- a/modules/im/ximcp/imDefIm.c
+++ b/modules/im/ximcp/imDefIm.c
@@ -430,6 +430,7 @@ _XimPreConnect(
return False;
im->private.proto.im_window = im_window;
+ im->private.proto.fabricated_serial = 0;
return True;
}
diff --git a/modules/im/ximcp/imDefLkup.c b/modules/im/ximcp/imDefLkup.c
index 18289a80..a6923d5b 100644
--- a/modules/im/ximcp/imDefLkup.c
+++ b/modules/im/ximcp/imDefLkup.c
@@ -351,6 +351,54 @@ _XimForwardEvent(
return _XimForwardEventCore(ic, ev, sync);
}
+Bool
+_XimFabricateSerial(
+ Xim im,
+ unsigned long serial)
+{
+ if (!serial)
+ return False;
+ if (serial == im->private.proto.fabricated_serial) {
+ fprintf(stderr, "%s,%d: The key event is already fabricated.\n", __FILE__, __LINE__);
+ return False;
+ }
+ if (im->private.proto.fabricated_serial)
+ fprintf(stderr, "%s,%d: Tried to fabricate a wrong key event.\n", __FILE__, __LINE__);
+
+ MARK_FABRICATED(im);
+ im->private.proto.fabricated_serial = serial;
+ return True;
+}
+
+Bool
+_XimUnfabricateSerial(
+ Xim im,
+ unsigned long serial)
+{
+ if (!serial)
+ return False;
+ if (!im->private.proto.fabricated_serial) {
+ fprintf(stderr, "%s,%d: The key event is already unfabricated.\n", __FILE__, __LINE__);
+ return False;
+ }
+ if (serial != im->private.proto.fabricated_serial)
+ fprintf(stderr, "%s,%d: Tried to unfabricate a wrong key event.\n", __FILE__, __LINE__);
+
+ im->private.proto.fabricated_serial = 0;
+ UNMARK_FABRICATED(im);
+ return True;
+}
+
+Bool
+_XimIsFabricatedSerial(
+ Xim im,
+ unsigned long serial)
+{
+ if (!serial)
+ return False;
+ return (serial == im->private.proto.fabricated_serial);
+}
+
static void
_XimProcEvent(
Display *d,
@@ -365,7 +413,7 @@ _XimProcEvent(
ev->xany.serial |= serial << 16;
ev->xany.send_event = False;
ev->xany.display = d;
- MARK_FABRICATED(ic->core.im);
+ _XimFabricateSerial((Xim)ic->core.im, ev->xany.serial);
return;
}
@@ -727,10 +775,6 @@ _XimCommitRecv(
(void)_XimRespSyncReply(ic, flag);
- if (ic->private.proto.registed_filter_event
- & (KEYPRESS_MASK | KEYRELEASE_MASK))
- MARK_FABRICATED(im);
-
bzero(&ev, sizeof(ev)); /* uninitialized : found when running kterm under valgrind */
ev.type = KeyPress;
@@ -742,6 +786,10 @@ _XimCommitRecv(
ev.time = 0L;
ev.serial = LastKnownRequestProcessed(im->core.display);
+
+ if (ic->private.proto.registed_filter_event
+ & (KEYPRESS_MASK | KEYRELEASE_MASK))
+ _XimFabricateSerial(im, ev.serial);
/* FIXME :
I wish there were COMMENTs (!) about the data passed around.
*/
diff --git a/src/xlibi18n/XimintP.h b/src/xlibi18n/XimintP.h
index 14a7e6d5..7f5b107a 100644
--- a/src/xlibi18n/XimintP.h
+++ b/src/xlibi18n/XimintP.h
@@ -149,6 +149,8 @@ typedef struct _XimProtoPrivateRec {
XimTransRegDispatcher register_dispatcher;
XimTransCallDispatcher call_dispatcher;
XPointer spec;
+
+ unsigned long fabricated_serial;
} XimProtoPrivateRec;
/*
@@ -307,4 +309,19 @@ typedef struct _XicProtoPrivateRec {
#define XIM_MAXIMNAMELEN 64
#define XIM_MAXLCNAMELEN 64
+Bool
+_XimFabricateSerial(
+ Xim im,
+ unsigned long serial);
+
+Bool
+_XimUnfabricateSerial(
+ Xim im,
+ unsigned long serial);
+
+Bool
+_XimIsFabricatedSerial(
+ Xim im,
+ unsigned long serial);
+
#endif /* _XIMINTP_H */
--
2.47.1

View File

@ -0,0 +1,158 @@
From a1037538b74e4016c3a1c2ebef9b1836811ed687 Mon Sep 17 00:00:00 2001
From: Takao Fujiwara <tfujiwar@redhat.com>
Date: Fri, 12 Apr 2024 10:21:43 +0900
Subject: [PATCH libX11 2/7] imDefLkup: Commit first info in XimCommitInfo
Xic.private.proto.commit_info can receive multiple XimCommitInfo
when typing keys very quickly like an bar code scanner (or evemu-play)
and the first info in XimCommitInfo should be committed to keep
the typing key order.
This and 041b5291 are same patches but the regression issues will be
fixed by the later patches.
Closes: #198
Fixes: 041b5291 ("imDefLkup: Commit first info in XimCommitInfo")
Part-of: <https://gitlab.freedesktop.org/xorg/lib/libx11/-/merge_requests/246>
(cherry picked from commit c7790072657f9fdbe8cda031776617088c5f11db)
---
modules/im/ximcp/imDefLkup.c | 60 +++++++++++++++++++++++++++++-------
1 file changed, 49 insertions(+), 11 deletions(-)
diff --git a/modules/im/ximcp/imDefLkup.c b/modules/im/ximcp/imDefLkup.c
index a6923d5b..31205e6b 100644
--- a/modules/im/ximcp/imDefLkup.c
+++ b/modules/im/ximcp/imDefLkup.c
@@ -650,18 +650,29 @@ _XimRegCommitInfo(
}
static void
-_XimUnregCommitInfo(
- Xic ic)
+_XimUnregRealCommitInfo(
+ Xic ic,
+ Bool reverse)
{
XimCommitInfo info;
+ XimCommitInfo prev_info = NULL;
- if (!(info = ic->private.proto.commit_info))
+ info = ic->private.proto.commit_info;
+ while (reverse && info) {
+ if (!info->next)
+ break;
+ prev_info = info;
+ info = info->next;
+ }
+ if (!info)
return;
-
Xfree(info->string);
Xfree(info->keysym);
- ic->private.proto.commit_info = info->next;
+ if (prev_info)
+ prev_info->next = info->next;
+ else
+ ic->private.proto.commit_info = info->next;
Xfree(info);
/*
@@ -679,6 +690,20 @@ _XimUnregCommitInfo(
return;
}
+static void
+_XimUnregCommitInfo(
+ Xic ic)
+{
+ _XimUnregRealCommitInfo(ic, False);
+}
+
+static void
+_XimUnregFirstCommitInfo(
+ Xic ic)
+{
+ _XimUnregRealCommitInfo(ic, True);
+}
+
void
_XimFreeCommitInfo(
Xic ic)
@@ -688,6 +713,19 @@ _XimFreeCommitInfo(
return;
}
+static XimCommitInfo
+_XimFirstCommitInfo(
+ Xic ic)
+{
+ XimCommitInfo info = ic->private.proto.commit_info;
+ while (info) {
+ if (!info->next)
+ break;
+ info = info->next;
+ }
+ return info;
+}
+
static Bool
_XimProcKeySym(
Xic ic,
@@ -1082,7 +1120,7 @@ _XimProtoMbLookupString(
state = &tmp_state;
if ((ev->type == KeyPress) && (ev->keycode == 0)) { /* Filter function */
- if (!(info = ic->private.proto.commit_info)) {
+ if (!(info = _XimFirstCommitInfo(ic))) {
*state = XLookupNone;
return 0;
}
@@ -1098,7 +1136,7 @@ _XimProtoMbLookupString(
else
*state = XLookupKeySym;
}
- _XimUnregCommitInfo(ic);
+ _XimUnregFirstCommitInfo(ic);
} else if (ev->type == KeyPress) {
ret = _XimLookupMBText(ic, ev, buffer, bytes, keysym, NULL);
@@ -1145,7 +1183,7 @@ _XimProtoWcLookupString(
state = &tmp_state;
if (ev->type == KeyPress && ev->keycode == 0) { /* Filter function */
- if (!(info = ic->private.proto.commit_info)) {
+ if (!(info = _XimFirstCommitInfo(ic))) {
*state = XLookupNone;
return 0;
}
@@ -1161,7 +1199,7 @@ _XimProtoWcLookupString(
else
*state = XLookupKeySym;
}
- _XimUnregCommitInfo(ic);
+ _XimUnregFirstCommitInfo(ic);
} else if (ev->type == KeyPress) {
ret = _XimLookupWCText(ic, ev, buffer, bytes, keysym, NULL);
@@ -1208,7 +1246,7 @@ _XimProtoUtf8LookupString(
state = &tmp_state;
if (ev->type == KeyPress && ev->keycode == 0) { /* Filter function */
- if (!(info = ic->private.proto.commit_info)) {
+ if (!(info = _XimFirstCommitInfo(ic))) {
*state = XLookupNone;
return 0;
}
@@ -1224,7 +1262,7 @@ _XimProtoUtf8LookupString(
else
*state = XLookupKeySym;
}
- _XimUnregCommitInfo(ic);
+ _XimUnregFirstCommitInfo(ic);
} else if (ev->type == KeyPress) {
ret = _XimLookupUTF8Text(ic, ev, buffer, bytes, keysym, NULL);
--
2.47.1

View File

@ -0,0 +1,65 @@
From ed53956985d37c57fcd3587c642ee7ebf653d1af Mon Sep 17 00:00:00 2001
From: Takao Fujiwara <tfujiwar@redhat.com>
Date: Fri, 12 Apr 2024 10:50:33 +0900
Subject: [PATCH libX11 3/7] imDefLkup: Mark and unmark fabricated with serial
0
GTK2 applications with GTK_IM_MODULE=xim sets the serial number 0
to the XKeyEvent and the previous _XimFabricateSerial() logic did
not work for the applications.
Now the API marks to fabricate with the serial 0.
Closes: #205
Fixes: 024d229f ("ximcp: Unmark to fabricate key events with XKeyEvent serial")
Part-of: <https://gitlab.freedesktop.org/xorg/lib/libx11/-/merge_requests/246>
(cherry picked from commit 1181abd6ffede3ac5663a3a3d4ee66aef1fa553b)
---
modules/im/ximcp/imDefLkup.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/modules/im/ximcp/imDefLkup.c b/modules/im/ximcp/imDefLkup.c
index 31205e6b..53cf1f87 100644
--- a/modules/im/ximcp/imDefLkup.c
+++ b/modules/im/ximcp/imDefLkup.c
@@ -356,8 +356,11 @@ _XimFabricateSerial(
Xim im,
unsigned long serial)
{
- if (!serial)
- return False;
+ /* GTK2 XIM module sets serial=0. */
+ if (!serial) {
+ MARK_FABRICATED(im);
+ return True;
+ }
if (serial == im->private.proto.fabricated_serial) {
fprintf(stderr, "%s,%d: The key event is already fabricated.\n", __FILE__, __LINE__);
return False;
@@ -375,8 +378,11 @@ _XimUnfabricateSerial(
Xim im,
unsigned long serial)
{
- if (!serial)
- return False;
+ /* GTK2 XIM module sets serial=0. */
+ if (!serial) {
+ UNMARK_FABRICATED(im);
+ return True;
+ }
if (!im->private.proto.fabricated_serial) {
fprintf(stderr, "%s,%d: The key event is already unfabricated.\n", __FILE__, __LINE__);
return False;
@@ -394,8 +400,9 @@ _XimIsFabricatedSerial(
Xim im,
unsigned long serial)
{
+ /* GTK2 XIM module sets serial=0. */
if (!serial)
- return False;
+ return IS_FABRICATED(im);
return (serial == im->private.proto.fabricated_serial);
}
--
2.47.1

View File

@ -0,0 +1,216 @@
From 24f2fdba4e5162ebcb011ce41104fb195b163169 Mon Sep 17 00:00:00 2001
From: Takao Fujiwara <tfujiwar@redhat.com>
Date: Fri, 26 Apr 2024 00:49:14 +0900
Subject: [PATCH libX11 4/7] ximcp: Add fabricated_time in XimProtoPrivate for
timeout
When users type keys quickly, some applications using Steam or Java
do not call XNextEvent() for a key event but _XimFilterKeypress()
and _XimFilterKeyrelease() expect to receive the key events
forwarded by input methods.
Now fabricated_time Time value is added to XimProtoPrivate to check
the timeout value.
Closes: #205
Fixes: 024d229f ("ximcp: Unmark to fabricate key events with XKeyEvent serial")
Part-of: <https://gitlab.freedesktop.org/xorg/lib/libx11/-/merge_requests/246>
(cherry picked from commit 5a14178c7cc408f425fe298aeade3dee749b1ca1)
---
modules/im/ximcp/imDefFlt.c | 8 +++---
modules/im/ximcp/imDefIm.c | 2 ++
modules/im/ximcp/imDefLkup.c | 48 ++++++++++++++++++++++++++----------
src/xlibi18n/XimintP.h | 10 +++++---
4 files changed, 47 insertions(+), 21 deletions(-)
diff --git a/modules/im/ximcp/imDefFlt.c b/modules/im/ximcp/imDefFlt.c
index a7948df8..ad8a272b 100644
--- a/modules/im/ximcp/imDefFlt.c
+++ b/modules/im/ximcp/imDefFlt.c
@@ -142,9 +142,9 @@ _XimProtoKeypressFilter(
{
Xim im = (Xim)ic->core.im;
- if ((ev->keycode == 0) || _XimIsFabricatedSerial(im, ev->serial)) {
+ if ((ev->keycode == 0) || _XimIsFabricatedSerial(im, ev)) {
_XimPendingFilter(ic);
- _XimUnfabricateSerial(im, ev->serial);
+ _XimUnfabricateSerial(im, ev);
return NOTFILTERD;
}
@@ -203,9 +203,9 @@ _XimProtoKeyreleaseFilter(
{
Xim im = (Xim)ic->core.im;
- if (_XimIsFabricatedSerial(im, ev->serial)) {
+ if (_XimIsFabricatedSerial(im, ev)) {
_XimPendingFilter(ic);
- _XimUnfabricateSerial(im, ev->serial);
+ _XimUnfabricateSerial(im, ev);
return NOTFILTERD;
}
diff --git a/modules/im/ximcp/imDefIm.c b/modules/im/ximcp/imDefIm.c
index a231a0ac..7eba0b34 100644
--- a/modules/im/ximcp/imDefIm.c
+++ b/modules/im/ximcp/imDefIm.c
@@ -431,6 +431,8 @@ _XimPreConnect(
im->private.proto.im_window = im_window;
im->private.proto.fabricated_serial = 0;
+ im->private.proto.fabricated_time = 0;
+ im->private.proto.enable_fabricated_order = True;
return True;
}
diff --git a/modules/im/ximcp/imDefLkup.c b/modules/im/ximcp/imDefLkup.c
index 53cf1f87..6b2d27dc 100644
--- a/modules/im/ximcp/imDefLkup.c
+++ b/modules/im/ximcp/imDefLkup.c
@@ -354,14 +354,14 @@ _XimForwardEvent(
Bool
_XimFabricateSerial(
Xim im,
- unsigned long serial)
+ XKeyEvent *event)
{
/* GTK2 XIM module sets serial=0. */
- if (!serial) {
+ if (!event->serial || !im->private.proto.enable_fabricated_order) {
MARK_FABRICATED(im);
return True;
}
- if (serial == im->private.proto.fabricated_serial) {
+ if (event->serial == im->private.proto.fabricated_serial) {
fprintf(stderr, "%s,%d: The key event is already fabricated.\n", __FILE__, __LINE__);
return False;
}
@@ -369,17 +369,18 @@ _XimFabricateSerial(
fprintf(stderr, "%s,%d: Tried to fabricate a wrong key event.\n", __FILE__, __LINE__);
MARK_FABRICATED(im);
- im->private.proto.fabricated_serial = serial;
+ im->private.proto.fabricated_serial = event->serial;
+ im->private.proto.fabricated_time = event->time;
return True;
}
Bool
_XimUnfabricateSerial(
Xim im,
- unsigned long serial)
+ XKeyEvent *event)
{
/* GTK2 XIM module sets serial=0. */
- if (!serial) {
+ if (!event->serial || !im->private.proto.enable_fabricated_order) {
UNMARK_FABRICATED(im);
return True;
}
@@ -387,10 +388,11 @@ _XimUnfabricateSerial(
fprintf(stderr, "%s,%d: The key event is already unfabricated.\n", __FILE__, __LINE__);
return False;
}
- if (serial != im->private.proto.fabricated_serial)
+ if (event->serial != im->private.proto.fabricated_serial)
fprintf(stderr, "%s,%d: Tried to unfabricate a wrong key event.\n", __FILE__, __LINE__);
im->private.proto.fabricated_serial = 0;
+ im->private.proto.fabricated_time = 0;
UNMARK_FABRICATED(im);
return True;
}
@@ -398,12 +400,32 @@ _XimUnfabricateSerial(
Bool
_XimIsFabricatedSerial(
Xim im,
- unsigned long serial)
+ XKeyEvent *event)
{
/* GTK2 XIM module sets serial=0. */
- if (!serial)
- return IS_FABRICATED(im);
- return (serial == im->private.proto.fabricated_serial);
+ if (!event->serial || !im->private.proto.enable_fabricated_order)
+ return IS_FABRICATED(im) ? True : False;
+ if (event->serial == im->private.proto.fabricated_serial)
+ return True;
+ if (!im->private.proto.fabricated_serial)
+ return False;
+ /* Rotate time */
+ if (event->time < im->private.proto.fabricated_time) {
+ if (event->time >= 1000)
+ im->private.proto.fabricated_time = 0;
+ } else if (event->time - im->private.proto.fabricated_time > 1000) {
+ fprintf(stderr,
+ "%s,%d: The application disposed a key event with %ld serial.\n",
+ __FILE__, __LINE__,
+ im->private.proto.fabricated_serial);
+ im->private.proto.enable_fabricated_order = False;
+ if (IS_FABRICATED(im)) {
+ if (event->serial)
+ im->private.proto.fabricated_serial = event->serial;
+ return True;
+ }
+ }
+ return False;
}
static void
@@ -420,7 +442,7 @@ _XimProcEvent(
ev->xany.serial |= serial << 16;
ev->xany.send_event = False;
ev->xany.display = d;
- _XimFabricateSerial((Xim)ic->core.im, ev->xany.serial);
+ _XimFabricateSerial((Xim)ic->core.im, &ev->xkey);
return;
}
@@ -834,7 +856,7 @@ _XimCommitRecv(
if (ic->private.proto.registed_filter_event
& (KEYPRESS_MASK | KEYRELEASE_MASK))
- _XimFabricateSerial(im, ev.serial);
+ _XimFabricateSerial(im, &ev);
/* FIXME :
I wish there were COMMENTs (!) about the data passed around.
*/
diff --git a/src/xlibi18n/XimintP.h b/src/xlibi18n/XimintP.h
index 7f5b107a..715800c7 100644
--- a/src/xlibi18n/XimintP.h
+++ b/src/xlibi18n/XimintP.h
@@ -150,7 +150,9 @@ typedef struct _XimProtoPrivateRec {
XimTransCallDispatcher call_dispatcher;
XPointer spec;
- unsigned long fabricated_serial;
+ unsigned long fabricated_serial;
+ Time fabricated_time;
+ Bool enable_fabricated_order;
} XimProtoPrivateRec;
/*
@@ -312,16 +314,16 @@ typedef struct _XicProtoPrivateRec {
Bool
_XimFabricateSerial(
Xim im,
- unsigned long serial);
+ XKeyEvent *event);
Bool
_XimUnfabricateSerial(
Xim im,
- unsigned long serial);
+ XKeyEvent *event);
Bool
_XimIsFabricatedSerial(
Xim im,
- unsigned long serial);
+ XKeyEvent *event);
#endif /* _XIMINTP_H */
--
2.47.1

View File

@ -0,0 +1,168 @@
From b3157722535db692d54b8fe7d26d07f94d49daf3 Mon Sep 17 00:00:00 2001
From: Takao Fujiwara <tfujiwar@redhat.com>
Date: Fri, 26 Apr 2024 01:29:26 +0900
Subject: [PATCH libX11 5/7] Accept anon windows in XFilterEvent to update XIM
state
When input focuses are switched quickly with shortcut keys in a Java
window, the focus is sometimes lost and the Window=0 is assigned in
XFilterEvent() but the XKeyEvent was forwarded by a XIM serer(IBus)
with XIM_FORWARD_EVENT -> XNextEvent() -> XFilterEvent() and the event
needs to be forwarded to the XIM XKeyEvent press and release filters
to update the XIM state with Window=0 likes _XimPendingFilter() and
_XimUnfabricateSerial().
Closes: #205, #206
Fixes: 024d229f ("ximcp: Unmark to fabricate key events with XKeyEvent serial")
Part-of: <https://gitlab.freedesktop.org/xorg/lib/libx11/-/merge_requests/246>
(cherry picked from commit 5a1e62d77b65ba148b1c6d1d22a81dc2b07e7d9e)
---
modules/im/ximcp/imDefFlt.c | 34 ++++++++++++++++++++++++++++++----
src/FilterEv.c | 25 +++++++++++++++++++++++++
2 files changed, 55 insertions(+), 4 deletions(-)
diff --git a/modules/im/ximcp/imDefFlt.c b/modules/im/ximcp/imDefFlt.c
index ad8a272b..76d63e88 100644
--- a/modules/im/ximcp/imDefFlt.c
+++ b/modules/im/ximcp/imDefFlt.c
@@ -138,7 +138,8 @@ _XimPendingFilter(
static Bool
_XimProtoKeypressFilter(
Xic ic,
- XKeyEvent *ev)
+ XKeyEvent *ev,
+ Window w)
{
Xim im = (Xim)ic->core.im;
@@ -147,6 +148,9 @@ _XimProtoKeypressFilter(
_XimUnfabricateSerial(im, ev);
return NOTFILTERD;
}
+ /* w=0 is used for _XimIsFabricatedSerial() only */
+ if (!w)
+ return NOTFILTERD;
if (IS_NEGLECT_EVENT(ic, KeyPressMask))
return FILTERD;
@@ -193,13 +197,14 @@ _XimFilterKeypress(
XEvent *ev,
XPointer client_data)
{
- return _XimProtoKeypressFilter((Xic)client_data, (XKeyEvent *)ev );
+ return _XimProtoKeypressFilter((Xic)client_data, (XKeyEvent *)ev, w);
}
static Bool
_XimProtoKeyreleaseFilter(
Xic ic,
- XKeyEvent *ev)
+ XKeyEvent *ev,
+ Window w)
{
Xim im = (Xim)ic->core.im;
@@ -208,6 +213,9 @@ _XimProtoKeyreleaseFilter(
_XimUnfabricateSerial(im, ev);
return NOTFILTERD;
}
+ /* w=0 is used for _XimIsFabricatedSerial() only */
+ if (!w)
+ return NOTFILTERD;
if (IS_NEGLECT_EVENT(ic, KeyReleaseMask))
return FILTERD;
@@ -254,7 +262,7 @@ _XimFilterKeyrelease(
XEvent *ev,
XPointer client_data)
{
- return _XimProtoKeyreleaseFilter((Xic)client_data, (XKeyEvent *)ev);
+ return _XimProtoKeyreleaseFilter((Xic)client_data, (XKeyEvent *)ev, w);
}
static void
@@ -263,6 +271,11 @@ _XimRegisterKeyPressFilter(
{
if (ic->core.focus_window) {
if (!(ic->private.proto.registed_filter_event & KEYPRESS_MASK)) {
+ _XRegisterFilterByType (ic->core.im->core.display,
+ 0,
+ KeyPress, KeyPress,
+ _XimFilterKeypress,
+ (XPointer)ic);
_XRegisterFilterByType (ic->core.im->core.display,
ic->core.focus_window,
KeyPress, KeyPress,
@@ -280,6 +293,11 @@ _XimRegisterKeyReleaseFilter(
{
if (ic->core.focus_window) {
if (!(ic->private.proto.registed_filter_event & KEYRELEASE_MASK)) {
+ _XRegisterFilterByType (ic->core.im->core.display,
+ 0,
+ KeyRelease, KeyRelease,
+ _XimFilterKeyrelease,
+ (XPointer)ic);
_XRegisterFilterByType (ic->core.im->core.display,
ic->core.focus_window,
KeyRelease, KeyRelease,
@@ -301,6 +319,10 @@ _XimUnregisterKeyPressFilter(
ic->core.focus_window,
_XimFilterKeypress,
(XPointer)ic);
+ _XUnregisterFilter (ic->core.im->core.display,
+ 0,
+ _XimFilterKeypress,
+ (XPointer)ic);
ic->private.proto.registed_filter_event &= ~KEYPRESS_MASK;
}
}
@@ -317,6 +339,10 @@ _XimUnregisterKeyReleaseFilter(
ic->core.focus_window,
_XimFilterKeyrelease,
(XPointer)ic);
+ _XUnregisterFilter (ic->core.im->core.display,
+ 0,
+ _XimFilterKeyrelease,
+ (XPointer)ic);
ic->private.proto.registed_filter_event &= ~KEYRELEASE_MASK;
}
}
diff --git a/src/FilterEv.c b/src/FilterEv.c
index 0a48e548..07845bcc 100644
--- a/src/FilterEv.c
+++ b/src/FilterEv.c
@@ -100,6 +100,31 @@ XFilterEvent(
}
}
}
+ for (p = ev->xany.display->im_filters; p != NULL; p = p->next) {
+ /* Java sometimes calls XFilterEvent() with window=0 and ev come from
+ * XNextEvent() when users type some keys quickly and switch multiple
+ * input focuses in a Java window with the keys.
+ * But XKeyEvent filters need to receive the event with window=0 for
+ * _XimPendingFilter() and _XimUnfabricateSerial() to clear the
+ * fowarded XKeyEvent with XIM_FORWARD_EVENT.
+ *
+ * The case of p->window == 0 is checkekd after all cases of p->window
+ * != 0 are checked because all input contexts share
+ * Display->im_filters but each input context has
+ * Xic->private.proto.registed_filter_event for the filters
+ * and same p->filter could be registerd to Display->im_filters twice
+ * with different p->window.
+ */
+ if (p->window == 0 && window == 0) {
+ if ((mask & p->event_mask) ||
+ (ev->type >= p->start_type && ev->type <= p->end_type)) {
+ UnlockDisplay(ev->xany.display);
+ ret = (*(p->filter))(ev->xany.display, p->window, ev,
+ p->client_data);
+ return(ret);
+ }
+ }
+ }
UnlockDisplay(ev->xany.display);
#endif
return(False);
--
2.47.1

View File

@ -0,0 +1,82 @@
From 546a51348322d83a57fd9b8c1e42b44fbe970368 Mon Sep 17 00:00:00 2001
From: Takao Fujiwara <tfujiwar@redhat.com>
Date: Fri, 26 Apr 2024 01:29:34 +0900
Subject: [PATCH libX11 6/7] ximcp: Unmark fabricated with serial 0 and Xic
commit_info
GTK2 XIM resets the XKeyEvent serial to 0 even if _XimCommitRecv()
sets the serial so now checks if the events are sent with
Xic->private.proto.commit_info.
Closes: !246
Part-of: <https://gitlab.freedesktop.org/xorg/lib/libx11/-/merge_requests/246>
(cherry picked from commit 898746f9b1fb384d6d24ed827c836ec8a0b3da3b)
---
modules/im/ximcp/imDefFlt.c | 4 ++--
modules/im/ximcp/imDefLkup.c | 12 +++++++++++-
src/xlibi18n/XimintP.h | 1 +
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/modules/im/ximcp/imDefFlt.c b/modules/im/ximcp/imDefFlt.c
index 76d63e88..3dfbf8cd 100644
--- a/modules/im/ximcp/imDefFlt.c
+++ b/modules/im/ximcp/imDefFlt.c
@@ -145,7 +145,7 @@ _XimProtoKeypressFilter(
if ((ev->keycode == 0) || _XimIsFabricatedSerial(im, ev)) {
_XimPendingFilter(ic);
- _XimUnfabricateSerial(im, ev);
+ _XimUnfabricateSerial(im, ic, ev);
return NOTFILTERD;
}
/* w=0 is used for _XimIsFabricatedSerial() only */
@@ -210,7 +210,7 @@ _XimProtoKeyreleaseFilter(
if (_XimIsFabricatedSerial(im, ev)) {
_XimPendingFilter(ic);
- _XimUnfabricateSerial(im, ev);
+ _XimUnfabricateSerial(im, ic, ev);
return NOTFILTERD;
}
/* w=0 is used for _XimIsFabricatedSerial() only */
diff --git a/modules/im/ximcp/imDefLkup.c b/modules/im/ximcp/imDefLkup.c
index 6b2d27dc..326339fe 100644
--- a/modules/im/ximcp/imDefLkup.c
+++ b/modules/im/ximcp/imDefLkup.c
@@ -377,10 +377,20 @@ _XimFabricateSerial(
Bool
_XimUnfabricateSerial(
Xim im,
+ Xic ic,
XKeyEvent *event)
{
+ if (!im->private.proto.enable_fabricated_order) {
+ UNMARK_FABRICATED(im);
+ return True;
+ }
/* GTK2 XIM module sets serial=0. */
- if (!event->serial || !im->private.proto.enable_fabricated_order) {
+ if (!event->serial) {
+ /* _XimCommitRecv() sets event->serial and call _XimFabricateSerial()
+ * but GTK2 XIM always reset event->serial=0 with XFilterEvent().
+ */
+ if (ic && ic->private.proto.commit_info)
+ im->private.proto.fabricated_serial = 0;
UNMARK_FABRICATED(im);
return True;
}
diff --git a/src/xlibi18n/XimintP.h b/src/xlibi18n/XimintP.h
index 715800c7..fe52231e 100644
--- a/src/xlibi18n/XimintP.h
+++ b/src/xlibi18n/XimintP.h
@@ -319,6 +319,7 @@ _XimFabricateSerial(
Bool
_XimUnfabricateSerial(
Xim im,
+ Xic ic,
XKeyEvent *event);
Bool
--
2.47.1

View File

@ -0,0 +1,58 @@
From 9abd669f8826909a715e9b19531fd687800ce44c Mon Sep 17 00:00:00 2001
From: Takao Fujiwara <tfujiwar@redhat.com>
Date: Fri, 26 Apr 2024 01:29:39 +0900
Subject: [PATCH libX11 7/7] imDefIm: Add LIBX11_ENABLE_FABRICATED_ORDER env
If an XIM application does not return the XKeyEvent from XNextEvent()
to XFilterEvent(), a timeout is reached and the behavior is fallen
back to the previous one with a warning messsage and we can ask
the application to send the XKeyEvent to XFilterEvent() but also
libX11 provides LIBX11_ENABLE_FABRICATED_ORDER environment variable.
If the application runs with LIBX11_ENABLE_FABRICATED_ORDER=0, the
previous behavior is available until the application is fixed.
Closes: !246
Part-of: <https://gitlab.freedesktop.org/xorg/lib/libx11/-/merge_requests/246>
(cherry picked from commit 90b8fc65da1e773b0091a50be46b23609591e8b7)
---
modules/im/ximcp/imDefIm.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/modules/im/ximcp/imDefIm.c b/modules/im/ximcp/imDefIm.c
index 7eba0b34..f42aa92c 100644
--- a/modules/im/ximcp/imDefIm.c
+++ b/modules/im/ximcp/imDefIm.c
@@ -63,6 +63,8 @@ PERFORMANCE OF THIS SOFTWARE.
#include "Ximint.h"
#include <limits.h>
+#include <stdlib.h>
+#include <strings.h>
int
_XimCheckDataSize(
@@ -400,6 +402,7 @@ _XimPreConnect(
Atom *atoms;
Window im_window = 0;
register int i;
+ const char *env_enable_fabricated_order;
if((imserver = XInternAtom(display, XIM_SERVERS, True)) == (Atom)None)
return False;
@@ -433,6 +436,13 @@ _XimPreConnect(
im->private.proto.fabricated_serial = 0;
im->private.proto.fabricated_time = 0;
im->private.proto.enable_fabricated_order = True;
+ env_enable_fabricated_order = getenv("LIBX11_ENABLE_FABRICATED_ORDER");
+ if (env_enable_fabricated_order && *env_enable_fabricated_order) {
+ if (!strncasecmp(env_enable_fabricated_order, "0", 2) ||
+ !strncasecmp(env_enable_fabricated_order, "false", 6)) {
+ im->private.proto.enable_fabricated_order = False;
+ }
+ }
return True;
}
--
2.47.1

View File

@ -5,7 +5,7 @@
Summary: Core X11 protocol client library
Name: libX11
Version: 1.7.0
Release: 10%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist}
Release: 11%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist}
License: MIT
URL: http://www.x.org
@ -36,6 +36,15 @@ Patch9: 0001-CVE-2023-43787-Integer-overflow-in-XCreateImage-lead.patch
# https://issues.redhat.com/browse/RHEL-58298
Patch10: 0001-imDefLkup-verify-that-a-pointer-isn-t-NULL-before-us.patch
# https://issues.redhat.com/browse/RHEL-69791
Patch11: 0001-ximcp-Unmark-to-fabricate-key-events-with-XKeyEvent-.patch
Patch12: 0002-imDefLkup-Commit-first-info-in-XimCommitInfo.patch
Patch13: 0003-imDefLkup-Mark-and-unmark-fabricated-with-serial-0.patch
Patch14: 0004-ximcp-Add-fabricated_time-in-XimProtoPrivate-for-tim.patch
Patch15: 0005-Accept-anon-windows-in-XFilterEvent-to-update-XIM-st.patch
Patch16: 0006-ximcp-Unmark-fabricated-with-serial-0-and-Xic-commit.patch
Patch17: 0007-imDefIm-Add-LIBX11_ENABLE_FABRICATED_ORDER-env.patch
BuildRequires: make
BuildRequires: xorg-x11-util-macros >= 1.11
BuildRequires: pkgconfig(xproto) >= 7.0.15
@ -138,6 +147,9 @@ make %{?_smp_mflags} check
%{_mandir}/man5/*.5*
%changelog
* Fri Dec 13 2024 Olivier Fourdan <ofourdan@redhat.com> - 1.7.0-11
- Backport fixes for XIM input sometimes jumbled (RHEL-69791)
* Fri Sep 13 2024 José Expósito <jexposit@redhat.com> - 1.7.0-10
- Backport NULL check to avoid a crash
Resolves: https://issues.redhat.com/browse/RHEL-58298