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>,
alternate_screen_state: Option<AlternateScreenState>,
cursor: Cursor,
cursor_is_hidden: bool,
saved_cursor_position: Option<Cursor>,
// 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
@ -408,6 +409,7 @@ impl Grid {
lines_below: vec![],
horizontal_tabstops: create_horizontal_tabstops(columns),
cursor: Cursor::new(0, 0),
cursor_is_hidden: false,
saved_cursor_position: None,
scroll_region: None,
preceding_char: None,
@ -898,7 +900,7 @@ impl Grid {
(changed_character_chunks, changed_sixel_image_chunks)
}
pub fn cursor_coordinates(&self) -> Option<(usize, usize)> {
if self.cursor.is_hidden {
if self.cursor_is_hidden {
None
} else {
Some((self.cursor.x, self.cursor.y))
@ -1309,10 +1311,10 @@ impl Grid {
}
}
pub fn hide_cursor(&mut self) {
self.cursor.is_hidden = true;
self.cursor_is_hidden = true;
}
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>) {
let bottom_line_index = bottom_line_index.unwrap_or(self.height);

View File

@ -672,7 +672,6 @@ pub enum CursorShape {
pub struct Cursor {
pub x: usize,
pub y: usize,
pub is_hidden: bool,
pub pending_styles: CharacterStyles,
pub charsets: Charsets,
shape: CursorShape,
@ -683,7 +682,6 @@ impl Cursor {
Cursor {
x,
y,
is_hidden: false,
pending_styles: RESET_STYLES,
charsets: Default::default(),
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");
}
#[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"
);
}