diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-28 04:11:56 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-28 04:12:53 +0300 |
| commit | bf9cc201244946496b4d950046bf7edcc4892994 (patch) | |
| tree | 920c866e67783cf31d2feff9642457204999c8eb /src/pane.rs | |
| parent | 789738cada5afaa20bbd77a0d479fb689c455bfe (diff) | |
fix: preserve live handoff terminal state
Diffstat (limited to 'src/pane.rs')
| -rw-r--r-- | src/pane.rs | 76 |
1 files changed, 55 insertions, 21 deletions
diff --git a/src/pane.rs b/src/pane.rs index 77249de8..11d6e03c 100644 --- a/src/pane.rs +++ b/src/pane.rs @@ -16,6 +16,7 @@ use crate::events::AppEvent; use crate::layout::PaneId; mod input; +mod kitty_keyboard; mod osc; mod state; mod terminal; @@ -493,19 +494,6 @@ pub struct PaneRuntime { detect_handle: tokio::task::AbortHandle, } -#[cfg(unix)] -#[derive(Debug)] -pub struct PaneRuntimeImport { - pub pane_id: PaneId, - pub master_fd: std::os::fd::RawFd, - pub child_pid: u32, - pub rows: u16, - pub cols: u16, - pub cell_width_px: u32, - pub cell_height_px: u32, - pub initial_history_ansi: Option<String>, -} - #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum WheelRouting { HostScroll, @@ -835,16 +823,25 @@ impl PaneRuntime { } #[cfg(unix)] - pub fn handoff_pane(&self, pane_id: u32) -> crate::server::handoff::HandoffPane { + pub fn handoff_runtime_state( + &self, + pane_id: u32, + ) -> crate::handoff_runtime::HandoffRuntimeState { let child_pid = self.child_pid.load(Ordering::Acquire); let (rows, cols, cell_width_px, cell_height_px) = self.current_size.get(); - crate::server::handoff::HandoffPane { + crate::handoff_runtime::HandoffRuntimeState { pane_id, child_pid, rows, cols, cell_width_px, cell_height_px, + keyboard_protocol_flags: match self.keyboard_protocol() { + crate::input::KeyboardProtocol::Legacy => 0, + crate::input::KeyboardProtocol::Kitty { flags } => flags, + }, + keyboard_protocol_ansi: self.terminal.kitty_keyboard_state_ansi(), + input_state: self.input_state(), initial_history_ansi: None, } } @@ -1057,23 +1054,27 @@ impl PaneRuntime { #[cfg(unix)] pub fn from_handoff_fd( - import: PaneRuntimeImport, + import: crate::handoff_runtime::ImportedHandoffRuntime, scrollback_limit_bytes: usize, host_terminal_theme: crate::terminal_theme::TerminalTheme, events: mpsc::Sender<AppEvent>, render_notify: Arc<Notify>, render_dirty: Arc<AtomicBool>, ) -> std::io::Result<Self> { - let PaneRuntimeImport { + let crate::handoff_runtime::ImportedHandoffRuntime { master_fd, state } = import; + let crate::handoff_runtime::HandoffRuntimeState { pane_id, - master_fd, child_pid, rows, cols, cell_width_px, cell_height_px, + keyboard_protocol_flags, + keyboard_protocol_ansi, + input_state, initial_history_ansi, - } = import; + } = state; + let pane_id = PaneId::from_raw(pane_id); use std::os::fd::{AsRawFd, FromRawFd, IntoRawFd}; let master_fd = unsafe { std::os::fd::OwnedFd::from_raw_fd(master_fd) }; @@ -1099,12 +1100,20 @@ impl PaneRuntime { } let pane_terminal = GhosttyPaneTerminal::new(terminal, input_tx.clone())?; pane_terminal.apply_host_terminal_theme(host_terminal_theme); + if let Some(input_state) = input_state { + pane_terminal.seed_handoff_input_state(input_state); + } + if let Some(ansi) = keyboard_protocol_ansi.as_deref() { + pane_terminal.seed_keyboard_protocol_ansi(ansi); + } else { + pane_terminal.seed_keyboard_protocol_flags(keyboard_protocol_flags); + } if let Some(ansi) = initial_history_ansi.as_deref() { pane_terminal.seed_history_ansi(ansi); } let terminal = Arc::new(PaneTerminal::new(pane_terminal)); let child_pid = Arc::new(AtomicU32::new(child_pid)); - let kitty_keyboard_flags = Arc::new(AtomicU16::new(0)); + let kitty_keyboard_flags = Arc::new(AtomicU16::new(keyboard_protocol_flags)); let (reader_stopped_tx, reader_stopped_rx) = std::sync::mpsc::channel(); { @@ -1790,7 +1799,6 @@ impl PaneRuntime { self.detect_reset_notify.notify_one(); } - #[cfg(test)] pub(crate) fn current_size(&self) -> (u16, u16) { let (rows, cols, _, _) = self.current_size.get(); (rows, cols) @@ -2220,6 +2228,32 @@ mod tests { assert!(runtime.handoff_history_ansi().is_none()); } + #[tokio::test] + async fn handoff_runtime_state_captures_terminal_input_state() { + let runtime = PaneRuntime::test_with_screen_bytes( + 80, + 24, + b"\x1b[>5u\x1b[>4;2m\x1b[?1h\x1b[?2004h\x1b[?1004h\x1b[?1002h\x1b[?1006h", + ); + + let pane = runtime.handoff_runtime_state(12); + + assert_eq!(pane.keyboard_protocol_flags, 5); + assert_eq!( + pane.input_state, + Some(InputState { + alternate_screen: false, + application_cursor: true, + bracketed_paste: true, + focus_reporting: true, + mouse_protocol_mode: crate::input::MouseProtocolMode::ButtonMotion, + mouse_protocol_encoding: crate::input::MouseProtocolEncoding::Sgr, + mouse_alternate_scroll: true, + modify_other_keys: true, + }) + ); + } + #[test] fn truncate_handoff_history_keeps_recent_utf8_boundary() { let history = format!("old\n{}\nrecent\n", "é".repeat(8)); |
