diff --git a/src/changelog/unreleased.md b/src/changelog/unreleased.md index 38c723927..afe1edb60 100644 --- a/src/changelog/unreleased.md +++ b/src/changelog/unreleased.md @@ -46,4 +46,5 @@ changelog entry. ### Fixed -- On X11, fixed crash with uim +- On X11, fix crash with uim. +- On X11, fix modifiers for keys that were sent by the same X11 request. diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 438c808b8..79f5c114f 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, } @@ -163,13 +166,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); } } @@ -950,7 +951,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.