Account for option_as_alt when doing kitty protocol

By default `Alt` is not a real `Alt` on macOS, so we shouldn't treat
it as a modifier.

Fixes #7443.
This commit is contained in:
Kirill Chibisov 2023-12-20 10:37:21 +04:00 committed by GitHub
parent a10fb8adc0
commit 3d7d81c848
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -78,13 +78,16 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
return;
}
// Mask `Alt` modifier from input when we won't send esc.
let mods = if self.alt_send_esc(&key, text) { mods } else { mods & !ModifiersState::ALT };
let build_key_sequence = Self::should_build_sequence(&key, text, mode, mods);
let bytes = if build_key_sequence {
build_sequence(key, mods, mode)
} else {
let mut bytes = Vec::with_capacity(text.len() + 1);
if self.alt_send_esc() && text.len() == 1 {
if mods.alt_key() {
bytes.push(b'\x1b');
}
@ -99,6 +102,34 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
}
}
fn alt_send_esc(&mut self, key: &KeyEvent, text: &str) -> bool {
#[cfg(not(target_os = "macos"))]
let alt_send_esc = self.ctx.modifiers().state().alt_key();
#[cfg(target_os = "macos")]
let alt_send_esc = {
let option_as_alt = self.ctx.config().window.option_as_alt();
self.ctx.modifiers().state().alt_key()
&& (option_as_alt == OptionAsAlt::Both
|| (option_as_alt == OptionAsAlt::OnlyLeft
&& self.ctx.modifiers().lalt_state() == ModifiersKeyState::Pressed)
|| (option_as_alt == OptionAsAlt::OnlyRight
&& self.ctx.modifiers().ralt_state() == ModifiersKeyState::Pressed))
};
match key.logical_key {
Key::Named(named) => {
if named.to_text().is_some() {
alt_send_esc
} else {
// Treat `Alt` as modifier for named keys without text, like ArrowUp.
self.ctx.modifiers().state().alt_key()
}
},
_ => text.len() == 1 && alt_send_esc,
}
}
/// Check whether we should try to build escape sequence for the [`KeyEvent`].
fn should_build_sequence(
key: &KeyEvent,
@ -123,23 +154,6 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
}
}
/// Whether we should send `ESC` due to `Alt` being pressed.
#[cfg(not(target_os = "macos"))]
fn alt_send_esc(&mut self) -> bool {
self.ctx.modifiers().state().alt_key()
}
#[cfg(target_os = "macos")]
fn alt_send_esc(&mut self) -> bool {
let option_as_alt = self.ctx.config().window.option_as_alt();
self.ctx.modifiers().state().alt_key()
&& (option_as_alt == OptionAsAlt::Both
|| (option_as_alt == OptionAsAlt::OnlyLeft
&& self.ctx.modifiers().lalt_state() == ModifiersKeyState::Pressed)
|| (option_as_alt == OptionAsAlt::OnlyRight
&& self.ctx.modifiers().ralt_state() == ModifiersKeyState::Pressed))
}
/// Attempt to find a binding and execute its action.
///
/// The provided mode, mods, and key must match what is allowed by a binding
@ -190,6 +204,10 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
return;
}
// Mask `Alt` modifier from input when we won't send esc.
let text = key.text_with_all_modifiers().unwrap_or_default();
let mods = if self.alt_send_esc(&key, text) { mods } else { mods & !ModifiersState::ALT };
let bytes: Cow<'static, [u8]> = match key.logical_key.as_ref() {
// NOTE: Echo the key back on release to follow kitty/foot behavior. When
// KEYBOARD_REPORT_ALL_KEYS_AS_ESC is used, we build proper escapes for