aboutsummaryrefslogtreecommitdiff
path: root/src/server/render_stream.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/render_stream.rs')
-rw-r--r--src/server/render_stream.rs49
1 files changed, 41 insertions, 8 deletions
diff --git a/src/server/render_stream.rs b/src/server/render_stream.rs
index 45542a7a..ca0ecddd 100644
--- a/src/server/render_stream.rs
+++ b/src/server/render_stream.rs
@@ -57,7 +57,8 @@ impl ClientRenderState {
if blit_encoder.is_current(frame) {
return None;
}
- let encoded = blit_encoder.encode(frame, false);
+ let mut encoded = blit_encoder.encode(frame, false);
+ insert_graphics_before_sync_end(&mut encoded.bytes, &frame.graphics);
Some(PreparedRender {
message: ServerMessage::Terminal(TerminalFrame {
seq: *seq + 1,
@@ -72,12 +73,6 @@ impl ClientRenderState {
}
}
- pub(crate) fn note_oversized_frame(&mut self, frame: FrameData) {
- if let Self::Semantic { last_frame } = self {
- *last_frame = Some(frame);
- }
- }
-
pub(crate) fn commit_sent_frame(&mut self, frame: FrameData, prepared: PreparedRender) {
match (self, prepared.encoded) {
(Self::Semantic { last_frame }, None) => *last_frame = Some(frame),
@@ -98,6 +93,30 @@ impl ClientRenderState {
}
}
+const SYNC_OUTPUT_END: &[u8] = b"\x1b[?2026l";
+
+fn insert_graphics_before_sync_end(encoded: &mut Vec<u8>, graphics: &[u8]) {
+ if graphics.is_empty() {
+ return;
+ }
+
+ if let Some(sync_end) = rfind_subslice(encoded, SYNC_OUTPUT_END) {
+ encoded.splice(sync_end..sync_end, graphics.iter().copied());
+ } else {
+ encoded.extend_from_slice(graphics);
+ }
+}
+
+fn rfind_subslice(haystack: &[u8], needle: &[u8]) -> Option<usize> {
+ if needle.is_empty() || needle.len() > haystack.len() {
+ return None;
+ }
+
+ haystack
+ .windows(needle.len())
+ .rposition(|window| window == needle)
+}
+
/// A prepared client render message plus any baseline state needed after send.
pub(crate) struct PreparedRender {
message: ServerMessage,
@@ -202,8 +221,22 @@ pub(crate) fn render_virtual(
area: Rect,
resize_panes: bool,
) -> (ratatui::buffer::Buffer, Option<CursorState>) {
+ render_virtual_with_cell_size(
+ app_state,
+ area,
+ resize_panes,
+ crate::kitty_graphics::HostCellSize::default(),
+ )
+}
+
+pub(crate) fn render_virtual_with_cell_size(
+ app_state: &mut AppState,
+ area: Rect,
+ resize_panes: bool,
+ cell_size: crate::kitty_graphics::HostCellSize,
+) -> (ratatui::buffer::Buffer, Option<CursorState>) {
if resize_panes {
- crate::ui::compute_view(app_state, area);
+ crate::ui::compute_view_with_cell_size(app_state, area, cell_size);
} else {
crate::ui::compute_view_without_resizing_panes(app_state, area);
}