aboutsummaryrefslogtreecommitdiff
path: root/src/server
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/server
parent4cbe72ec2d8a174e3c4f9bde2101aa189c7f38e7 (diff)
fix: forward pane cursor shape
fixes #116
Diffstat (limited to 'src/server')
-rw-r--r--src/server/headless.rs2
-rw-r--r--src/server/protocol.rs15
-rw-r--r--src/server/render_stream.rs2
3 files changed, 18 insertions, 1 deletions
diff --git a/src/server/headless.rs b/src/server/headless.rs
index cc57c1f5..9bb3181f 100644
--- a/src/server/headless.rs
+++ b/src/server/headless.rs
@@ -2137,6 +2137,7 @@ mod tests {
x: pane.inner_rect.x + 4,
y: pane.inner_rect.y,
visible: true,
+ shape: cursor.as_ref().map(|c| c.shape).unwrap_or(0),
})
);
}
@@ -2172,6 +2173,7 @@ mod tests {
x: pane.inner_rect.x + 4,
y: pane.inner_rect.y,
visible: false,
+ shape: cursor.as_ref().map(|c| c.shape).unwrap_or(0),
})
);
}
diff --git a/src/server/protocol.rs b/src/server/protocol.rs
index e9b7975e..7d0d3e2d 100644
--- a/src/server/protocol.rs
+++ b/src/server/protocol.rs
@@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize};
// ---------------------------------------------------------------------------
/// Current protocol version. Bumped when wire format changes incompatibly.
-pub const PROTOCOL_VERSION: u32 = 5;
+pub const PROTOCOL_VERSION: u32 = 6;
/// Maximum allowed frame payload size (2 MB). Frames larger than this are
/// rejected to prevent denial-of-service via oversized length prefixes.
@@ -103,6 +103,13 @@ pub struct CellData {
pub hyperlink: Option<u32>,
}
+/// Cursor shape encoded as a DECSCUSR parameter.
+///
+/// 0 = terminal default, 1 = blinking block, 2 = steady block,
+/// 3 = blinking underline, 4 = steady underline, 5 = blinking bar,
+/// 6 = steady bar.
+pub type CursorShapeParam = u8;
+
/// Cursor position within a rendered frame.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CursorState {
@@ -112,6 +119,9 @@ pub struct CursorState {
pub y: u16,
/// Whether the cursor is visible.
pub visible: bool,
+ /// Cursor shape as a DECSCUSR parameter.
+ #[serde(default)]
+ pub shape: CursorShapeParam,
}
/// A rendered frame to be displayed by the client.
@@ -725,6 +735,7 @@ mod tests {
x: 0,
y: 0,
visible: true,
+ shape: 6,
}),
hyperlinks: vec!["https://example.com".to_owned()],
graphics: Vec::new(),
@@ -875,6 +886,7 @@ mod tests {
x: 10,
y: 5,
visible: true,
+ shape: 0,
}),
hyperlinks: Vec::new(),
graphics: Vec::new(),
@@ -1151,6 +1163,7 @@ mod tests {
x: 1,
y: 0,
visible: true,
+ shape: 0,
};
let frame = FrameData::from_ratatui_buffer(&buffer, Some(cursor.clone()));
diff --git a/src/server/render_stream.rs b/src/server/render_stream.rs
index ca0ecddd..a921960c 100644
--- a/src/server/render_stream.rs
+++ b/src/server/render_stream.rs
@@ -151,6 +151,7 @@ impl CursorTrackingBackend {
x: pos.x,
y: pos.y,
visible: true,
+ shape: 0,
})
}
}
@@ -296,5 +297,6 @@ fn focused_terminal_cursor(app_state: &AppState) -> Option<CursorState> {
x: cursor.x,
y: cursor.y,
visible: cursor.visible && !crate::ui::pane_is_scrolled_back(rt),
+ shape: cursor.shape,
})
}