Skip to content

Commit

Permalink
Apply modifiers before presses in kitty protocol
Browse files Browse the repository at this point in the history
While this doesn't handle releases with multiple identical modifiers
pressed, the release can't work reliable anyway, since one modifier
could be pressed before focusing the window, thus tracking modifiers
based on the keysym values won't work as it was suggested by kitty
author.

Links: kovidgoyal/kitty#6913
  • Loading branch information
kchibisov authored and chrisduerr committed Dec 27, 2023
1 parent b8acfda commit 28166f5
Showing 1 changed file with 20 additions and 3 deletions.
23 changes: 20 additions & 3 deletions alacritty/src/input/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
/// The key sequences for `APP_KEYPAD` and alike are handled inside the bindings.
#[inline(never)]
fn build_sequence(key: KeyEvent, mods: ModifiersState, mode: TermMode) -> Vec<u8> {
let modifiers = mods.into();
let mut modifiers = mods.into();

let kitty_seq = mode.intersects(
TermMode::REPORT_ALL_KEYS_AS_ESC
Expand All @@ -263,7 +263,7 @@ fn build_sequence(key: KeyEvent, mods: ModifiersState, mode: TermMode) -> Vec<u8
let sequence_base = context
.try_build_numpad(&key)
.or_else(|| context.try_build_named(&key))
.or_else(|| context.try_build_control_char_or_mod(&key))
.or_else(|| context.try_build_control_char_or_mod(&key, &mut modifiers))
.or_else(|| context.try_build_textual(&key));

let (payload, terminator) = match sequence_base {
Expand Down Expand Up @@ -493,7 +493,11 @@ impl SequenceBuilder {
}

/// Try building escape from control characters (e.g. Enter) and modifiers.
fn try_build_control_char_or_mod(&self, key: &KeyEvent) -> Option<SequenceBase> {
fn try_build_control_char_or_mod(
&self,
key: &KeyEvent,
mods: &mut SequenceModifiers,
) -> Option<SequenceBase> {
if !self.kitty_encode_all && !self.kitty_seq {
return None;
}
Expand Down Expand Up @@ -536,6 +540,19 @@ impl SequenceBuilder {
_ => base,
};

// NOTE: Kitty's protocol mandates that the modifier state is applied before
// key press, however winit sends them after the key press, so for modifiers
// itself apply the state based on keysyms and not the _actual_ modifiers
// state, which is how kitty is doing so and what is suggested in such case.
let press = key.state.is_pressed();
match named {
NamedKey::Shift => mods.set(SequenceModifiers::SHIFT, press),
NamedKey::Control => mods.set(SequenceModifiers::CONTROL, press),
NamedKey::Alt => mods.set(SequenceModifiers::ALT, press),
NamedKey::Super => mods.set(SequenceModifiers::SUPER, press),
_ => (),
}

if base.is_empty() {
None
} else {
Expand Down

0 comments on commit 28166f5

Please sign in to comment.