jobextra/libx11/MR236.patch

345 lines
9.0 KiB
Diff

From 024d229fdf88a7755577b01b46af6ef908d599e0 Mon Sep 17 00:00:00 2001
From: Takao Fujiwara <tfujiwar@redhat.com>
Date: Wed, 31 Jan 2024 20:26:40 +0900
Subject: [PATCH 1/2] 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.
Fixes: #198
---
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 44cc6884..834b9db4 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 (IS_FABRICATED(im)) {
+ if (_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 fe4d18ba..ac7f1195 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 dd1adf53..5192e8c1 100644
--- a/modules/im/ximcp/imDefLkup.c
+++ b/modules/im/ximcp/imDefLkup.c
@@ -341,6 +341,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,
@@ -355,7 +403,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;
}
@@ -704,10 +752,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;
@@ -719,6 +763,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 674da029..2a51e2ed 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 */
--
GitLab
From 041b5291f0956c5cda5054be2981c0d02b009a4c Mon Sep 17 00:00:00 2001
From: Takao Fujiwara <tfujiwar@redhat.com>
Date: Wed, 31 Jan 2024 20:27:57 +0900
Subject: [PATCH 2/2] 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.
Fixes: #198
---
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 5192e8c1..6ffe6f48 100644
--- a/modules/im/ximcp/imDefLkup.c
+++ b/modules/im/ximcp/imDefLkup.c
@@ -640,22 +640,47 @@ _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);
return;
}
+static void
+_XimUnregCommitInfo(
+ Xic ic)
+{
+ _XimUnregRealCommitInfo(ic, False);
+}
+
+static void
+_XimUnregFirstCommitInfo(
+ Xic ic)
+{
+ _XimUnregRealCommitInfo(ic, True);
+}
+
void
_XimFreeCommitInfo(
Xic ic)
@@ -665,6 +690,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,
@@ -1059,7 +1097,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;
}
@@ -1075,7 +1113,7 @@ _XimProtoMbLookupString(
else
*state = XLookupKeySym;
}
- _XimUnregCommitInfo(ic);
+ _XimUnregFirstCommitInfo(ic);
} else if (ev->type == KeyPress) {
ret = _XimLookupMBText(ic, ev, buffer, bytes, keysym, NULL);
@@ -1122,7 +1160,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;
}
@@ -1138,7 +1176,7 @@ _XimProtoWcLookupString(
else
*state = XLookupKeySym;
}
- _XimUnregCommitInfo(ic);
+ _XimUnregFirstCommitInfo(ic);
} else if (ev->type == KeyPress) {
ret = _XimLookupWCText(ic, ev, buffer, bytes, keysym, NULL);
@@ -1185,7 +1223,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;
}
@@ -1201,7 +1239,7 @@ _XimProtoUtf8LookupString(
else
*state = XLookupKeySym;
}
- _XimUnregCommitInfo(ic);
+ _XimUnregFirstCommitInfo(ic);
} else if (ev->type == KeyPress) {
ret = _XimLookupUTF8Text(ic, ev, buffer, bytes, keysym, NULL);
--
GitLab