344 lines
9 KiB
Diff
344 lines
9 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
|
|
|