terminal: Pin.garbage tracking
parent
2b647ba4cb
commit
7b26e6319e
|
|
@ -371,6 +371,9 @@ fn verifyIntegrity(self: *const PageList) IntegrityError!void {
|
|||
if (comptime !build_options.slow_runtime_safety) return;
|
||||
if (self.pause_integrity_checks > 0) return;
|
||||
|
||||
// Our viewport pin should never be garbage
|
||||
assert(!self.viewport_pin.garbage);
|
||||
|
||||
// Verify that our cached total_rows matches the actual row count
|
||||
const actual_total = self.totalRows();
|
||||
if (actual_total != self.total_rows) {
|
||||
|
|
@ -528,6 +531,8 @@ pub fn reset(self: *PageList) void {
|
|||
self.total_rows = self.rows;
|
||||
|
||||
// Update all our tracked pins to point to our first page top-left
|
||||
// and mark them as garbage, because it got mangled in a way where
|
||||
// semantically it really doesn't make sense.
|
||||
{
|
||||
var it = self.tracked_pins.iterator();
|
||||
while (it.next()) |entry| {
|
||||
|
|
@ -535,7 +540,11 @@ pub fn reset(self: *PageList) void {
|
|||
p.node = self.pages.first.?;
|
||||
p.x = 0;
|
||||
p.y = 0;
|
||||
p.garbage = true;
|
||||
}
|
||||
|
||||
// Our viewport pin is never garbage
|
||||
self.viewport_pin.garbage = false;
|
||||
}
|
||||
|
||||
// Move our viewport back to the active area since everything is gone.
|
||||
|
|
@ -2428,7 +2437,9 @@ pub fn grow(self: *PageList) !?*List.Node {
|
|||
p.node = self.pages.first.?;
|
||||
p.y = 0;
|
||||
p.x = 0;
|
||||
p.garbage = true;
|
||||
}
|
||||
self.viewport_pin.garbage = false;
|
||||
|
||||
// In this case we do NOT need to update page_size because
|
||||
// we're reusing an existing page so nothing has changed.
|
||||
|
|
@ -3047,13 +3058,16 @@ pub fn eraseRows(
|
|||
fn erasePage(self: *PageList, node: *List.Node) void {
|
||||
assert(node.next != null or node.prev != null);
|
||||
|
||||
// Update any tracked pins to move to the next page.
|
||||
// Update any tracked pins to move to the previous or next page.
|
||||
const pin_keys = self.tracked_pins.keys();
|
||||
for (pin_keys) |p| {
|
||||
if (p.node != node) continue;
|
||||
p.node = node.next orelse node.prev orelse unreachable;
|
||||
p.node = node.prev orelse node.next orelse unreachable;
|
||||
p.y = 0;
|
||||
p.x = 0;
|
||||
|
||||
// This doesn't get marked garbage because the tracked pin
|
||||
// movement is sensical.
|
||||
}
|
||||
|
||||
// Remove the page from the linked list
|
||||
|
|
@ -3903,6 +3917,13 @@ pub const Pin = struct {
|
|||
y: size.CellCountInt = 0,
|
||||
x: size.CellCountInt = 0,
|
||||
|
||||
/// This is flipped to true for tracked pins that were tracking
|
||||
/// a page that got pruned for any reason and where the tracked pin
|
||||
/// couldn't be moved to a sensical location. Users of the tracked
|
||||
/// pin could use this data and make their own determination of
|
||||
/// semantics.
|
||||
garbage: bool = false,
|
||||
|
||||
pub inline fn rowAndCell(self: Pin) struct {
|
||||
row: *pagepkg.Row,
|
||||
cell: *pagepkg.Cell,
|
||||
|
|
@ -5757,6 +5778,7 @@ test "PageList grow prune scrollback" {
|
|||
try testing.expect(p.node == s.pages.first.?);
|
||||
try testing.expect(p.x == 0);
|
||||
try testing.expect(p.y == 0);
|
||||
try testing.expect(p.garbage);
|
||||
|
||||
// Verify the viewport offset cache was invalidated. After pruning,
|
||||
// the offset should have changed because we removed rows from
|
||||
|
|
@ -10641,6 +10663,29 @@ test "PageList reset across two pages" {
|
|||
try testing.expectEqual(@as(usize, s.rows), s.totalRows());
|
||||
}
|
||||
|
||||
test "PageList reset moves tracked pins and marks them as garbage" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
var s = try init(alloc, 80, 24, null);
|
||||
defer s.deinit();
|
||||
|
||||
// Create a tracked pin into the active area
|
||||
const p = try s.trackPin(s.pin(.{ .active = .{
|
||||
.x = 42,
|
||||
.y = 12,
|
||||
} }).?);
|
||||
defer s.untrackPin(p);
|
||||
|
||||
s.reset();
|
||||
|
||||
// Our added pin should now be garbage
|
||||
try testing.expect(p.garbage);
|
||||
|
||||
// Viewport pin should not be garbage because it makes sense.
|
||||
try testing.expect(!s.viewport_pin.garbage);
|
||||
}
|
||||
|
||||
test "PageList clears history" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
|
|
|||
Loading…
Reference in New Issue