a73x

70396bf0

Add SurfaceState struct for visibility tracking

a73x   2026-04-16 10:44

Commit message
Add SurfaceState struct for visibility tracking

Single source of truth for whether the surface is currently mapped,
configured, and not suspended. Not yet wired into Window — that happens
in a follow-up.

src/wayland.zig
Old New
@@ -18,6 +18,18 @@ pub const Output = struct {
18 pending_scale: i32 = 1, 18 pending_scale: i32 = 1,
19 }; 19 };
20 20
21 pub const SurfaceState = struct {
22 configured: bool = false,
23 suspended: bool = false,
24 tracker: *ScaleTracker,
25
26 pub fn visible(self: *const SurfaceState) bool {
27 return self.configured
28 and !self.suspended
29 and self.tracker.enteredCount() > 0;
30 }
31 };
32
21 pub const KeyboardEvent = struct { 33 pub const KeyboardEvent = struct {
22 keysym: u32, 34 keysym: u32,
23 modifiers: Modifiers, 35 modifiers: Modifiers,
@@ -1217,3 +1229,29 @@ test "Window.bufferScale reflects ScaleTracker entered outputs" {
1217 tracker.leaveOutput(2); 1229 tracker.leaveOutput(2);
1218 try std.testing.expectEqual(@as(i32, 1), tracker.bufferScale()); 1230 try std.testing.expectEqual(@as(i32, 1), tracker.bufferScale());
1219 } 1231 }
1232
1233 test "SurfaceState.visible requires configured && !suspended && enteredCount > 0" {
1234 var tracker = ScaleTracker.init(std.testing.allocator);
1235 defer tracker.deinit();
1236 try tracker.addOutput(1);
1237
1238 var state = SurfaceState{ .tracker = &tracker };
1239
1240 // Unconfigured → not visible
1241 try std.testing.expect(!state.visible());
1242
1243 state.configured = true;
1244 // No entered outputs yet → not visible
1245 try std.testing.expect(!state.visible());
1246
1247 try tracker.enterOutput(1);
1248 // Configured + entered + not suspended → visible
1249 try std.testing.expect(state.visible());
1250
1251 state.suspended = true;
1252 try std.testing.expect(!state.visible());
1253
1254 state.suspended = false;
1255 tracker.leaveOutput(1);
1256 try std.testing.expect(!state.visible());
1257 }