From 44e28e43d3ec0b1528429802c2ef53d1e3f0773c Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 21 Nov 2023 11:27:02 -0800 Subject: [PATCH] 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. --- src/terminal/Screen.zig | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/terminal/Screen.zig b/src/terminal/Screen.zig index 4805a7119..63295a97a 100644 --- a/src/terminal/Screen.zig +++ b/src/terminal/Screen.zig @@ -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); } }