mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
terminal/new: pagelist doesn't actively maintain active offset
This commit is contained in:
@ -57,7 +57,6 @@ pages: List,
|
|||||||
/// - history: active row minus one
|
/// - history: active row minus one
|
||||||
///
|
///
|
||||||
viewport: Viewport,
|
viewport: Viewport,
|
||||||
active: RowOffset,
|
|
||||||
|
|
||||||
/// The current desired screen dimensions. I say "desired" because individual
|
/// The current desired screen dimensions. I say "desired" because individual
|
||||||
/// pages may still be a different size and not yet reflowed since we lazily
|
/// pages may still be a different size and not yet reflowed since we lazily
|
||||||
@ -120,7 +119,6 @@ pub fn init(
|
|||||||
.page_pool = page_pool,
|
.page_pool = page_pool,
|
||||||
.pages = page_list,
|
.pages = page_list,
|
||||||
.viewport = .{ .active = {} },
|
.viewport = .{ .active = {} },
|
||||||
.active = .{ .page = page },
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,10 +222,30 @@ pub fn rowIterator(
|
|||||||
/// Get the top-left of the screen for the given tag.
|
/// Get the top-left of the screen for the given tag.
|
||||||
fn getTopLeft(self: *const PageList, tag: point.Tag) RowOffset {
|
fn getTopLeft(self: *const PageList, tag: point.Tag) RowOffset {
|
||||||
return switch (tag) {
|
return switch (tag) {
|
||||||
.active => self.active,
|
// The full screen or history is always just the first page.
|
||||||
.screen, .history => .{ .page = self.pages.first.? },
|
.screen, .history => .{ .page = self.pages.first.? },
|
||||||
|
|
||||||
.viewport => switch (self.viewport) {
|
.viewport => switch (self.viewport) {
|
||||||
.active => self.active,
|
// If the viewport is in the active area then its the same as active.
|
||||||
|
.active => self.getTopLeft(.active),
|
||||||
|
},
|
||||||
|
|
||||||
|
// The active area is calculated backwards from the last page.
|
||||||
|
// This makes getting the active top left slower but makes scrolling
|
||||||
|
// much faster because we don't need to update the top left. Under
|
||||||
|
// heavy load this makes a measurable difference.
|
||||||
|
.active => active: {
|
||||||
|
var page = self.pages.last.?;
|
||||||
|
var rem = self.rows;
|
||||||
|
while (rem > page.data.size.rows) {
|
||||||
|
rem -= page.data.size.rows;
|
||||||
|
page = page.prev.?; // assertion: we always have enough rows for active
|
||||||
|
}
|
||||||
|
|
||||||
|
break :active .{
|
||||||
|
.page = page,
|
||||||
|
.row_offset = page.data.size.rows - rem,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -311,12 +329,12 @@ test "PageList" {
|
|||||||
|
|
||||||
var s = try init(alloc, 80, 24, 1000);
|
var s = try init(alloc, 80, 24, 1000);
|
||||||
defer s.deinit();
|
defer s.deinit();
|
||||||
|
|
||||||
// Viewport is setup
|
|
||||||
try testing.expect(s.viewport == .active);
|
try testing.expect(s.viewport == .active);
|
||||||
try testing.expect(s.active.page == s.pages.first);
|
try testing.expect(s.pages.first != null);
|
||||||
try testing.expect(s.active.page.next == null);
|
|
||||||
try testing.expect(s.active.row_offset == 0);
|
// Active area should be the top
|
||||||
try testing.expect(s.active.page.data.size.cols == 80);
|
try testing.expectEqual(RowOffset{
|
||||||
try testing.expect(s.active.page.data.size.rows == 24);
|
.page = s.pages.first.?,
|
||||||
|
.row_offset = 0,
|
||||||
|
}, s.getTopLeft(.active));
|
||||||
}
|
}
|
||||||
|
@ -51,13 +51,17 @@ pub fn init(
|
|||||||
rows: size.CellCountInt,
|
rows: size.CellCountInt,
|
||||||
max_scrollback: usize,
|
max_scrollback: usize,
|
||||||
) !Screen {
|
) !Screen {
|
||||||
// Initialize our backing pages. This will initialize the viewport.
|
// Initialize our backing pages.
|
||||||
var pages = try PageList.init(alloc, cols, rows, max_scrollback);
|
var pages = try PageList.init(alloc, cols, rows, max_scrollback);
|
||||||
errdefer pages.deinit();
|
errdefer pages.deinit();
|
||||||
|
|
||||||
// The viewport is guaranteed to exist, so grab it so we can setup
|
// The active area is guaranteed to be allocated and the first
|
||||||
// our initial cursor.
|
// page in the list after init. This lets us quickly setup the cursor.
|
||||||
const page_offset = pages.rowOffset(.{ .active = .{ .x = 0, .y = 0 } });
|
// This is MUCH faster than pages.rowOffset.
|
||||||
|
const page_offset: PageList.RowOffset = .{
|
||||||
|
.page = pages.pages.first.?,
|
||||||
|
.row_offset = 0,
|
||||||
|
};
|
||||||
const page_rac = page_offset.rowAndCell(0);
|
const page_rac = page_offset.rowAndCell(0);
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
@ -146,13 +150,6 @@ pub fn cursorDownScroll(self: *Screen) !void {
|
|||||||
self.cursor.page_offset = page_offset;
|
self.cursor.page_offset = page_offset;
|
||||||
self.cursor.page_row = page_rac.row;
|
self.cursor.page_row = page_rac.row;
|
||||||
self.cursor.page_cell = page_rac.cell;
|
self.cursor.page_cell = page_rac.cell;
|
||||||
|
|
||||||
// try self.pages.scrollActive(1);
|
|
||||||
// const page_offset = self.pages.active.forward(self.cursor.y).?;
|
|
||||||
// const page_rac = page_offset.rowAndCell(self.cursor.x);
|
|
||||||
// self.cursor.page_offset = page_offset;
|
|
||||||
// self.cursor.page_row = page_rac.row;
|
|
||||||
// self.cursor.page_cell = page_rac.cell;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dump the screen to a string. The writer given should be buffered;
|
/// Dump the screen to a string. The writer given should be buffered;
|
||||||
|
@ -461,12 +461,11 @@ test "Terminal: input that forces scroll" {
|
|||||||
for ("abcdef") |c| try t.print(c);
|
for ("abcdef") |c| try t.print(c);
|
||||||
try testing.expectEqual(@as(usize, 4), t.screen.cursor.y);
|
try testing.expectEqual(@as(usize, 4), t.screen.cursor.y);
|
||||||
try testing.expectEqual(@as(usize, 0), t.screen.cursor.x);
|
try testing.expectEqual(@as(usize, 0), t.screen.cursor.x);
|
||||||
// TODO once viewport is moved
|
{
|
||||||
// {
|
const str = try t.plainString(alloc);
|
||||||
// const str = try t.plainString(alloc);
|
defer alloc.free(str);
|
||||||
// defer alloc.free(str);
|
try testing.expectEqualStrings("b\nc\nd\ne\nf", str);
|
||||||
// try testing.expectEqualStrings("b\nc\nd\ne\nf", str);
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "Terminal: zero-width character at start" {
|
test "Terminal: zero-width character at start" {
|
||||||
|
Reference in New Issue
Block a user