aboutsummaryrefslogtreecommitdiff
path: root/src/pane
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-05-15 20:53:34 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-05-15 20:53:55 +0300
commit73dba97521f5a0e3104518ef48b775a178998f52 (patch)
treead9f95b4836303a35974b9ccdde229a1b05b03f4 /src/pane
parent4cbe72ec2d8a174e3c4f9bde2101aa189c7f38e7 (diff)
fix: forward pane cursor shape
fixes #116
Diffstat (limited to 'src/pane')
-rw-r--r--src/pane/terminal.rs54
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();