aba50517
Bump xdg_wm_base to v6 and honor toplevel suspended state
a73x 2026-04-16 10:53
Commit message
src/wayland.zig
| Old | New | ||
|---|---|---|---|
| @@ -1078,11 +1078,27 @@ fn surfaceListener(_: *wl.Surface, event: wl.Surface.Event, window: *Window) voi | |||
| 1078 | } | 1078 | } |
| 1079 | } | 1079 | } |
| 1080 | 1080 | ||
| 1081 | fn applyToplevelStates(state: *SurfaceState, state_bytes: []const u8) void { | ||
| 1082 | // xdg_toplevel.configure delivers the state array as a wl_array of u32. | ||
| 1083 | // Re-interpret to u32 slice and scan for `.suspended`. | ||
| 1084 | const u32_count = state_bytes.len / @sizeOf(u32); | ||
| 1085 | const states = std.mem.bytesAsSlice(u32, state_bytes[0 .. u32_count * @sizeOf(u32)]); | ||
| 1086 | var suspended = false; | ||
| 1087 | for (states) |raw| { | ||
| 1088 | if (raw == @intFromEnum(xdg.Toplevel.State.suspended)) { | ||
| 1089 | suspended = true; | ||
| 1090 | break; | ||
| 1091 | } | ||
| 1092 | } | ||
| 1093 | state.suspended = suspended; | ||
| 1094 | } | ||
| 1095 | |||
| 1081 | fn xdgToplevelListener(_: *xdg.Toplevel, event: xdg.Toplevel.Event, window: *Window) void { | 1096 | fn xdgToplevelListener(_: *xdg.Toplevel, event: xdg.Toplevel.Event, window: *Window) void { |
| 1082 | switch (event) { | 1097 | switch (event) { |
| 1083 | .configure => |cfg| { | 1098 | .configure => |cfg| { |
| 1084 | if (cfg.width > 0) window.width = @intCast(cfg.width); | 1099 | if (cfg.width > 0) window.width = @intCast(cfg.width); |
| 1085 | if (cfg.height > 0) window.height = @intCast(cfg.height); | 1100 | if (cfg.height > 0) window.height = @intCast(cfg.height); |
| 1101 | applyToplevelStates(&window.state, std.mem.sliceAsBytes(cfg.states.slice(u32))); | ||
| 1086 | }, | 1102 | }, |
| 1087 | .close => window.should_close = true, | 1103 | .close => window.should_close = true, |
| 1088 | .configure_bounds => {}, | 1104 | .configure_bounds => {}, |
| @@ -1103,7 +1119,7 @@ fn registryListener( | |||
| 1103 | } else if (std.mem.eql(u8, iface, std.mem.span(wl.DataDeviceManager.interface.name))) { | 1119 | } else if (std.mem.eql(u8, iface, std.mem.span(wl.DataDeviceManager.interface.name))) { |
| 1104 | conn.globals.data_device_manager = registry.bind(g.name, wl.DataDeviceManager, 3) catch return; | 1120 | conn.globals.data_device_manager = registry.bind(g.name, wl.DataDeviceManager, 3) catch return; |
| 1105 | } else if (std.mem.eql(u8, iface, std.mem.span(xdg.WmBase.interface.name))) { | 1121 | } else if (std.mem.eql(u8, iface, std.mem.span(xdg.WmBase.interface.name))) { |
| 1106 | conn.globals.wm_base = registry.bind(g.name, xdg.WmBase, 5) catch return; | 1122 | conn.globals.wm_base = registry.bind(g.name, xdg.WmBase, 6) catch return; |
| 1107 | } else if (std.mem.eql(u8, iface, std.mem.span(wl.Seat.interface.name))) { | 1123 | } else if (std.mem.eql(u8, iface, std.mem.span(wl.Seat.interface.name))) { |
| 1108 | conn.globals.seat = registry.bind(g.name, wl.Seat, 9) catch return; | 1124 | conn.globals.seat = registry.bind(g.name, wl.Seat, 9) catch return; |
| 1109 | } else if (std.mem.eql(u8, iface, std.mem.span(wl.Output.interface.name))) { | 1125 | } else if (std.mem.eql(u8, iface, std.mem.span(wl.Output.interface.name))) { |
| @@ -1257,3 +1273,24 @@ test "SurfaceState.visible requires configured && !suspended && enteredCount > 0 | |||
| 1257 | tracker.leaveOutput(1); | 1273 | tracker.leaveOutput(1); |
| 1258 | try std.testing.expect(!state.visible()); | 1274 | try std.testing.expect(!state.visible()); |
| 1259 | } | 1275 | } |
| 1276 | |||
| 1277 | test "SurfaceState.suspended toggles from xdg_toplevel.configure.states" { | ||
| 1278 | var tracker = ScaleTracker.init(std.testing.allocator); | ||
| 1279 | defer tracker.deinit(); | ||
| 1280 | try tracker.addOutput(1); | ||
| 1281 | try tracker.enterOutput(1); | ||
| 1282 | |||
| 1283 | var state = SurfaceState{ .tracker = &tracker, .configured = true }; | ||
| 1284 | try std.testing.expect(state.visible()); | ||
| 1285 | |||
| 1286 | // Helper function under test — applies xdg_toplevel state array to SurfaceState. | ||
| 1287 | const states_suspended = [_]u32{@intFromEnum(xdg.Toplevel.State.suspended)}; | ||
| 1288 | applyToplevelStates(&state, std.mem.sliceAsBytes(&states_suspended)); | ||
| 1289 | try std.testing.expect(state.suspended); | ||
| 1290 | try std.testing.expect(!state.visible()); | ||
| 1291 | |||
| 1292 | const states_none = [_]u32{}; | ||
| 1293 | applyToplevelStates(&state, std.mem.sliceAsBytes(&states_none)); | ||
| 1294 | try std.testing.expect(!state.suspended); | ||
| 1295 | try std.testing.expect(state.visible()); | ||
| 1296 | } | ||