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:
parent
e4b1dd6d4c
commit
cbbdccc285
3 changed files with 56 additions and 5 deletions
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue