fix(terminal): properly cache cursor position for synchronized renders (#3483)

* fix(terminal): properly cache cursor position for synchronized renders

* style(fmt): rustfmt
This commit is contained in:
Aram Drevekenin 2024-07-08 14:30:31 +02:00 committed by GitHub
parent c886af41c2
commit ffca97f5a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 109 additions and 37 deletions

View File

@ -1142,6 +1142,9 @@ impl Grid {
Some((self.cursor.x, self.cursor.y)) 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 /// Clears all buffers with text for a current screen
pub fn clear_screen(&mut self) { pub fn clear_screen(&mut self) {
if self.alternate_screen_state.is_some() { if self.alternate_screen_state.is_some() {

View File

@ -193,6 +193,9 @@ impl Pane for TerminalPane {
.cursor_coordinates() .cursor_coordinates()
.map(|(x, y)| (x + left, y + top)) .map(|(x, y)| (x + left, y + top))
} }
fn is_mid_frame(&self) -> bool {
self.grid.is_mid_frame()
}
fn adjust_input_to_terminal( fn adjust_input_to_terminal(
&mut self, &mut self,
key_with_modifier: &Option<KeyWithModifier>, key_with_modifier: &Option<KeyWithModifier>,

View File

@ -217,6 +217,9 @@ pub trait Pane {
fn handle_pty_bytes(&mut self, _bytes: VteBytes) {} fn handle_pty_bytes(&mut self, _bytes: VteBytes) {}
fn handle_plugin_bytes(&mut self, _client_id: ClientId, _bytes: VteBytes) {} fn handle_plugin_bytes(&mut self, _client_id: ClientId, _bytes: VteBytes) {}
fn cursor_coordinates(&self) -> Option<(usize, usize)>; fn cursor_coordinates(&self) -> Option<(usize, usize)>;
fn is_mid_frame(&self) -> bool {
false
}
fn adjust_input_to_terminal( fn adjust_input_to_terminal(
&mut self, &mut self,
_key_with_modifier: &Option<KeyWithModifier>, _key_with_modifier: &Option<KeyWithModifier>,
@ -1866,6 +1869,20 @@ impl Tab {
} }
Ok(should_update_ui) Ok(should_update_ui)
} }
pub fn active_terminal_is_mid_frame(&self, client_id: ClientId) -> Option<bool> {
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( pub fn get_active_terminal_cursor_position(
&self, &self,
client_id: ClientId, client_id: ClientId,
@ -2000,8 +2017,8 @@ impl Tab {
.with_context(err_context)?; .with_context(err_context)?;
} }
self.render_cursor(output);
if output.has_rendered_assets() { if output.has_rendered_assets() {
self.render_cursor(output);
self.hide_cursor_and_clear_display_as_needed(output); self.hide_cursor_and_clear_display_as_needed(output);
} }
@ -2044,8 +2061,17 @@ impl Tab {
|| previous_shape != &desired_cursor_shape || previous_shape != &desired_cursor_shape
}) })
.unwrap_or(true); .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 show_cursor = "\u{1b}[?25h";
let goto_cursor_position = &format!( let goto_cursor_position = &format!(
"\u{1b}[{};{}H\u{1b}[m{}", "\u{1b}[{};{}H\u{1b}[m{}",

View File

@ -1,25 +1,25 @@
--- ---
source: zellij-server/src/./unit/screen_tests.rs source: zellij-server/src/./unit/screen_tests.rs
assertion_line: 3501 assertion_line: 3502
expression: "format!(\"{}\", snapshot)" expression: "format!(\"{}\", snapshot)"
--- ---
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ 00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐
01 (C): │ │ 01 (C): │ │
02 (C): │ │ 02 (C): │ │
03 (C): │ │ 03 (C): │ │
04 (C): │ │ 04 (C): │ │
05 (C): │ 05 (C): │ ┌ file:/path/to/fake/plugin ───────────┐
06 (C): │ 06 (C): │ │Loading file:/path/to/fake/plugin │
07 (C): │ ┌ file:/path/to/fake/plugin ───────────┐ 07 (C): │ │ │
08 (C): │ │Loading file:/path/to/fake/plugin │ 08 (C): │ │ │
09 (C): │ │ │ │ 09 (C): │ │ │
10 (C): │ │ │ │ 10 (C): │ │ │
11 (C): │ │ │ │ 11 (C): │ │ │
12 (C): │ │ │ │ 12 (C): │ │ │
13 (C): │ │ │ │ 13 (C): │ │ │
14 (C): │ │ │ 14 (C): │ └──────────────────────────────────────┘
15 (C): │ │ │ 15 (C): │
16 (C): │ └──────────────────────────────────────┘ 16 (C): │
17 (C): │ │ 17 (C): │ │
18 (C): │ │ 18 (C): │ │
19 (C): └──────────────────────────────────────────────────────────────────────────────┘ 19 (C): └──────────────────────────────────────────────────────────────────────────────┘

View File

@ -1,25 +1,25 @@
--- ---
source: zellij-server/src/./unit/screen_tests.rs source: zellij-server/src/./unit/screen_tests.rs
assertion_line: 3501 assertion_line: 3502
expression: "format!(\"{}\", snapshot)" expression: "format!(\"{}\", snapshot)"
--- ---
00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐ 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐
01 (C): │ │ 01 (C): │ │
02 (C): │ │ 02 (C): │ │
03 (C): │ │ 03 (C): │ │
04 (C): │ │ 04 (C): │ │
05 (C): │ │ 05 (C): │ │
06 (C): │ │ 06 (C): │ │
07 (C): │ 07 (C): │ ┌ file:/path/to/fake/plugin ───────────┐
08 (C): │ 08 (C): │ │Loading file:/path/to/fake/plugin │
09 (C): │ 09 (C): │ │ │
10 (C): │ 10 (C): │ │ │
11 (C): │ 11 (C): │ │ │
12 (C): │ 12 (C): │ │ │
13 (C): │ 13 (C): │ │ │
14 (C): │ 14 (C): │ │ │
15 (C): │ 15 (C): │ │ │
16 (C): │ 16 (C): │ └──────────────────────────────────────┘
17 (C): │ │ 17 (C): │ │
18 (C): │ │ 18 (C): │ │
19 (C): └──────────────────────────────────────────────────────────────────────────────┘ 19 (C): └──────────────────────────────────────────────────────────────────────────────┘

View File

@ -1,6 +1,26 @@
--- ---
source: zellij-server/src/./unit/screen_tests.rs source: zellij-server/src/./unit/screen_tests.rs
assertion_line: 3503 assertion_line: 3502
expression: "format!(\"{}\", snapshot_count)" 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): └──────────────────────────────────────────────────────────────────────────────┘

View File

@ -1,10 +1,10 @@
--- ---
source: zellij-server/src/./unit/screen_tests.rs source: zellij-server/src/./unit/screen_tests.rs
assertion_line: 3428 assertion_line: 3429
expression: "format!(\"{}\", snapshot)" expression: "format!(\"{}\", snapshot)"
--- ---
00 (C): ┌ pane_to_stay ────────────────────────────────────────────────────────────────┐ 00 (C): ┌ plugin_pane_to_break_free ───────────────────────────────────────────────────┐
01 (C): │ 01 (C): │Loading file:/path/to/fake/plugin
02 (C): │ │ 02 (C): │ │
03 (C): │ │ 03 (C): │ │
04 (C): │ │ 04 (C): │ │

View File

@ -1,6 +1,26 @@
--- ---
source: zellij-server/src/./unit/screen_tests.rs source: zellij-server/src/./unit/screen_tests.rs
assertion_line: 3430 assertion_line: 3429
expression: "format!(\"{}\", snapshot_count)" 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): └──────────────────────────────────────────────────────────────────────────────┘