From ffca97f5a9bc74a7ccac5dee20845959793bc24b Mon Sep 17 00:00:00 2001 From: Aram Drevekenin Date: Mon, 8 Jul 2024 14:30:31 +0200 Subject: [PATCH] fix(terminal): properly cache cursor position for synchronized renders (#3483) * fix(terminal): properly cache cursor position for synchronized renders * style(fmt): rustfmt --- zellij-server/src/panes/grid.rs | 3 ++ zellij-server/src/panes/terminal_pane.rs | 3 ++ zellij-server/src/tab/mod.rs | 30 +++++++++++++++++-- ...k_floating_plugin_pane_to_a_new_tab-2.snap | 28 ++++++++--------- ...k_floating_plugin_pane_to_a_new_tab-3.snap | 24 +++++++-------- ...k_floating_plugin_pane_to_a_new_tab-5.snap | 26 ++++++++++++++-- ..._can_break_plugin_pane_to_a_new_tab-4.snap | 6 ++-- ..._can_break_plugin_pane_to_a_new_tab-5.snap | 26 ++++++++++++++-- 8 files changed, 109 insertions(+), 37 deletions(-) diff --git a/zellij-server/src/panes/grid.rs b/zellij-server/src/panes/grid.rs index da48422b9..c22cb4808 100644 --- a/zellij-server/src/panes/grid.rs +++ b/zellij-server/src/panes/grid.rs @@ -1142,6 +1142,9 @@ impl Grid { Some((self.cursor.x, self.cursor.y)) } } + pub fn is_mid_frame(&self) -> bool { + self.lock_renders + } /// Clears all buffers with text for a current screen pub fn clear_screen(&mut self) { if self.alternate_screen_state.is_some() { diff --git a/zellij-server/src/panes/terminal_pane.rs b/zellij-server/src/panes/terminal_pane.rs index 3923b1d9c..4df055212 100644 --- a/zellij-server/src/panes/terminal_pane.rs +++ b/zellij-server/src/panes/terminal_pane.rs @@ -193,6 +193,9 @@ impl Pane for TerminalPane { .cursor_coordinates() .map(|(x, y)| (x + left, y + top)) } + fn is_mid_frame(&self) -> bool { + self.grid.is_mid_frame() + } fn adjust_input_to_terminal( &mut self, key_with_modifier: &Option, diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs index 3be998cb3..92e9eeb94 100644 --- a/zellij-server/src/tab/mod.rs +++ b/zellij-server/src/tab/mod.rs @@ -217,6 +217,9 @@ pub trait Pane { fn handle_pty_bytes(&mut self, _bytes: VteBytes) {} fn handle_plugin_bytes(&mut self, _client_id: ClientId, _bytes: VteBytes) {} fn cursor_coordinates(&self) -> Option<(usize, usize)>; + fn is_mid_frame(&self) -> bool { + false + } fn adjust_input_to_terminal( &mut self, _key_with_modifier: &Option, @@ -1866,6 +1869,20 @@ impl Tab { } Ok(should_update_ui) } + pub fn active_terminal_is_mid_frame(&self, client_id: ClientId) -> Option { + let active_pane_id = if self.floating_panes.panes_are_visible() { + self.floating_panes + .get_active_pane_id(client_id) + .or_else(|| self.tiled_panes.get_active_pane_id(client_id))? + } else { + self.tiled_panes.get_active_pane_id(client_id)? + }; + let active_terminal = &self + .floating_panes + .get(&active_pane_id) + .or_else(|| self.tiled_panes.get_pane(active_pane_id))?; + Some(active_terminal.is_mid_frame()) + } pub fn get_active_terminal_cursor_position( &self, client_id: ClientId, @@ -2000,8 +2017,8 @@ impl Tab { .with_context(err_context)?; } + self.render_cursor(output); if output.has_rendered_assets() { - self.render_cursor(output); self.hide_cursor_and_clear_display_as_needed(output); } @@ -2044,8 +2061,17 @@ impl Tab { || previous_shape != &desired_cursor_shape }) .unwrap_or(true); + let active_terminal_is_mid_frame = self + .active_terminal_is_mid_frame(client_id) + .unwrap_or(false); - if output.is_dirty() || cursor_changed_position_or_shape { + if active_terminal_is_mid_frame { + // no-op, this means the active terminal is currently rendering a frame, + // which means the cursor can be jumping around and we definitely do not + // want to render it + // + // (I felt this was clearer than expanding the if conditional below) + } else if output.is_dirty() || cursor_changed_position_or_shape { let show_cursor = "\u{1b}[?25h"; let goto_cursor_position = &format!( "\u{1b}[{};{}H\u{1b}[m{}", diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-2.snap index e12b6aaa0..6e6cd79a3 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-2.snap @@ -1,25 +1,25 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 3501 +assertion_line: 3502 expression: "format!(\"{}\", snapshot)" --- -00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ +00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐ 01 (C): │ │ 02 (C): │ │ 03 (C): │ │ 04 (C): │ │ -05 (C): │ │ -06 (C): │ │ -07 (C): │ ┌ file:/path/to/fake/plugin ───────────┐ │ -08 (C): │ │Loading file:/path/to/fake/plugin │ │ -09 (C): │ │ │ │ -10 (C): │ │ │ │ -11 (C): │ │ │ │ -12 (C): │ │ │ │ -13 (C): │ │ │ │ -14 (C): │ │ │ │ -15 (C): │ │ │ │ -16 (C): │ └──────────────────────────────────────┘ │ +05 (C): │ ┌ file:/path/to/fake/plugin ───────────┐ │ +06 (C): │ │Loading file:/path/to/fake/plugin │ │ +07 (C): │ │ │ │ +08 (C): │ │ │ │ +09 (C): │ │ │ │ +10 (C): │ │ │ │ +11 (C): │ │ │ │ +12 (C): │ │ │ │ +13 (C): │ │ │ │ +14 (C): │ └──────────────────────────────────────┘ │ +15 (C): │ │ +16 (C): │ │ 17 (C): │ │ 18 (C): │ │ 19 (C): └──────────────────────────────────────────────────────────────────────────────┘ diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-3.snap index 652b57260..53ae655ce 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-3.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-3.snap @@ -1,25 +1,25 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 3501 +assertion_line: 3502 expression: "format!(\"{}\", snapshot)" --- -00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐ +00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ 01 (C): │ │ 02 (C): │ │ 03 (C): │ │ 04 (C): │ │ 05 (C): │ │ 06 (C): │ │ -07 (C): │ │ -08 (C): │ │ -09 (C): │ │ -10 (C): │ │ -11 (C): │ │ -12 (C): │ │ -13 (C): │ │ -14 (C): │ │ -15 (C): │ │ -16 (C): │ │ +07 (C): │ ┌ file:/path/to/fake/plugin ───────────┐ │ +08 (C): │ │Loading file:/path/to/fake/plugin │ │ +09 (C): │ │ │ │ +10 (C): │ │ │ │ +11 (C): │ │ │ │ +12 (C): │ │ │ │ +13 (C): │ │ │ │ +14 (C): │ │ │ │ +15 (C): │ │ │ │ +16 (C): │ └──────────────────────────────────────┘ │ 17 (C): │ │ 18 (C): │ │ 19 (C): └──────────────────────────────────────────────────────────────────────────────┘ diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-5.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-5.snap index 78be09770..8fc16e075 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-5.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-5.snap @@ -1,6 +1,26 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 3503 -expression: "format!(\"{}\", snapshot_count)" +assertion_line: 3502 +expression: "format!(\"{}\", snapshot)" --- -4 +00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐ +01 (C): │ │ +02 (C): │ │ +03 (C): │ │ +04 (C): │ │ +05 (C): │ │ +06 (C): │ │ +07 (C): │ │ +08 (C): │ │ +09 (C): │ │ +10 (C): │ │ +11 (C): │ │ +12 (C): │ │ +13 (C): │ │ +14 (C): │ │ +15 (C): │ │ +16 (C): │ │ +17 (C): │ │ +18 (C): │ │ +19 (C): └──────────────────────────────────────────────────────────────────────────────┘ + diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-4.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-4.snap index 2681e18e3..a55bc4d26 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-4.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-4.snap @@ -1,10 +1,10 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 3428 +assertion_line: 3429 expression: "format!(\"{}\", snapshot)" --- -00 (C): ┌ pane_to_stay ────────────────────────────────────────────────────────────────┐ -01 (C): │ │ +00 (C): ┌ plugin_pane_to_break_free ───────────────────────────────────────────────────┐ +01 (C): │Loading file:/path/to/fake/plugin │ 02 (C): │ │ 03 (C): │ │ 04 (C): │ │ diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-5.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-5.snap index 5f701fea2..91a3ecd4e 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-5.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-5.snap @@ -1,6 +1,26 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 3430 -expression: "format!(\"{}\", snapshot_count)" +assertion_line: 3429 +expression: "format!(\"{}\", snapshot)" --- -4 +00 (C): ┌ pane_to_stay ────────────────────────────────────────────────────────────────┐ +01 (C): │ │ +02 (C): │ │ +03 (C): │ │ +04 (C): │ │ +05 (C): │ │ +06 (C): │ │ +07 (C): │ │ +08 (C): │ │ +09 (C): │ │ +10 (C): │ │ +11 (C): │ │ +12 (C): │ │ +13 (C): │ │ +14 (C): │ │ +15 (C): │ │ +16 (C): │ │ +17 (C): │ │ +18 (C): │ │ +19 (C): └──────────────────────────────────────────────────────────────────────────────┘ +