Skip to content

Commit

Permalink
x11: fix KeyboardInput delivered twice with IME
Browse files Browse the repository at this point in the history
The filtered events were still processed even though they shouldn't once
we know that they're filtered.

Fixes #4048.
  • Loading branch information
kchibisov authored Dec 22, 2024
1 parent f0d8689 commit e316a89
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/changelog/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
15 changes: 12 additions & 3 deletions src/platform_impl/linux/x11/event_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, {
Expand All @@ -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
Expand All @@ -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 {
Expand Down

0 comments on commit e316a89

Please sign in to comment.