aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/src/terminal/ScreenSet.zig
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-06-01 23:05:23 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-06-01 23:05:51 +0300
commit5bd21b7ed468b5ff4d1a5b2ed7e211f401eb138a (patch)
tree672fa4625cca0ecb3e9376fc7f8e33d7b0e9deef /vendor/libghostty-vt/src/terminal/ScreenSet.zig
parent32abb3776668ee768200019c170956f67fe33a86 (diff)
chore: update libghostty vendor
refs #276
Diffstat (limited to 'vendor/libghostty-vt/src/terminal/ScreenSet.zig')
-rw-r--r--vendor/libghostty-vt/src/terminal/ScreenSet.zig43
1 files changed, 43 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/terminal/ScreenSet.zig b/vendor/libghostty-vt/src/terminal/ScreenSet.zig
index d0856da5..4d3689e3 100644
--- a/vendor/libghostty-vt/src/terminal/ScreenSet.zig
+++ b/vendor/libghostty-vt/src/terminal/ScreenSet.zig
@@ -30,6 +30,11 @@ active: *Screen,
/// All screens that are initialized.
all: std.EnumMap(Key, *Screen),
+/// Monotonic generation counter for each screen key. This changes whenever a
+/// screen is removed so external handles can distinguish a newly initialized
+/// screen from stale references into destroyed screen storage.
+generations: std.EnumMap(Key, usize),
+
pub fn init(
alloc: Allocator,
opts: Screen.Options,
@@ -42,6 +47,7 @@ pub fn init(
.active_key = .primary,
.active = screen,
.all = .init(.{ .primary = screen }),
+ .generations = .initFull(0),
};
}
@@ -59,6 +65,11 @@ pub fn get(self: *const ScreenSet, key: Key) ?*Screen {
return self.all.get(key);
}
+/// Get the current generation for the given screen key.
+pub fn generation(self: *const ScreenSet, key: Key) usize {
+ return self.generations.get(key).?;
+}
+
/// Get the screen for the given key, initializing it if necessary.
pub fn getInit(
self: *ScreenSet,
@@ -82,6 +93,7 @@ pub fn remove(
) void {
assert(key != .primary);
if (self.all.fetchRemove(key)) |screen| {
+ self.generations.put(key, self.generation(key) +% 1);
screen.deinit();
alloc.destroy(screen);
}
@@ -99,9 +111,40 @@ test ScreenSet {
var set: ScreenSet = try .init(alloc, .default);
defer set.deinit(alloc);
try testing.expectEqual(.primary, set.active_key);
+ try testing.expectEqual(@as(usize, 0), set.generation(.primary));
+ try testing.expectEqual(@as(usize, 0), set.generation(.alternate));
// Initialize a secondary screen
_ = try set.getInit(alloc, .alternate, .default);
+ try testing.expectEqual(@as(usize, 0), set.generation(.alternate));
+
set.switchTo(.alternate);
try testing.expectEqual(.alternate, set.active_key);
}
+
+test "ScreenSet generations" {
+ const alloc = testing.allocator;
+ var set: ScreenSet = try .init(alloc, .default);
+ defer set.deinit(alloc);
+
+ try testing.expectEqual(@as(usize, 0), set.generation(.primary));
+ try testing.expectEqual(@as(usize, 0), set.generation(.alternate));
+
+ // A no-op removal doesn't change the generation.
+ set.remove(alloc, .alternate);
+ try testing.expectEqual(@as(usize, 0), set.generation(.alternate));
+
+ // Initializing a screen doesn't change the generation.
+ _ = try set.getInit(alloc, .alternate, .default);
+ try testing.expectEqual(@as(usize, 0), set.generation(.alternate));
+
+ const alternate_generation = set.generation(.alternate);
+ set.remove(alloc, .alternate);
+ try testing.expectEqual(alternate_generation +% 1, set.generation(.alternate));
+
+ // Reinitializing keeps the generation from the last removal, so stale
+ // handles can distinguish the new screen from the destroyed screen.
+ _ = try set.getInit(alloc, .alternate, .default);
+ try testing.expectEqual(alternate_generation +% 1, set.generation(.alternate));
+ try testing.expectEqual(@as(usize, 0), set.generation(.primary));
+}