libX11/0001-ximcp-Unmark-to-fabricate-key-events-with-XKeyEvent-.patch

201 lines
5.7 KiB
Diff

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