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 committed Feb 5, 2025
1 parent 3912577 commit e8461f5
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 7 deletions.
3 changes: 2 additions & 1 deletion src/changelog/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
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 @@ -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);
}
}

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

0 comments on commit e8461f5

Please sign in to comment.