fix(compatibility): do not set scroll buffer in alternate screen (#1032)
avoid moving lines to lines_above when in alternate screen. adjust resizing when in alternate screen: * remove extra lines instead of sending to lines_above * truncate excess characters
This commit is contained in:
parent
0737a5a215
commit
143bbfb0bb
4 changed files with 117 additions and 56 deletions
21
src/tests/fixtures/alternate_screen_change_size
vendored
Normal file
21
src/tests/fixtures/alternate_screen_change_size
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
[?1049hline1aaaaaaaaaaaaaaa
|
||||||
|
line2aaaaaaaaaaaaaaa
|
||||||
|
line3aaaaaaaaaaaaaaa
|
||||||
|
line4aaaaaaaaaaaaaaa
|
||||||
|
line5aaaaaaaaaaaaaaa
|
||||||
|
line6aaaaaaaaaaaaaaa
|
||||||
|
line7aaaaaaaaaaaaaaa
|
||||||
|
line8aaaaaaaaaaaaaaa
|
||||||
|
line9aaaaaaaaaaaaaaa
|
||||||
|
line10aaaaaaaaaaaaaa
|
||||||
|
line11aaaaaaaaaaaaaa
|
||||||
|
line12aaaaaaaaaaaaaa
|
||||||
|
line13aaaaaaaaaaaaaa
|
||||||
|
line14aaaaaaaaaaaaaa
|
||||||
|
line15aaaaaaaaaaaaaa
|
||||||
|
line16aaaaaaaaaaaaaa
|
||||||
|
line17aaaaaaaaaaaaaa
|
||||||
|
line18aaaaaaaaaaaaaa
|
||||||
|
line19a🦀aaaaaaaaaaa
|
||||||
|
line20a🦀🦀aaaaaaaaa
|
||||||
|
line21🦀🦀🦀🦀🦀🦀🦀
|
||||||
|
|
@ -374,7 +374,7 @@ pub struct Grid {
|
||||||
viewport: Vec<Row>,
|
viewport: Vec<Row>,
|
||||||
lines_below: Vec<Row>,
|
lines_below: Vec<Row>,
|
||||||
horizontal_tabstops: BTreeSet<usize>,
|
horizontal_tabstops: BTreeSet<usize>,
|
||||||
alternative_lines_above_viewport_and_cursor: Option<(VecDeque<Row>, Vec<Row>, Cursor)>,
|
alternate_lines_above_viewport_and_cursor: Option<(VecDeque<Row>, Vec<Row>, Cursor)>,
|
||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
saved_cursor_position: Option<Cursor>,
|
saved_cursor_position: Option<Cursor>,
|
||||||
// FIXME: change scroll_region to be (usize, usize) - where the top line is always the first
|
// FIXME: change scroll_region to be (usize, usize) - where the top line is always the first
|
||||||
|
|
@ -442,7 +442,7 @@ impl Grid {
|
||||||
erasure_mode: false,
|
erasure_mode: false,
|
||||||
insert_mode: false,
|
insert_mode: false,
|
||||||
disable_linewrap: false,
|
disable_linewrap: false,
|
||||||
alternative_lines_above_viewport_and_cursor: None,
|
alternate_lines_above_viewport_and_cursor: None,
|
||||||
clear_viewport_before_rendering: false,
|
clear_viewport_before_rendering: false,
|
||||||
active_charset: Default::default(),
|
active_charset: Default::default(),
|
||||||
pending_messages_to_pty: vec![],
|
pending_messages_to_pty: vec![],
|
||||||
|
|
@ -673,7 +673,7 @@ impl Grid {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.selection.reset();
|
self.selection.reset();
|
||||||
if new_columns != self.width {
|
if new_columns != self.width && self.alternate_lines_above_viewport_and_cursor.is_none() {
|
||||||
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();
|
||||||
|
|
@ -786,6 +786,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;
|
||||||
|
} else if new_columns != self.width
|
||||||
|
&& self.alternate_lines_above_viewport_and_cursor.is_some()
|
||||||
|
{
|
||||||
|
// in alternate screen just truncate exceeding width
|
||||||
|
for row in &mut self.viewport {
|
||||||
|
if row.width() >= new_columns {
|
||||||
|
let truncate_at = row.position_accounting_for_widechars(new_columns);
|
||||||
|
row.columns.truncate(truncate_at);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if new_rows != self.height {
|
if new_rows != self.height {
|
||||||
let current_viewport_row_count = self.viewport.len();
|
let current_viewport_row_count = self.viewport.len();
|
||||||
|
|
@ -808,12 +818,17 @@ impl Grid {
|
||||||
} else {
|
} else {
|
||||||
self.cursor.y -= row_count_to_transfer;
|
self.cursor.y -= row_count_to_transfer;
|
||||||
}
|
}
|
||||||
|
if self.alternate_lines_above_viewport_and_cursor.is_none() {
|
||||||
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,
|
||||||
row_count_to_transfer,
|
row_count_to_transfer,
|
||||||
new_columns,
|
new_columns,
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
// in alternate screen, no scroll buffer, so just remove lines
|
||||||
|
self.viewport.drain(0..row_count_to_transfer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ordering::Equal => {}
|
Ordering::Equal => {}
|
||||||
}
|
}
|
||||||
|
|
@ -916,16 +931,11 @@ impl Grid {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn fill_viewport(&mut self, character: TerminalCharacter) {
|
pub fn fill_viewport(&mut self, character: TerminalCharacter) {
|
||||||
let row_count_to_transfer = self.viewport.len();
|
if self.alternate_lines_above_viewport_and_cursor.is_some() {
|
||||||
let transferred_rows_count = transfer_rows_from_viewport_to_lines_above(
|
self.viewport.clear();
|
||||||
&mut self.viewport,
|
} else {
|
||||||
&mut self.lines_above,
|
self.transfer_rows_to_lines_above(self.viewport.len())
|
||||||
row_count_to_transfer,
|
};
|
||||||
self.width,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.scrollback_buffer_lines =
|
|
||||||
subtract_isize_from_usize(self.scrollback_buffer_lines, transferred_rows_count);
|
|
||||||
|
|
||||||
for _ in 0..self.height {
|
for _ in 0..self.height {
|
||||||
let columns = VecDeque::from(vec![character; self.width]);
|
let columns = VecDeque::from(vec![character; self.width]);
|
||||||
|
|
@ -947,17 +957,12 @@ impl Grid {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if scroll_region_bottom == self.height - 1 && scroll_region_top == 0 {
|
if scroll_region_bottom == self.height - 1 && scroll_region_top == 0 {
|
||||||
let row_count_to_transfer = 1;
|
if self.alternate_lines_above_viewport_and_cursor.is_none() {
|
||||||
let transferred_rows_count = transfer_rows_from_viewport_to_lines_above(
|
self.transfer_rows_to_lines_above(1);
|
||||||
&mut self.viewport,
|
} else {
|
||||||
&mut self.lines_above,
|
self.viewport.remove(0);
|
||||||
row_count_to_transfer,
|
}
|
||||||
self.width,
|
|
||||||
);
|
|
||||||
self.scrollback_buffer_lines = subtract_isize_from_usize(
|
|
||||||
self.scrollback_buffer_lines,
|
|
||||||
transferred_rows_count,
|
|
||||||
);
|
|
||||||
let columns = VecDeque::from(vec![EMPTY_TERMINAL_CHARACTER; self.width]);
|
let columns = VecDeque::from(vec![EMPTY_TERMINAL_CHARACTER; self.width]);
|
||||||
self.viewport.push(Row::from_columns(columns).canonical());
|
self.viewport.push(Row::from_columns(columns).canonical());
|
||||||
self.selection.move_up(1);
|
self.selection.move_up(1);
|
||||||
|
|
@ -984,15 +989,11 @@ impl Grid {
|
||||||
}
|
}
|
||||||
if self.cursor.y == self.height - 1 {
|
if self.cursor.y == self.height - 1 {
|
||||||
if self.scroll_region.is_none() {
|
if self.scroll_region.is_none() {
|
||||||
let row_count_to_transfer = 1;
|
if self.alternate_lines_above_viewport_and_cursor.is_none() {
|
||||||
let transferred_rows_count = transfer_rows_from_viewport_to_lines_above(
|
self.transfer_rows_to_lines_above(1);
|
||||||
&mut self.viewport,
|
} else {
|
||||||
&mut self.lines_above,
|
self.viewport.remove(0);
|
||||||
row_count_to_transfer,
|
}
|
||||||
self.width,
|
|
||||||
);
|
|
||||||
self.scrollback_buffer_lines =
|
|
||||||
subtract_isize_from_usize(self.scrollback_buffer_lines, transferred_rows_count);
|
|
||||||
|
|
||||||
self.selection.move_up(1);
|
self.selection.move_up(1);
|
||||||
}
|
}
|
||||||
|
|
@ -1062,15 +1063,11 @@ impl Grid {
|
||||||
// line wrap
|
// line wrap
|
||||||
self.cursor.x = 0;
|
self.cursor.x = 0;
|
||||||
if self.cursor.y == self.height - 1 {
|
if self.cursor.y == self.height - 1 {
|
||||||
let row_count_to_transfer = 1;
|
if self.alternate_lines_above_viewport_and_cursor.is_none() {
|
||||||
let transferred_rows_count = transfer_rows_from_viewport_to_lines_above(
|
self.transfer_rows_to_lines_above(1);
|
||||||
&mut self.viewport,
|
} else {
|
||||||
&mut self.lines_above,
|
self.viewport.remove(0);
|
||||||
row_count_to_transfer,
|
}
|
||||||
self.width,
|
|
||||||
);
|
|
||||||
self.scrollback_buffer_lines =
|
|
||||||
subtract_isize_from_usize(self.scrollback_buffer_lines, transferred_rows_count);
|
|
||||||
let wrapped_row = Row::new(self.width);
|
let wrapped_row = Row::new(self.width);
|
||||||
self.viewport.push(wrapped_row);
|
self.viewport.push(wrapped_row);
|
||||||
self.selection.move_up(1);
|
self.selection.move_up(1);
|
||||||
|
|
@ -1365,7 +1362,7 @@ impl Grid {
|
||||||
self.lines_above = VecDeque::with_capacity(*SCROLL_BUFFER_SIZE.get().unwrap());
|
self.lines_above = VecDeque::with_capacity(*SCROLL_BUFFER_SIZE.get().unwrap());
|
||||||
self.lines_below = vec![];
|
self.lines_below = vec![];
|
||||||
self.viewport = vec![Row::new(self.width).canonical()];
|
self.viewport = vec![Row::new(self.width).canonical()];
|
||||||
self.alternative_lines_above_viewport_and_cursor = None;
|
self.alternate_lines_above_viewport_and_cursor = None;
|
||||||
self.cursor_key_mode = false;
|
self.cursor_key_mode = false;
|
||||||
self.scroll_region = None;
|
self.scroll_region = None;
|
||||||
self.clear_viewport_before_rendering = true;
|
self.clear_viewport_before_rendering = true;
|
||||||
|
|
@ -1501,6 +1498,17 @@ impl Grid {
|
||||||
self.title = Some(popped_title);
|
self.title = Some(popped_title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn transfer_rows_to_lines_above(&mut self, count: usize) {
|
||||||
|
let transferred_rows_count = transfer_rows_from_viewport_to_lines_above(
|
||||||
|
&mut self.viewport,
|
||||||
|
&mut self.lines_above,
|
||||||
|
count,
|
||||||
|
self.width,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.scrollback_buffer_lines =
|
||||||
|
subtract_isize_from_usize(self.scrollback_buffer_lines, transferred_rows_count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Perform for Grid {
|
impl Perform for Grid {
|
||||||
|
|
@ -1805,17 +1813,18 @@ impl Perform for Grid {
|
||||||
self.bracketed_paste_mode = false;
|
self.bracketed_paste_mode = false;
|
||||||
}
|
}
|
||||||
Some(1049) => {
|
Some(1049) => {
|
||||||
|
// leave alternate buffer
|
||||||
if let Some((
|
if let Some((
|
||||||
alternative_lines_above,
|
alternative_lines_above,
|
||||||
alternative_viewport,
|
alternative_viewport,
|
||||||
alternative_cursor,
|
alternative_cursor,
|
||||||
)) = &mut self.alternative_lines_above_viewport_and_cursor
|
)) = &mut self.alternate_lines_above_viewport_and_cursor
|
||||||
{
|
{
|
||||||
std::mem::swap(&mut self.lines_above, alternative_lines_above);
|
std::mem::swap(&mut self.lines_above, alternative_lines_above);
|
||||||
std::mem::swap(&mut self.viewport, alternative_viewport);
|
std::mem::swap(&mut self.viewport, alternative_viewport);
|
||||||
std::mem::swap(&mut self.cursor, alternative_cursor);
|
std::mem::swap(&mut self.cursor, alternative_cursor);
|
||||||
}
|
}
|
||||||
self.alternative_lines_above_viewport_and_cursor = None;
|
self.alternate_lines_above_viewport_and_cursor = None;
|
||||||
self.clear_viewport_before_rendering = true;
|
self.clear_viewport_before_rendering = true;
|
||||||
self.force_change_size(self.height, self.width); // the alternative_viewport might have been of a different size...
|
self.force_change_size(self.height, self.width); // the alternative_viewport might have been of a different size...
|
||||||
self.mark_for_rerender();
|
self.mark_for_rerender();
|
||||||
|
|
@ -1861,18 +1870,17 @@ impl Perform for Grid {
|
||||||
self.bracketed_paste_mode = true;
|
self.bracketed_paste_mode = true;
|
||||||
}
|
}
|
||||||
Some(1049) => {
|
Some(1049) => {
|
||||||
|
// enter alternate buffer
|
||||||
let current_lines_above = std::mem::replace(
|
let current_lines_above = std::mem::replace(
|
||||||
&mut self.lines_above,
|
&mut self.lines_above,
|
||||||
VecDeque::with_capacity(*SCROLL_BUFFER_SIZE.get().unwrap()),
|
VecDeque::with_capacity(*SCROLL_BUFFER_SIZE.get().unwrap()),
|
||||||
);
|
);
|
||||||
let current_viewport = std::mem::replace(
|
let current_viewport = std::mem::take(&mut self.viewport);
|
||||||
&mut self.viewport,
|
|
||||||
vec![Row::new(self.width).canonical()],
|
|
||||||
);
|
|
||||||
let current_cursor = std::mem::replace(&mut self.cursor, Cursor::new(0, 0));
|
let current_cursor = std::mem::replace(&mut self.cursor, Cursor::new(0, 0));
|
||||||
self.alternative_lines_above_viewport_and_cursor =
|
self.alternate_lines_above_viewport_and_cursor =
|
||||||
Some((current_lines_above, current_viewport, current_cursor));
|
Some((current_lines_above, current_viewport, current_cursor));
|
||||||
self.clear_viewport_before_rendering = true;
|
self.clear_viewport_before_rendering = true;
|
||||||
|
self.scrollback_buffer_lines = self.recalculate_scrollback_buffer_count();
|
||||||
}
|
}
|
||||||
Some(1) => {
|
Some(1) => {
|
||||||
self.cursor_key_mode = true;
|
self.cursor_key_mode = true;
|
||||||
|
|
|
||||||
|
|
@ -1090,3 +1090,19 @@ pub fn ring_bell() {
|
||||||
}
|
}
|
||||||
assert!(grid.ring_bell);
|
assert!(grid.ring_bell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn alternate_screen_change_size() {
|
||||||
|
let mut vte_parser = vte::Parser::new();
|
||||||
|
let mut grid = Grid::new(20, 20, Palette::default());
|
||||||
|
let fixture_name = "alternate_screen_change_size";
|
||||||
|
let content = read_fixture(fixture_name);
|
||||||
|
for byte in content {
|
||||||
|
vte_parser.advance(&mut grid, byte);
|
||||||
|
}
|
||||||
|
// no scrollback in alternate screen
|
||||||
|
assert_eq!(grid.scrollback_position_and_length(), (0, 0));
|
||||||
|
grid.change_size(10, 10);
|
||||||
|
assert_snapshot!(format!("{:?}", grid));
|
||||||
|
assert_eq!(grid.scrollback_position_and_length(), (0, 0))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
source: zellij-server/src/panes/./unit/grid_tests.rs
|
||||||
|
expression: "format!(\"{:?}\", grid)"
|
||||||
|
|
||||||
|
---
|
||||||
|
00 (C): line12aaaa
|
||||||
|
01 (C): line13aaaa
|
||||||
|
02 (C): line14aaaa
|
||||||
|
03 (C): line15aaaa
|
||||||
|
04 (C): line16aaaa
|
||||||
|
05 (C): line17aaaa
|
||||||
|
06 (C): line18aaaa
|
||||||
|
07 (C): line19a🦀a
|
||||||
|
08 (C): line20a🦀
|
||||||
|
09 (C): line21🦀🦀
|
||||||
|
|
||||||
Loading…
Add table
Reference in a new issue