mirror of
https://github.com/wez/wezterm.git
synced 2024-11-29 21:44:24 +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 rewrapped = VecDeque::new();
|
||||||
let mut logical_line: Option<Line> = None;
|
let mut logical_line: Option<Line> = None;
|
||||||
let mut logical_cursor_x: Option<usize> = 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() {
|
for (phys_idx, mut line) in self.lines.drain(..).enumerate() {
|
||||||
line.update_last_change_seqno(seqno);
|
line.update_last_change_seqno(seqno);
|
||||||
@ -140,6 +140,25 @@ impl Screen {
|
|||||||
let num_lines = x / physical_cols;
|
let num_lines = x / physical_cols;
|
||||||
let last_x = x - (num_lines * physical_cols);
|
let last_x = x - (num_lines * physical_cols);
|
||||||
adjusted_cursor = (last_x, rewrapped.len() + num_lines);
|
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 {
|
if line.len() <= physical_cols {
|
||||||
|
@ -914,7 +914,11 @@ impl TerminalState {
|
|||||||
if self.dec_origin_mode {
|
if self.dec_origin_mode {
|
||||||
self.left_and_right_margins.end
|
self.left_and_right_margins.end
|
||||||
} else {
|
} 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
|
} as i64
|
||||||
- 1,
|
- 1,
|
||||||
)
|
)
|
||||||
|
@ -298,7 +298,7 @@ fn test_cup() {
|
|||||||
term.cup(-1, -1);
|
term.cup(-1, -1);
|
||||||
term.assert_cursor_pos(0, 0, None, None);
|
term.assert_cursor_pos(0, 0, None, None);
|
||||||
term.cup(500, 500);
|
term.cup(500, 500);
|
||||||
term.assert_cursor_pos(3, 2, None, None);
|
term.assert_cursor_pos(4, 2, None, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -313,7 +313,7 @@ fn test_hvp() {
|
|||||||
term.hvp(-1, -1);
|
term.hvp(-1, -1);
|
||||||
term.assert_cursor_pos(0, 0, None, None);
|
term.assert_cursor_pos(0, 0, None, None);
|
||||||
term.hvp(500, 500);
|
term.hvp(500, 500);
|
||||||
term.assert_cursor_pos(3, 2, None, None);
|
term.assert_cursor_pos(4, 2, None, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -354,7 +354,7 @@ fn test_cha() {
|
|||||||
term.assert_cursor_pos(0, 1, None, Some(seqno));
|
term.assert_cursor_pos(0, 1, None, Some(seqno));
|
||||||
|
|
||||||
term.print("\x1b[100G");
|
term.print("\x1b[100G");
|
||||||
term.assert_cursor_pos(3, 1, None, None);
|
term.assert_cursor_pos(4, 1, None, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -756,6 +756,162 @@ fn test_dec_double_width() {
|
|||||||
assert!(lines[3].is_single_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
|
/// Test the behavior of wrapped lines when we resize the terminal
|
||||||
/// wider and then narrower.
|
/// wider and then narrower.
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user