Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Correct SUPER modifier key handling in kitty protocol #4605

Merged
80 changes: 75 additions & 5 deletions wezterm-input-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1674,6 +1674,9 @@ impl KeyEvent {
if raw_modifiers.contains(Modifiers::SUPER) {
modifiers |= 8;
}
// TODO: Hyper and Meta are not handled yet.
// We should somehow detect this?
// See: https://github.com/wez/wezterm/pull/4605#issuecomment-1823604708
if self.leds.contains(KeyboardLedStatus::CAPS_LOCK) {
modifiers |= 64;
}
Expand Down Expand Up @@ -1800,30 +1803,31 @@ impl KeyEvent {
format!("\x1b[{c};{modifiers}{event_type}~")
}
Char(shifted_key) => {
let mut use_legacy = false;
let shifted_key = if *shifted_key == '\x08' {
// Backspace is really VERASE -> ASCII DEL
'\x7f'
} else {
*shifted_key
};

if !flags.contains(KittyKeyboardFlags::REPORT_ALTERNATE_KEYS)
let use_legacy = !flags.contains(KittyKeyboardFlags::REPORT_ALTERNATE_KEYS)
&& event_type.is_empty()
&& is_legacy_key
&& !(flags.contains(KittyKeyboardFlags::DISAMBIGUATE_ESCAPE_CODES)
&& (self.modifiers.contains(Modifiers::CTRL)
|| self.modifiers.contains(Modifiers::ALT)))
{
use_legacy = true;
}
&& !self.modifiers.intersects(
Modifiers::SUPER, /* TODO: Hyper and Meta should be added here. */
);

if use_legacy {
// Legacy text key
// https://sw.kovidgoyal.net/kitty/keyboard-protocol/#legacy-text-keys
let mut output = String::new();
if self.modifiers.contains(Modifiers::ALT) {
output.push('\x1b');
}

if self.modifiers.contains(Modifiers::CTRL) {
csi_u_encode(
&mut output,
Expand All @@ -1833,6 +1837,7 @@ impl KeyEvent {
} else {
output.push(shifted_key);
}

return output;
}

Expand Down Expand Up @@ -3054,4 +3059,69 @@ mod test {
"".to_string()
);
}

#[test]
fn encode_issue_4436() {
let flags = KittyKeyboardFlags::DISAMBIGUATE_ESCAPE_CODES;

assert_eq!(
KeyEvent {
key: KeyCode::Char('q'),
modifiers: Modifiers::NONE,
leds: KeyboardLedStatus::empty(),
repeat_count: 1,
key_is_down: true,
raw: None,
#[cfg(windows)]
win32_uni_char: None,
}
.encode_kitty(flags),
"q".to_string()
);

assert_eq!(
KeyEvent {
key: KeyCode::Char('f'),
modifiers: Modifiers::SUPER,
leds: KeyboardLedStatus::empty(),
repeat_count: 1,
key_is_down: true,
raw: None,
#[cfg(windows)]
win32_uni_char: None,
}
.encode_kitty(flags),
"\u{1b}[102;9u".to_string()
);

assert_eq!(
KeyEvent {
key: KeyCode::Char('f'),
modifiers: Modifiers::SUPER | Modifiers::SHIFT,
leds: KeyboardLedStatus::empty(),
repeat_count: 1,
key_is_down: true,
raw: None,
#[cfg(windows)]
win32_uni_char: None,
}
.encode_kitty(flags),
"\u{1b}[102;10u".to_string()
);

assert_eq!(
KeyEvent {
key: KeyCode::Char('f'),
modifiers: Modifiers::SUPER | Modifiers::SHIFT | Modifiers::CTRL,
leds: KeyboardLedStatus::empty(),
repeat_count: 1,
key_is_down: true,
raw: None,
#[cfg(windows)]
win32_uni_char: None,
}
.encode_kitty(flags),
"\u{1b}[102;14u".to_string()
);
}
}