mirror of
https://github.com/wez/wezterm.git
synced 2024-12-26 23:04:49 +03:00
term: fixup cursor position during rewrap
refs: https://github.com/wez/wezterm/issues/2162
This commit is contained in:
parent
8eb44b43b3
commit
4bf89e0c10
@ -105,7 +105,7 @@ impl Screen {
|
||||
let mut rewrapped = VecDeque::new();
|
||||
let mut logical_line: Option<Line> = None;
|
||||
let mut logical_cursor_x: Option<usize> = None;
|
||||
let mut adjusted_cursor = (cursor_y, cursor_y);
|
||||
let mut adjusted_cursor = (cursor_x, cursor_y);
|
||||
|
||||
for (phys_idx, mut line) in self.lines.drain(..).enumerate() {
|
||||
line.update_last_change_seqno(seqno);
|
||||
@ -140,6 +140,25 @@ impl Screen {
|
||||
let num_lines = x / physical_cols;
|
||||
let last_x = x - (num_lines * physical_cols);
|
||||
adjusted_cursor = (last_x, rewrapped.len() + num_lines);
|
||||
|
||||
// Special case: if the cursor lands in column zero, we'll
|
||||
// lose track of its logical association with the wrapped
|
||||
// line and it won't resize with the line correctly.
|
||||
// Put it back on the prior line. The cursor is now
|
||||
// technically outside of the viewport width.
|
||||
if adjusted_cursor.0 == 0 && adjusted_cursor.1 > 0 {
|
||||
if physical_cols < self.physical_cols {
|
||||
// getting smaller: preserve its original position
|
||||
// on the prior line
|
||||
adjusted_cursor.0 = cursor_x;
|
||||
} else {
|
||||
// getting larger; we were most likely in column 1
|
||||
// or somewhere close. Jump to the end of the
|
||||
// prior line.
|
||||
adjusted_cursor.0 = physical_cols;
|
||||
}
|
||||
adjusted_cursor.1 -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if line.len() <= physical_cols {
|
||||
|
@ -914,7 +914,11 @@ impl TerminalState {
|
||||
if self.dec_origin_mode {
|
||||
self.left_and_right_margins.end
|
||||
} else {
|
||||
self.screen().physical_cols
|
||||
// We allow 1 extra for the cursor x position
|
||||
// to account for some resize/rewrap scenarios
|
||||
// where we don't want to forget that the
|
||||
// cursor belongs to a wrapped line
|
||||
self.screen().physical_cols + 1
|
||||
} as i64
|
||||
- 1,
|
||||
)
|
||||
|
@ -298,7 +298,7 @@ fn test_cup() {
|
||||
term.cup(-1, -1);
|
||||
term.assert_cursor_pos(0, 0, None, None);
|
||||
term.cup(500, 500);
|
||||
term.assert_cursor_pos(3, 2, None, None);
|
||||
term.assert_cursor_pos(4, 2, None, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -313,7 +313,7 @@ fn test_hvp() {
|
||||
term.hvp(-1, -1);
|
||||
term.assert_cursor_pos(0, 0, None, None);
|
||||
term.hvp(500, 500);
|
||||
term.assert_cursor_pos(3, 2, None, None);
|
||||
term.assert_cursor_pos(4, 2, None, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -354,7 +354,7 @@ fn test_cha() {
|
||||
term.assert_cursor_pos(0, 1, None, Some(seqno));
|
||||
|
||||
term.print("\x1b[100G");
|
||||
term.assert_cursor_pos(3, 1, None, None);
|
||||
term.assert_cursor_pos(4, 1, None, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -756,6 +756,162 @@ fn test_dec_double_width() {
|
||||
assert!(lines[3].is_single_width());
|
||||
}
|
||||
|
||||
/// This test skips over an edge case with cursor positioning,
|
||||
/// while sizing down, but tries to trip over the same edge
|
||||
/// case while sizing back up again
|
||||
#[test]
|
||||
fn test_resize_2162_by_2_then_up_1() {
|
||||
let num_lines = 4;
|
||||
let num_cols = 20;
|
||||
|
||||
let mut term = TestTerm::new(num_lines, num_cols, 0);
|
||||
term.print("some long long text");
|
||||
assert_visible_contents(
|
||||
&term,
|
||||
file!(),
|
||||
line!(),
|
||||
&["some long long text", "", "", ""],
|
||||
);
|
||||
term.assert_cursor_pos(19, 0, None, Some(0));
|
||||
term.resize(TerminalSize {
|
||||
rows: num_lines,
|
||||
cols: num_cols - 2,
|
||||
pixel_width: 0,
|
||||
pixel_height: 0,
|
||||
dpi: 0,
|
||||
});
|
||||
assert_visible_contents(
|
||||
&term,
|
||||
file!(),
|
||||
line!(),
|
||||
&["some long long tex", "t", "", ""],
|
||||
);
|
||||
eprintln!("check cursor pos 2");
|
||||
term.assert_cursor_pos(1, 1, None, Some(5));
|
||||
term.resize(TerminalSize {
|
||||
rows: num_lines - 1,
|
||||
cols: num_cols,
|
||||
pixel_width: 0,
|
||||
pixel_height: 0,
|
||||
dpi: 0,
|
||||
});
|
||||
assert_visible_contents(&term, file!(), line!(), &["some long long text", "", ""]);
|
||||
eprintln!("check cursor pos 3");
|
||||
term.assert_cursor_pos(19, 0, None, Some(5));
|
||||
term.resize(TerminalSize {
|
||||
rows: num_lines,
|
||||
cols: num_cols,
|
||||
pixel_width: 0,
|
||||
pixel_height: 0,
|
||||
dpi: 0,
|
||||
});
|
||||
assert_visible_contents(
|
||||
&term,
|
||||
file!(),
|
||||
line!(),
|
||||
&["some long long text", "", "", ""],
|
||||
);
|
||||
eprintln!("check cursor pos 3");
|
||||
term.assert_cursor_pos(19, 0, None, Some(5));
|
||||
}
|
||||
|
||||
/// This test skips over an edge case with cursor positioning,
|
||||
/// so it passes even ahead of a fix for issue 2162.
|
||||
#[test]
|
||||
fn test_resize_2162_by_2() {
|
||||
let num_lines = 4;
|
||||
let num_cols = 20;
|
||||
|
||||
let mut term = TestTerm::new(num_lines, num_cols, 0);
|
||||
term.print("some long long text");
|
||||
assert_visible_contents(
|
||||
&term,
|
||||
file!(),
|
||||
line!(),
|
||||
&["some long long text", "", "", ""],
|
||||
);
|
||||
term.assert_cursor_pos(19, 0, None, Some(0));
|
||||
term.resize(TerminalSize {
|
||||
rows: num_lines,
|
||||
cols: num_cols - 2,
|
||||
pixel_width: 0,
|
||||
pixel_height: 0,
|
||||
dpi: 0,
|
||||
});
|
||||
assert_visible_contents(
|
||||
&term,
|
||||
file!(),
|
||||
line!(),
|
||||
&["some long long tex", "t", "", ""],
|
||||
);
|
||||
eprintln!("check cursor pos 2");
|
||||
term.assert_cursor_pos(1, 1, None, Some(5));
|
||||
term.resize(TerminalSize {
|
||||
rows: num_lines,
|
||||
cols: num_cols,
|
||||
pixel_width: 0,
|
||||
pixel_height: 0,
|
||||
dpi: 0,
|
||||
});
|
||||
assert_visible_contents(
|
||||
&term,
|
||||
file!(),
|
||||
line!(),
|
||||
&["some long long text", "", "", ""],
|
||||
);
|
||||
eprintln!("check cursor pos 3");
|
||||
term.assert_cursor_pos(19, 0, None, Some(5));
|
||||
}
|
||||
|
||||
/// This case tickles an edge case where the cursor ends
|
||||
/// up drifting away from where the line wraps and ends up
|
||||
/// in the wrong place
|
||||
#[test]
|
||||
fn test_resize_2162() {
|
||||
let num_lines = 4;
|
||||
let num_cols = 20;
|
||||
|
||||
let mut term = TestTerm::new(num_lines, num_cols, 0);
|
||||
term.print("some long long text");
|
||||
assert_visible_contents(
|
||||
&term,
|
||||
file!(),
|
||||
line!(),
|
||||
&["some long long text", "", "", ""],
|
||||
);
|
||||
term.assert_cursor_pos(19, 0, None, Some(0));
|
||||
term.resize(TerminalSize {
|
||||
rows: num_lines,
|
||||
cols: num_cols - 1,
|
||||
pixel_width: 0,
|
||||
pixel_height: 0,
|
||||
dpi: 0,
|
||||
});
|
||||
assert_visible_contents(
|
||||
&term,
|
||||
file!(),
|
||||
line!(),
|
||||
&["some long long text", "", "", ""],
|
||||
);
|
||||
eprintln!("check cursor pos 2");
|
||||
term.assert_cursor_pos(19, 0, None, Some(5));
|
||||
term.resize(TerminalSize {
|
||||
rows: num_lines,
|
||||
cols: num_cols,
|
||||
pixel_width: 0,
|
||||
pixel_height: 0,
|
||||
dpi: 0,
|
||||
});
|
||||
assert_visible_contents(
|
||||
&term,
|
||||
file!(),
|
||||
line!(),
|
||||
&["some long long text", "", "", ""],
|
||||
);
|
||||
eprintln!("check cursor pos 3");
|
||||
term.assert_cursor_pos(19, 0, None, Some(5));
|
||||
}
|
||||
|
||||
/// Test the behavior of wrapped lines when we resize the terminal
|
||||
/// wider and then narrower.
|
||||
#[test]
|
||||
|
Loading…
Reference in New Issue
Block a user