mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
typing jumps scroll to bottom
This commit is contained in:
2
TODO.md
2
TODO.md
@ -1,6 +1,8 @@
|
||||
Bugs:
|
||||
|
||||
* Underline should use freetype underline thickness hint
|
||||
* Any printing action forces scroll to jump to bottom, this makes it impossible
|
||||
to scroll up while logs are coming in or something
|
||||
|
||||
Performance:
|
||||
|
||||
|
@ -121,6 +121,15 @@ pub fn deinit(self: *Screen, alloc: Allocator) void {
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
/// This returns true if the display area is anchored at the bottom currently.
|
||||
pub fn displayIsBottom(self: Screen) bool {
|
||||
return self.visible_offset == self.bottomOffset();
|
||||
}
|
||||
|
||||
fn bottomOffset(self: Screen) usize {
|
||||
return self.bottom - self.rows;
|
||||
}
|
||||
|
||||
/// Returns an iterator that can be used to iterate over all of the rows
|
||||
/// from index zero.
|
||||
pub fn rowIterator(self: *const Screen) RowIterator {
|
||||
@ -429,7 +438,12 @@ test "Screen: scrolling" {
|
||||
var s = try init(alloc, 3, 5, 0);
|
||||
defer s.deinit(alloc);
|
||||
s.testWriteString("1ABCD\n2EFGH\n3IJKL");
|
||||
|
||||
try testing.expect(s.displayIsBottom());
|
||||
|
||||
// Scroll down, should still be bottom
|
||||
s.scroll(.{ .delta = 1 });
|
||||
try testing.expect(s.displayIsBottom());
|
||||
|
||||
// Test our row index
|
||||
try testing.expectEqual(@as(usize, 5), s.rowIndex(0));
|
||||
@ -462,6 +476,7 @@ test "Screen: scroll down from 0" {
|
||||
defer s.deinit(alloc);
|
||||
s.testWriteString("1ABCD\n2EFGH\n3IJKL");
|
||||
s.scroll(.{ .delta = -1 });
|
||||
try testing.expect(s.displayIsBottom());
|
||||
|
||||
{
|
||||
// Test our contents rotated
|
||||
@ -494,6 +509,7 @@ test "Screen: scrollback" {
|
||||
|
||||
// Scrolling to the bottom
|
||||
s.scroll(.{ .bottom = {} });
|
||||
try testing.expect(s.displayIsBottom());
|
||||
|
||||
{
|
||||
// Test our contents rotated
|
||||
@ -504,6 +520,7 @@ test "Screen: scrollback" {
|
||||
|
||||
// Scrolling back should make it visible again
|
||||
s.scroll(.{ .delta = -1 });
|
||||
try testing.expect(!s.displayIsBottom());
|
||||
|
||||
{
|
||||
// Test our contents rotated
|
||||
|
@ -203,6 +203,9 @@ pub fn print(self: *Terminal, c: u21) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
// If we're not at the bottom, then we need to move there
|
||||
if (!self.screen.displayIsBottom()) self.screen.scroll(.{ .bottom = {} });
|
||||
|
||||
// If we're soft-wrapping, then handle that first.
|
||||
if (self.cursor.pending_wrap and self.mode_autowrap) {
|
||||
// Mark that the cell is wrapped, which guarantees that there is
|
||||
@ -691,12 +694,15 @@ pub fn scrollDown(self: *Terminal, count: usize) void {
|
||||
|
||||
/// Options for scrolling the viewport of the terminal grid.
|
||||
pub const ScrollViewport = union(enum) {
|
||||
/// Scroll to the top of the scrollback
|
||||
top: void,
|
||||
delta: isize,
|
||||
};
|
||||
|
||||
/// Scroll the viewport of the terminal grid.
|
||||
pub fn scrollViewport(self: *Terminal, behavior: ScrollViewport) void {
|
||||
self.screen.scroll(switch (behavior) {
|
||||
.top => .{ .top = {} },
|
||||
.delta => |delta| .{ .delta_no_grow = delta },
|
||||
});
|
||||
}
|
||||
@ -766,6 +772,41 @@ test "Terminal: soft wrap" {
|
||||
}
|
||||
}
|
||||
|
||||
test "Terminal: print scrolls back to bottom" {
|
||||
var t = try init(testing.allocator, 5, 2);
|
||||
defer t.deinit(testing.allocator);
|
||||
|
||||
// Basic grid writing
|
||||
for ("hello") |c| try t.print(c);
|
||||
|
||||
// Make newlines so we create scrollback
|
||||
// 3 pushes hello off the screen
|
||||
t.index();
|
||||
t.index();
|
||||
t.index();
|
||||
{
|
||||
var str = try t.plainString(testing.allocator);
|
||||
defer testing.allocator.free(str);
|
||||
try testing.expectEqualStrings("", str);
|
||||
}
|
||||
|
||||
// Scroll to the top
|
||||
t.scrollViewport(.{ .top = {} });
|
||||
{
|
||||
var str = try t.plainString(testing.allocator);
|
||||
defer testing.allocator.free(str);
|
||||
try testing.expectEqualStrings("hello", str);
|
||||
}
|
||||
|
||||
// Type
|
||||
try t.print('A');
|
||||
{
|
||||
var str = try t.plainString(testing.allocator);
|
||||
defer testing.allocator.free(str);
|
||||
try testing.expectEqualStrings("\nA", str);
|
||||
}
|
||||
}
|
||||
|
||||
test "Terminal: linefeed and carriage return" {
|
||||
var t = try init(testing.allocator, 80, 80);
|
||||
defer t.deinit(testing.allocator);
|
||||
|
Reference in New Issue
Block a user