From 9a3664b4a992a5a9b669179098542b0f882dece7 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. --- 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 64416958..e6440d51 100644 --- a/README.md +++ b/README.md @@ -190,6 +190,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] Removed support for `wl_shell` (#1443) - [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432) - [Wayland] Bugfix: `CLOCK_MONOTONIC` was not correctly enabled @@ -364,8 +366,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 1d0687ef..62db6644 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -402,8 +402,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 d56fe3da..726d7eaa 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -1265,16 +1265,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)