From 606c0fc03e05d8260aceec188fb1d9074527de0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 30 Jun 2020 20:57:24 +0200 Subject: [PATCH] X11: Fix detection of key events duplicated by XIM Background: The IM will filter out key events, instead sending exact duplicate events that are not filtered. It does not send these for every event, however, so the duplicate events cannot be relied on for key input. Instead we need to identify and discard them. Since they are identical, they have the same timestamp as the originals. The previous duplicate event detection would consume unrelated key events if the keys were pressed simultaneously, as it only tracked a single timestamp. This fixes that issue for any combination of keys, at the expense of a 1 KB array per GLFW window. This fix is a stopgap until explicit IME support is done. Based on #1472 by @LucaRood. Fixes #1112. Fixes #1415. Fixes #1616. Fixes #1663. Closes #1472. (cherry picked from commit 9a3664b4a992a5a9b669179098542b0f882dece7) --- README.md | 4 ++++ src/x11_platform.h | 5 +++-- src/x11_window.c | 16 ++++++++++------ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 9f82fce2..3a269d40 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,8 @@ information on what to include when reporting a bug. non-printable keys (#1598) - [X11] Bugfix: Function keys were mapped to `GLFW_KEY_UNKNOWN` for some layout combinaitons (#1598) + - [X11] Bugfix: Keys pressed simultaneously with others were not always + reported (#1112,#1415,#1472,#1616) - [Wayland] Bugfix: Repeated keys could be reported with `NULL` window (#1704) @@ -295,8 +297,10 @@ skills. - Eddie Ringle - Max Risuhin - Jorge Rodriguez + - Luca Rood - Ed Ropple - Aleksey Rybalkin + - Mikko Rytkönen - Riku Salminen - Brandon Schaefer - Sebastian Schuberth diff --git a/src/x11_platform.h b/src/x11_platform.h index 7377b2c0..4873bd74 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -199,8 +199,9 @@ typedef struct _GLFWwindowX11 // The last position the cursor was warped to by GLFW int warpCursorPosX, warpCursorPosY; - // The time of the last KeyPress event - Time lastKeyTime; + // The time of the last KeyPress event per keycode, for discarding + // duplicate key events generated for some keys by ibus + Time keyPressTimes[256]; } _GLFWwindowX11; diff --git a/src/x11_window.c b/src/x11_window.c index 37c34fae..9df28973 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -1275,16 +1275,20 @@ static void processEvent(XEvent *event) if (window->x11.ic) { - // HACK: Ignore duplicate key press events generated by ibus - // These have the same timestamp as the original event - // Corresponding release events are filtered out - // implicitly by the GLFW key repeat logic - if (window->x11.lastKeyTime < event->xkey.time) + // HACK: Do not report the key press events duplicated by XIM + // Duplicate key releases are filtered out implicitly by + // the GLFW key repeat logic in _glfwInputKey + // A timestamp per key is used to handle simultaneous keys + // NOTE: Always allow the first event for each key through + // (the server never sends a timestamp of zero) + // NOTE: Timestamp difference is compared to handle wrap-around + Time diff = event->xkey.time - window->x11.keyPressTimes[keycode]; + if (diff == event->xkey.time || (diff > 0 && diff < (1 << 31))) { if (keycode) _glfwInputKey(window, key, keycode, GLFW_PRESS, mods); - window->x11.lastKeyTime = event->xkey.time; + window->x11.keyPressTimes[keycode] = event->xkey.time; } if (!filtered)