From df5230ff4a88928522c463f28e52b3ee9ec003e6 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Mon, 29 Sep 2025 21:08:56 +0200 Subject: [PATCH] Reliably disable modifyOtherKeys on WezTerm WezTerm allows applications to enable modifyOtherKeys by default. Its implementation has issues on non-English or non-QWERTY layouts, see https://github.com/wezterm/wezterm/issues/6087 and #11204. fish 4.0.1 disabled modifyOtherKeys on WezTerm specifically (7ee6d91ba05 (Work around keyboard-layout related bugs in WezTerm's modifyOtherKeys, 2025-03-03)), fish 4.1.0 didn't, because at that time, WezTerm would advertise support for the kitty keyboard protocol (even if applications are not allowed to enable it) which would make fish skip requesting the legacy modifyOtherKeys. WezTerm no longer advertises that if config.enable_kitty_keyboard is false. Let's work around it in another way. --- CHANGELOG.rst | 1 + src/tty_handoff.rs | 28 +++++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c27038a48..615279551 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,6 +7,7 @@ fish 4.1.1 (released ???) This release fixes the following regressions identified in 4.1.0: - Some :doc:`fish_config ` subcommands for prompts and themes were broken in standalone Linux builds (those using the ``embed-data`` cargo feature), which has been fixed (:issue:`11832`). +- Our new workaround for WezTerm's `issues with modifyOtherKeys `__ breaking shifted keys was broken on some versions of WezTerm, which has been fixed (:issue:`11204`). fish 4.1.0 (released September 27, 2025) ======================================== diff --git a/src/tty_handoff.rs b/src/tty_handoff.rs index 124dae742..77ff42cdb 100644 --- a/src/tty_handoff.rs +++ b/src/tty_handoff.rs @@ -64,6 +64,8 @@ pub enum TtyQuirks { PreKittyIterm2, // Whether we are running under tmux. Tmux, + // Whether we are running under WezTerm. + Wezterm, } impl TtyQuirks { @@ -74,6 +76,8 @@ fn detect(xtversion: &wstr) -> Self { PreKittyIterm2 } else if xtversion.starts_with(L!("tmux ")) { Tmux + } else if xtversion.starts_with(L!("WezTerm ")) { + Wezterm } else { None } @@ -85,7 +89,8 @@ fn detect(xtversion: &wstr) -> Self { enum ProtocolKind { KittyKeyboard, // Kitty keyboard support, producing CSI-u style encoding. Other, // Other protocols (e.g., modifyOtherKeys) - None, // No protocols + WorkAroundWezTerm, + None, // No protocols } // Commands to emit to enable or disable TTY protocols. Each of these contains @@ -95,6 +100,7 @@ enum ProtocolKind { struct ProtocolBytes { kitty_keyboard: Box<[u8]>, other: Box<[u8]>, + wezterm_workaround: Box<[u8]>, none: Box<[u8]>, } @@ -123,6 +129,7 @@ fn safe_get_commands(&self, enable: bool) -> &[u8] { match protocol { ProtocolKind::KittyKeyboard => &cmds.kitty_keyboard, ProtocolKind::Other => &cmds.other, + ProtocolKind::WorkAroundWezTerm => &cmds.wezterm_workaround, ProtocolKind::None => &cmds.none, } } @@ -141,13 +148,19 @@ impl TtyQuirks { // Determine which keyboard protocol. // This is used from a signal handler. fn safe_get_supported_protocol(&self) -> ProtocolKind { - use TtyQuirks::PreKittyIterm2; + use TtyQuirks::{PreKittyIterm2, Wezterm}; if *self == PreKittyIterm2 { return ProtocolKind::Other; } match KITTY_KEYBOARD_SUPPORTED.get() { Some(&true) => ProtocolKind::KittyKeyboard, - Some(&false) => ProtocolKind::Other, + Some(&false) => { + if *self == Wezterm { + ProtocolKind::WorkAroundWezTerm + } else { + ProtocolKind::Other + } + } None => ProtocolKind::None, } } @@ -178,6 +191,10 @@ fn get_protocols(self) -> TtyProtocolsSet { ModifyOtherKeysEnable, // XTerm's modifyOtherKeys ApplicationKeypadModeEnable, // set application keypad mode, so the keypad keys send unique codes ])), + wezterm_workaround: serialize_commands(maybe_enable_focus_reporting(&[ + DecsetBracketedPaste, + ApplicationKeypadModeEnable, // set application keypad mode, so the keypad keys send unique codes + ])), none: serialize_commands(maybe_enable_focus_reporting(&[DecsetBracketedPaste])), }; let disablers = ProtocolBytes { @@ -190,6 +207,10 @@ fn get_protocols(self) -> TtyProtocolsSet { ModifyOtherKeysDisable, ApplicationKeypadModeDisable, ])), + wezterm_workaround: serialize_commands(maybe_disable_focus_reporting(&[ + DecrstBracketedPaste, + ApplicationKeypadModeDisable, + ])), none: serialize_commands(maybe_disable_focus_reporting(&[DecrstBracketedPaste])), }; TtyProtocolsSet { @@ -273,6 +294,7 @@ fn set_tty_protocols_active(on_write: fn(), enable: bool) -> bool { match protocols.quirks.safe_get_supported_protocol() { ProtocolKind::KittyKeyboard => FLOG!(reader, mode, "kitty keyboard protocol"), ProtocolKind::Other => FLOG!(reader, mode, "other extended keys"), + ProtocolKind::WorkAroundWezTerm => FLOG!(reader, mode, "wezterm; no modifyOtherKeys"), ProtocolKind::None => (), }; (on_write)();