Skip to content

Commit

Permalink
x11: fix modifiers replay
Browse files Browse the repository at this point in the history
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: alacritty/alacritty#8461
  • Loading branch information
kchibisov authored Feb 5, 2025
1 parent a6998af commit 5e6350d
Showing 1 changed file with 7 additions and 6 deletions.
13 changes: 7 additions & 6 deletions src/platform_impl/linux/x11/event_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ pub struct EventProcessor {
pub active_window: Option<xproto::Window>,
/// Latest modifiers we've sent for the user to trigger change in event.
pub modifiers: Cell<ModifiersState>,
pub xfiltered_modifiers: VecDeque<c_ulong>,
// 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<u8>,
pub xmodmap: util::ModifierKeymap,
pub is_composing: bool,
}
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit 5e6350d

Please sign in to comment.