diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-15 20:53:34 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-15 20:53:55 +0300 |
| commit | 73dba97521f5a0e3104518ef48b775a178998f52 (patch) | |
| tree | ad9f95b4836303a35974b9ccdde229a1b05b03f4 /src/pane | |
| parent | 4cbe72ec2d8a174e3c4f9bde2101aa189c7f38e7 (diff) | |
fix: forward pane cursor shape
fixes #116
Diffstat (limited to 'src/pane')
| -rw-r--r-- | src/pane/terminal.rs | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/pane/terminal.rs b/src/pane/terminal.rs index 33cd8ed5..f0535c7a 100644 --- a/src/pane/terminal.rs +++ b/src/pane/terminal.rs @@ -39,6 +39,21 @@ pub struct TerminalCursorState { pub x: u16, pub y: u16, pub visible: bool, + /// DECSCUSR parameter (0–6). 0 means terminal default. + pub shape: u8, +} + +fn decscusr_cursor_shape(style: crate::ghostty::CursorVisualStyle, blinking: bool) -> u8 { + match (style, blinking) { + (crate::ghostty::CursorVisualStyle::Block, true) + | (crate::ghostty::CursorVisualStyle::BlockHollow, true) => 1, + (crate::ghostty::CursorVisualStyle::Block, false) + | (crate::ghostty::CursorVisualStyle::BlockHollow, false) => 2, + (crate::ghostty::CursorVisualStyle::Underline, true) => 3, + (crate::ghostty::CursorVisualStyle::Underline, false) => 4, + (crate::ghostty::CursorVisualStyle::Bar, true) => 5, + (crate::ghostty::CursorVisualStyle::Bar, false) => 6, + } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -530,10 +545,17 @@ impl GhosttyPaneTerminal { } = &mut *core; render_state.update(terminal).ok()?; let cursor = render_state.cursor_viewport().ok()??; + let shape = render_state + .cursor_visual_style() + .ok() + .zip(render_state.cursor_blinking().ok()) + .map(|(style, blinking)| decscusr_cursor_shape(style, blinking)) + .unwrap_or(0); Some(TerminalCursorState { x: cursor.x, y: cursor.y, visible: render_state.cursor_visible().ok()?, + shape, }) } @@ -1203,6 +1225,38 @@ mod tests { } #[test] + fn decscusr_cursor_shape_preserves_blinking_variants() { + assert_eq!( + decscusr_cursor_shape(crate::ghostty::CursorVisualStyle::Block, true), + 1 + ); + assert_eq!( + decscusr_cursor_shape(crate::ghostty::CursorVisualStyle::Block, false), + 2 + ); + assert_eq!( + decscusr_cursor_shape(crate::ghostty::CursorVisualStyle::Underline, true), + 3 + ); + assert_eq!( + decscusr_cursor_shape(crate::ghostty::CursorVisualStyle::Underline, false), + 4 + ); + assert_eq!( + decscusr_cursor_shape(crate::ghostty::CursorVisualStyle::Bar, true), + 5 + ); + assert_eq!( + decscusr_cursor_shape(crate::ghostty::CursorVisualStyle::Bar, false), + 6 + ); + assert_eq!( + decscusr_cursor_shape(crate::ghostty::CursorVisualStyle::BlockHollow, false), + 2 + ); + } + + #[test] fn host_terminal_theme_restore_probe_skips_when_no_transient_override() { let (tx, _rx) = mpsc::channel(4); let terminal = crate::ghostty::Terminal::new(80, 24, 0).unwrap(); |
