From 5e6350d14269132412e558d9f40f07c8180bb635 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Wed, 5 Feb 2025 09:04:09 +0300 Subject: [PATCH] x11: fix modifiers replay The serial was not unique, thus leading to issues and replay being triggered for normal input. Track modifiers based on they keycodes instead, since it's more unique. Links: https://github.com/alacritty/alacritty/issues/8461 --- src/platform_impl/linux/x11/event_processor.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 61365490..33833b08 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -66,7 +66,10 @@ pub struct EventProcessor { pub active_window: Option, /// Latest modifiers we've sent for the user to trigger change in event. pub modifiers: Cell, - pub xfiltered_modifiers: VecDeque, + // Track modifiers based on keycodes. NOTE: that serials generally don't work for tracking + // since they are not unique and could be duplicated in case of sequence of key events is + // delivered at near the same time. + pub xfiltered_modifiers: VecDeque, pub xmodmap: util::ModifierKeymap, pub is_composing: bool, } @@ -160,13 +163,11 @@ impl EventProcessor { 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 - // when the modifiers are consumed entirely or serials are altered. - // - // Both cases shouldn't happen in well behaving clients. + // when the modifiers are consumed entirely. if self.xfiltered_modifiers.len() == MAX_MOD_REPLAY_LEN { self.xfiltered_modifiers.pop_back(); } - self.xfiltered_modifiers.push_front(xev.serial); + self.xfiltered_modifiers.push_front(xev.keycode as u8); } } @@ -941,7 +942,7 @@ impl EventProcessor { // itself are out of sync due to XkbState being delivered before XKeyEvent, since it's // being replayed by the XIM, thus we should replay ourselves. let replay = if let Some(position) = - self.xfiltered_modifiers.iter().rev().position(|&s| s == xev.serial) + self.xfiltered_modifiers.iter().rev().position(|&s| s == xev.keycode as u8) { // We don't have to replay modifiers pressed before the current event if some events // were not forwarded to us, since their state is irrelevant.