terminal: fix cursor pos when resizing more rows not at bottom

Fixes #906

This changes our resize behavior when increasing row height.

If the cursor was originally at the bottom of the viewport, existing
scrollback (if it exists) will be "pulled down" from the top,
effectively keeping the cursor at the bottom. This is the behavior
today, prior to this commit.

If the cursor is not at the bottom of the viewport, scrollback will NOT
be "pulled down" and instead blank lines will be added _below_. This is
new behavior.
This commit is contained in:
Mitchell Hashimoto
2023-11-21 11:27:02 -08:00
parent 7fbcc46106
commit 44e28e43d3

View File

@ -2397,6 +2397,23 @@ pub fn resizeWithoutReflow(self: *Screen, rows: usize, cols: usize) !void {
old_cursor_y_screen -| self.history
else
self.rows - 1;
// If our rows increased and our cursor is NOT at the bottom, we want
// to try to preserve the y value of the old cursor. In other words, we
// don't want to "pull down" scrollback. This is purely a UX feature.
if (self.rows > old.rows and
old.cursor.y < old.rows - 1 and
self.cursor.y > old.cursor.y)
{
const delta = self.cursor.y - old.cursor.y;
if (self.scroll(.{ .screen = @intCast(delta) })) {
self.cursor.y -= delta;
} else |err| {
// If this scroll fails its not that big of a deal so we just
// log and ignore.
log.warn("failed to scroll for resize, cursor may be off err={}", .{err});
}
}
}
/// Resize the screen. The rows or cols can be bigger or smaller. This
@ -5362,7 +5379,7 @@ test "Screen: resize (no reflow) less cols" {
}
}
test "Screen: resize (no reflow) more rows with scrollback" {
test "Screen: resize (no reflow) more rows with scrollback cursor end" {
const testing = std.testing;
const alloc = testing.allocator;
@ -5576,7 +5593,8 @@ test "Screen: resize more rows with populated scrollback" {
{
const contents = try s.testString(alloc, .viewport);
defer alloc.free(contents);
try testing.expectEqualStrings(str, contents);
const expected = "3IJKL\n4ABCD\n5EFGH";
try testing.expectEqualStrings(expected, contents);
}
}