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>
This commit is contained in:
Takao Fujiwara 2024-04-26 00:49:14 +09:00
parent 1181abd6ff
commit 5a14178c7c
4 changed files with 47 additions and 21 deletions

View file

@ -142,9 +142,9 @@ _XimProtoKeypressFilter(
{
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;
}
@ -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;
}

View file

@ -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;
}

View file

@ -344,14 +344,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;
}
@ -359,17 +359,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;
}
@ -377,10 +378,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;
}
@ -388,12 +390,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
@ -410,7 +432,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;
}
@ -811,7 +833,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.
*/

View file

@ -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 */