fix(terminal): persist cursor hide/show through alternate screen (#1586)

* fix(terminal): persist cursor hide/show through alternate screen

* style(fmt): rustfmt

* style(clippy): make clippy happy
This commit is contained in:
Aram Drevekenin 2022-07-14 11:55:07 +02:00 committed by GitHub
parent e4b1dd6d4c
commit cbbdccc285
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 5 deletions

View file

@ -305,6 +305,7 @@ pub struct Grid {
horizontal_tabstops: BTreeSet<usize>, horizontal_tabstops: BTreeSet<usize>,
alternate_screen_state: Option<AlternateScreenState>, alternate_screen_state: Option<AlternateScreenState>,
cursor: Cursor, cursor: Cursor,
cursor_is_hidden: bool,
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
// line of the viewport and the bottom line the last unless it's changed with CSI r and friends // line of the viewport and the bottom line the last unless it's changed with CSI r and friends
@ -408,6 +409,7 @@ impl Grid {
lines_below: vec![], lines_below: vec![],
horizontal_tabstops: create_horizontal_tabstops(columns), horizontal_tabstops: create_horizontal_tabstops(columns),
cursor: Cursor::new(0, 0), cursor: Cursor::new(0, 0),
cursor_is_hidden: false,
saved_cursor_position: None, saved_cursor_position: None,
scroll_region: None, scroll_region: None,
preceding_char: None, preceding_char: None,
@ -898,7 +900,7 @@ impl Grid {
(changed_character_chunks, changed_sixel_image_chunks) (changed_character_chunks, changed_sixel_image_chunks)
} }
pub fn cursor_coordinates(&self) -> Option<(usize, usize)> { pub fn cursor_coordinates(&self) -> Option<(usize, usize)> {
if self.cursor.is_hidden { if self.cursor_is_hidden {
None None
} else { } else {
Some((self.cursor.x, self.cursor.y)) Some((self.cursor.x, self.cursor.y))
@ -1309,10 +1311,10 @@ impl Grid {
} }
} }
pub fn hide_cursor(&mut self) { pub fn hide_cursor(&mut self) {
self.cursor.is_hidden = true; self.cursor_is_hidden = true;
} }
pub fn show_cursor(&mut self) { pub fn show_cursor(&mut self) {
self.cursor.is_hidden = false; self.cursor_is_hidden = false;
} }
pub fn set_scroll_region(&mut self, top_line_index: usize, bottom_line_index: Option<usize>) { pub fn set_scroll_region(&mut self, top_line_index: usize, bottom_line_index: Option<usize>) {
let bottom_line_index = bottom_line_index.unwrap_or(self.height); let bottom_line_index = bottom_line_index.unwrap_or(self.height);

View file

@ -672,7 +672,6 @@ pub enum CursorShape {
pub struct Cursor { pub struct Cursor {
pub x: usize, pub x: usize,
pub y: usize, pub y: usize,
pub is_hidden: bool,
pub pending_styles: CharacterStyles, pub pending_styles: CharacterStyles,
pub charsets: Charsets, pub charsets: Charsets,
shape: CursorShape, shape: CursorShape,
@ -683,7 +682,6 @@ impl Cursor {
Cursor { Cursor {
x, x,
y, y,
is_hidden: false,
pending_styles: RESET_STYLES, pending_styles: RESET_STYLES,
charsets: Default::default(), charsets: Default::default(),
shape: CursorShape::Initial, shape: CursorShape::Initial,

View file

@ -2513,3 +2513,54 @@ pub fn xtsmgraphics_pixel_graphics_geometry() {
}); });
assert_eq!(message_string, "\u{1b}[?2;0;776;1071S"); assert_eq!(message_string, "\u{1b}[?2;0;776;1071S");
} }
#[test]
pub fn cursor_hide_persists_through_alternate_screen() {
let mut vte_parser = vte::Parser::new();
let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default()));
let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new()));
let character_cell_size = Rc::new(RefCell::new(Some(SizeInPixels {
width: 8,
height: 21,
})));
let mut grid = Grid::new(
30,
112,
Rc::new(RefCell::new(Palette::default())),
terminal_emulator_color_codes,
Rc::new(RefCell::new(LinkHandler::new())),
character_cell_size,
sixel_image_store,
);
let hide_cursor = "\u{1b}[?25l";
for byte in hide_cursor.as_bytes() {
vte_parser.advance(&mut grid, *byte);
}
assert_eq!(grid.cursor_coordinates(), None, "Cursor hidden properly");
let move_to_alternate_screen = "\u{1b}[?1049h";
for byte in move_to_alternate_screen.as_bytes() {
vte_parser.advance(&mut grid, *byte);
}
assert_eq!(
grid.cursor_coordinates(),
None,
"Cursor still hidden in alternate screen"
);
let show_cursor = "\u{1b}[?25h";
for byte in show_cursor.as_bytes() {
vte_parser.advance(&mut grid, *byte);
}
assert!(grid.cursor_coordinates().is_some(), "Cursor shown");
let move_away_from_alternate_screen = "\u{1b}[?1049l";
for byte in move_away_from_alternate_screen.as_bytes() {
vte_parser.advance(&mut grid, *byte);
}
assert!(
grid.cursor_coordinates().is_some(),
"Cursor still shown away from alternate screen"
);
}