diff options
author | Kirill Chibisov <contact@kchibisov.com> | 2023-12-25 18:52:35 +0400 |
---|---|---|
committer | Christian Duerr <contact@christianduerr.com> | 2023-12-27 22:13:35 +0100 |
commit | 38fcdb600a3512bdc6d4b79730746a97067ca78a (patch) | |
tree | d820a1c9ed875535e3fefabca7705a9feef9d1cb | |
parent | b8acfdae1936fbdc8745fd5d9269b546a4bb9b0f (diff) | |
download | alacritty-38fcdb600a3512bdc6d4b79730746a97067ca78a.tar.gz alacritty-38fcdb600a3512bdc6d4b79730746a97067ca78a.zip |
Apply modifiers before presses in kitty protocol
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: https://github.com/kovidgoyal/kitty/issues/6913
-rw-r--r-- | alacritty/src/input/keyboard.rs | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs index 160600a1..423f8bae 100644 --- a/alacritty/src/input/keyboard.rs +++ b/alacritty/src/input/keyboard.rs @@ -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 @@ -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 { @@ -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; } @@ -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 { |