fix(input): preserve mouse forwarding through handoff (#3002)

refs #3000

Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
This commit is contained in:
akbash
2026-08-20 00:41:32 +03:00
committed by GitHub
co-authored by akbash-bot
parent 4d17957c43
commit 52960ea5b6
2 changed files with 26 additions and 39 deletions
+1
View File
@@ -31,6 +31,7 @@
- Experimental pane graphics now support bounded named layers, acknowledged full-RGBA primary-layer direct file frames on audited local terminals, owned BGRA fallback, exact pixel mouse input, and placement-only resize replay.
### Fixed
- Live handoff now preserves mouse forwarding for running pane applications. (#3000, thanks @xkrogen)
- Unix CLI commands now exit quietly when a downstream pipe closes instead of panicking with exit 101. (#2994)
- The terminal theme now keeps the active Space row fill visible when the Navigate cursor lands on it, in both expanded and collapsed sidebars. (#2987)
- Busy multi-pane sessions now avoid redundant hidden-pane wakeups and full terminal-state formatting in pane-scaled paths, preventing CPU regressions from high-rate background output, scrollbars, and enhanced keyboard modes. (#2550, #2901, #2962)
+25 -39
View File
@@ -1489,49 +1489,28 @@ impl GhosttyPaneTerminal {
input_state.color_scheme_reporting,
);
for mode in [
MODE_MOUSE_X10,
MODE_MOUSE_PRESS_RELEASE,
MODE_MOUSE_BUTTON_MOTION,
MODE_MOUSE_ANY_MOTION,
] {
let _ = core.terminal.mode_set(mode, false);
}
let mouse_mode = match input_state.mouse_protocol_mode {
core.terminal
.write(b"\x1b[?9l\x1b[?1000l\x1b[?1002l\x1b[?1003l");
let mouse_mode_ansi: Option<&[u8]> = match input_state.mouse_protocol_mode {
crate::input::MouseProtocolMode::None => None,
crate::input::MouseProtocolMode::Press => Some(MODE_MOUSE_X10),
crate::input::MouseProtocolMode::PressRelease => Some(MODE_MOUSE_PRESS_RELEASE),
crate::input::MouseProtocolMode::ButtonMotion => Some(MODE_MOUSE_BUTTON_MOTION),
crate::input::MouseProtocolMode::AnyMotion => Some(MODE_MOUSE_ANY_MOTION),
crate::input::MouseProtocolMode::Press => Some(b"\x1b[?9h"),
crate::input::MouseProtocolMode::PressRelease => Some(b"\x1b[?1000h"),
crate::input::MouseProtocolMode::ButtonMotion => Some(b"\x1b[?1002h"),
crate::input::MouseProtocolMode::AnyMotion => Some(b"\x1b[?1003h"),
};
if let Some(mode) = mouse_mode {
let _ = core.terminal.mode_set(mode, true);
if let Some(ansi) = mouse_mode_ansi {
core.terminal.write(ansi);
}
let _ = core
.terminal
.mode_set(crate::ghostty::MODE_MOUSE_UTF8, false);
let _ = core
.terminal
.mode_set(crate::ghostty::MODE_MOUSE_SGR, false);
let _ = core
.terminal
.mode_set(crate::ghostty::MODE_MOUSE_SGR_PIXELS, false);
match input_state.mouse_protocol_encoding {
crate::input::MouseProtocolEncoding::Default => {}
crate::input::MouseProtocolEncoding::Utf8 => {
let _ = core
.terminal
.mode_set(crate::ghostty::MODE_MOUSE_UTF8, true);
}
crate::input::MouseProtocolEncoding::Sgr => {
let _ = core.terminal.mode_set(crate::ghostty::MODE_MOUSE_SGR, true);
}
crate::input::MouseProtocolEncoding::SgrPixels => {
let _ = core
.terminal
.mode_set(crate::ghostty::MODE_MOUSE_SGR_PIXELS, true);
}
core.terminal.write(b"\x1b[?1005l\x1b[?1006l\x1b[?1016l");
let mouse_encoding_ansi: Option<&[u8]> = match input_state.mouse_protocol_encoding {
crate::input::MouseProtocolEncoding::Default => None,
crate::input::MouseProtocolEncoding::Utf8 => Some(b"\x1b[?1005h"),
crate::input::MouseProtocolEncoding::Sgr => Some(b"\x1b[?1006h"),
crate::input::MouseProtocolEncoding::SgrPixels => Some(b"\x1b[?1016h"),
};
if let Some(ansi) = mouse_encoding_ansi {
core.terminal.write(ansi);
}
if input_state.modify_other_keys {
@@ -4510,6 +4489,13 @@ mod tests {
let key = crate::input::parse_terminal_key_sequence("\x1b[13;2u").unwrap();
let encoded = pane.encode_terminal_key(key.clone(), crate::input::KeyboardProtocol::Legacy);
assert_eq!(encoded, b"\x1b[27;2;13~");
let encoded = pane.encode_mouse_wheel(
crossterm::event::MouseEventKind::ScrollUp,
crate::input::mouse::Position::Cell { column: 11, row: 9 },
crossterm::event::KeyModifiers::empty(),
);
assert_eq!(encoded.as_deref(), Some(&b"\x1b[<64;12;10M"[..]));
}
#[test]