fix(grid): glitchy resizes (#2182)

* fix(grid): glitchy resizes

* style(fmt): rustfmt
This commit is contained in:
Aram Drevekenin 2023-02-20 17:36:31 +01:00 committed by GitHub
parent df839fe947
commit 0101440cbb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 7 deletions

View file

@ -626,6 +626,27 @@ impl Grid {
} }
cursor_index_in_canonical_line cursor_index_in_canonical_line
} }
fn saved_cursor_index_in_canonical_line(&self) -> Option<usize> {
if let Some(saved_cursor_position) = self.saved_cursor_position.as_ref() {
let mut cursor_canonical_line_index = 0;
let mut cursor_index_in_canonical_line = 0;
for (i, line) in self.viewport.iter().enumerate() {
if line.is_canonical {
cursor_canonical_line_index = i;
}
if i == saved_cursor_position.y {
let line_wrap_position_in_line =
saved_cursor_position.y - cursor_canonical_line_index;
cursor_index_in_canonical_line =
line_wrap_position_in_line + saved_cursor_position.x;
break;
}
}
Some(cursor_index_in_canonical_line)
} else {
None
}
}
fn canonical_line_y_coordinates(&self, canonical_line_index: usize) -> usize { fn canonical_line_y_coordinates(&self, canonical_line_index: usize) -> usize {
let mut canonical_lines_traversed = 0; let mut canonical_lines_traversed = 0;
let mut y_coordinates = 0; let mut y_coordinates = 0;
@ -713,7 +734,7 @@ impl Grid {
} }
found_something found_something
} }
fn force_change_size(&mut self, new_rows: usize, new_columns: usize) { pub fn force_change_size(&mut self, new_rows: usize, new_columns: usize) {
// this is an ugly hack - it's here because sometimes we need to change_size to the // this is an ugly hack - it's here because sometimes we need to change_size to the
// existing size (eg. when resizing an alternative_grid to the current height/width) and // existing size (eg. when resizing an alternative_grid to the current height/width) and
// the change_size method is a no-op in that case. Should be fixed by making the // the change_size method is a no-op in that case. Should be fixed by making the
@ -742,6 +763,7 @@ impl Grid {
self.horizontal_tabstops = create_horizontal_tabstops(new_columns); self.horizontal_tabstops = create_horizontal_tabstops(new_columns);
let mut cursor_canonical_line_index = self.cursor_canonical_line_index(); let mut cursor_canonical_line_index = self.cursor_canonical_line_index();
let cursor_index_in_canonical_line = self.cursor_index_in_canonical_line(); let cursor_index_in_canonical_line = self.cursor_index_in_canonical_line();
let saved_cursor_index_in_canonical_line = self.saved_cursor_index_in_canonical_line();
let mut viewport_canonical_lines = vec![]; let mut viewport_canonical_lines = vec![];
for mut row in self.viewport.drain(..) { for mut row in self.viewport.drain(..) {
if !row.is_canonical if !row.is_canonical
@ -817,9 +839,25 @@ impl Grid {
self.viewport = new_viewport_rows; self.viewport = new_viewport_rows;
let mut new_cursor_y = self.canonical_line_y_coordinates(cursor_canonical_line_index); let mut new_cursor_y = self.canonical_line_y_coordinates(cursor_canonical_line_index);
let mut saved_cursor_y_coordinates =
if let Some(saved_cursor) = self.saved_cursor_position.as_ref() {
Some(self.canonical_line_y_coordinates(saved_cursor.y))
} else {
None
};
let new_cursor_x = (cursor_index_in_canonical_line / new_columns) let new_cursor_x = (cursor_index_in_canonical_line / new_columns)
+ (cursor_index_in_canonical_line % new_columns); + (cursor_index_in_canonical_line % new_columns);
let saved_cursor_x_coordinates = if let Some(saved_cursor_index_in_canonical_line) =
saved_cursor_index_in_canonical_line.as_ref()
{
Some(
(*saved_cursor_index_in_canonical_line / new_columns)
+ (*saved_cursor_index_in_canonical_line % new_columns),
)
} else {
None
};
let current_viewport_row_count = self.viewport.len(); let current_viewport_row_count = self.viewport.len();
match current_viewport_row_count.cmp(&self.height) { match current_viewport_row_count.cmp(&self.height) {
Ordering::Less => { Ordering::Less => {
@ -834,6 +872,9 @@ impl Grid {
); );
let rows_pulled = self.viewport.len() - current_viewport_row_count; let rows_pulled = self.viewport.len() - current_viewport_row_count;
new_cursor_y += rows_pulled; new_cursor_y += rows_pulled;
if let Some(saved_cursor_y_coordinates) = saved_cursor_y_coordinates.as_mut() {
*saved_cursor_y_coordinates += rows_pulled;
}
}, },
Ordering::Greater => { Ordering::Greater => {
let row_count_to_transfer = current_viewport_row_count - self.height; let row_count_to_transfer = current_viewport_row_count - self.height;
@ -842,6 +883,13 @@ impl Grid {
} else { } else {
new_cursor_y -= row_count_to_transfer; new_cursor_y -= row_count_to_transfer;
} }
if let Some(saved_cursor_y_coordinates) = saved_cursor_y_coordinates.as_mut() {
if row_count_to_transfer > *saved_cursor_y_coordinates {
*saved_cursor_y_coordinates = 0;
} else {
*saved_cursor_y_coordinates -= row_count_to_transfer;
}
}
transfer_rows_from_viewport_to_lines_above( transfer_rows_from_viewport_to_lines_above(
&mut self.viewport, &mut self.viewport,
&mut self.lines_above, &mut self.lines_above,
@ -855,8 +903,16 @@ impl Grid {
self.cursor.y = new_cursor_y; self.cursor.y = new_cursor_y;
self.cursor.x = new_cursor_x; self.cursor.x = new_cursor_x;
if let Some(saved_cursor_position) = self.saved_cursor_position.as_mut() { if let Some(saved_cursor_position) = self.saved_cursor_position.as_mut() {
saved_cursor_position.y = new_cursor_y; match (saved_cursor_x_coordinates, saved_cursor_y_coordinates) {
(Some(saved_cursor_x_coordinates), Some(saved_cursor_y_coordinates)) => {
saved_cursor_position.x = saved_cursor_x_coordinates;
saved_cursor_position.y = saved_cursor_y_coordinates;
},
_ => {
saved_cursor_position.x = new_cursor_x; saved_cursor_position.x = new_cursor_x;
saved_cursor_position.y = new_cursor_y;
},
}
}; };
} else if new_columns != self.width && self.alternate_screen_state.is_some() { } else if new_columns != self.width && self.alternate_screen_state.is_some() {
// in alternate screen just truncate exceeding width // in alternate screen just truncate exceeding width

View file

@ -794,7 +794,7 @@ impl TerminalPane {
fn reflow_lines(&mut self) { fn reflow_lines(&mut self) {
let rows = self.get_content_rows(); let rows = self.get_content_rows();
let cols = self.get_content_columns(); let cols = self.get_content_columns();
self.grid.change_size(rows, cols); self.grid.force_change_size(rows, cols);
if self.banner.is_some() { if self.banner.is_some() {
self.grid.reset_terminal_state(); self.grid.reset_terminal_state();
self.render_first_run_banner(); self.render_first_run_banner();

View file

@ -1,10 +1,10 @@
--- ---
source: zellij-server/src/tab/./unit/tab_integration_tests.rs source: zellij-server/src/tab/./unit/tab_integration_tests.rs
assertion_line: 1153 assertion_line: 1952
expression: snapshot expression: snapshot
--- ---
00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────────── SCROLL: 0/4 ┐ 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────────── SCROLL: 0/4 ┐
01 (C): │ Let's save the cursor position here this overwrote me!tten │ 01 (C): │Let's save the cursor position here this overwrote me!tten
02 (C): └──────────────────────────────────────────────────────────────────────────────────────────────────┘ 02 (C): └──────────────────────────────────────────────────────────────────────────────────────────────────┘
03 (C): 03 (C):
04 (C): 04 (C):

View file

@ -1935,7 +1935,7 @@ fn save_cursor_position_across_resizes() {
tab.handle_pty_bytes( tab.handle_pty_bytes(
1, 1,
Vec::from("\n\nI am some text\nI am another line of text\nLet's save the cursor position here \u{1b}[sI should be ovewritten".as_bytes()), Vec::from("\n\n\rI am some text\n\rI am another line of text\n\rLet's save the cursor position here \u{1b}[sI should be ovewritten".as_bytes()),
).unwrap(); ).unwrap();
tab.resize_whole_tab(Size { cols: 100, rows: 3 }).unwrap(); tab.resize_whole_tab(Size { cols: 100, rows: 3 }).unwrap();
tab.handle_pty_bytes(1, Vec::from("\u{1b}[uthis overwrote me!".as_bytes())) tab.handle_pty_bytes(1, Vec::from("\u{1b}[uthis overwrote me!".as_bytes()))