From fa5a3167392fb8cabde8091580a7eece31a0c6f5 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sun, 22 Dec 2024 05:34:17 +0300 Subject: [PATCH] x11: fix KeyboardInput delivered twice with IME The filtered events were still processed even though they shouldn't once we know that they're filtered. Fixes #4048. --- src/changelog/unreleased.md | 1 + src/platform_impl/linux/x11/event_processor.rs | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/changelog/unreleased.md b/src/changelog/unreleased.md index a835e0c944..c1eadf59f6 100644 --- a/src/changelog/unreleased.md +++ b/src/changelog/unreleased.md @@ -200,3 +200,4 @@ changelog entry. - On macOS, fixed the scancode conversion for audio volume keys. - On macOS, fixed the scancode conversion for `IntlBackslash`. - On macOS, fixed redundant `SurfaceResized` event at window creation. +- On X11, fixed KeyboardInput delivered twice when IME enabled. diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 6ce100e850..dbe82935da 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -128,6 +128,7 @@ impl EventProcessor { /// Specifically, this involves all of the KeyPress events in compose/pre-edit sequences, /// along with an extra copy of the KeyRelease events. This also prevents backspace and /// arrow keys from being detected twice. + #[must_use] fn filter_event(&mut self, xev: &mut XEvent) -> bool { unsafe { (self.target.xconn.xlib.XFilterEvent)(xev, { @@ -147,14 +148,15 @@ impl EventProcessor { // and forward back. This is not desired for e.g. games since some IMEs may delay the input // and game can toggle IME back when e.g. typing into some field where latency won't really // matter. - if event_type == xlib::KeyPress || event_type == xlib::KeyRelease { + let filtered = if event_type == xlib::KeyPress || event_type == xlib::KeyRelease { let ime = self.target.ime.as_ref(); let window = self.active_window.map(|window| window as XWindow); let forward_to_ime = ime .and_then(|ime| window.map(|window| ime.borrow().is_ime_allowed(window))) .unwrap_or(false); - if forward_to_ime && self.filter_event(xev) { + let filtered = forward_to_ime && self.filter_event(xev); + if filtered { let xev: &XKeyEvent = xev.as_ref(); if self.xmodmap.is_modifier(xev.keycode as u8) { // Don't grow the buffer past the `MAX_MOD_REPLAY_LEN`. This could happen @@ -167,8 +169,15 @@ impl EventProcessor { self.xfiltered_modifiers.push_front(xev.serial); } } + + filtered } else { - self.filter_event(xev); + self.filter_event(xev) + }; + + // Don't process event if it was filtered. + if filtered { + return; } match event_type {