diff --git a/docs/next/CHANGELOG.md b/docs/next/CHANGELOG.md index 05f3680842..ef42736b6a 100644 --- a/docs/next/CHANGELOG.md +++ b/docs/next/CHANGELOG.md @@ -28,6 +28,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) diff --git a/src/pane/terminal.rs b/src/pane/terminal.rs index 0b06302e95..f1c6e2e5a2 100644 --- a/src/pane/terminal.rs +++ b/src/pane/terminal.rs @@ -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]