mirror of
https://gitlab.freedesktop.org/xorg/lib/libx11.git
synced 2025-12-25 06:00:05 +01:00
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 and024d229fare 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>
This commit is contained in:
parent
a465588218
commit
13e9ac4d45
4 changed files with 75 additions and 9 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -430,6 +430,7 @@ _XimPreConnect(
|
|||
return False;
|
||||
|
||||
im->private.proto.im_window = im_window;
|
||||
im->private.proto.fabricated_serial = 0;
|
||||
return True;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue