Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
Window: refactor away redundant destroying bool
Also add an assertion in destroy()
river/Cursor.zig | 2 +-
river/Window.zig | 42 ++++++++++++++++--------------------------
river/WindowManager.zig | 2 +-
river/XdgToplevel.zig | 3 +--
4 files changed, 19 insertions(+), 30 deletions(-)
diff --git a/river/Cursor.zig b/river/Cursor.zig
index 718885d..f0aa0a8 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -360,7 +360,7 @@ fn updateHovered(cursor: *Cursor) void {
}
},
.xwayland => cursor.seat.wm_scheduled.window = window,
- .none => {},
+ .destroying => {},
}
},
.shell_surface, .lock_surface => cursor.seat.wm_scheduled.window = null,
diff --git a/river/Window.zig b/river/Window.zig
index 9bed396..969e687 100644
--- a/river/Window.zig
+++ b/river/Window.zig
@@ -53,9 +53,7 @@ const Impl = union(enum) {
/// This state is assigned during destruction after the xdg toplevel
/// has been destroyed but while the transaction system is still rendering
/// saved surfaces of the window.
- /// The toplevel could simply be set to undefined instead, but using a
- /// tag like this gives us better safety checks.
- none,
+ destroying,
};
pub const Border = struct {
@@ -115,9 +113,6 @@ popup_tree: *wlr.SceneTree,
/// proposing dimensions for a new river_window_v1 object.
initialized: bool = false,
mapped: bool = false,
-/// This indicates that the window should be destroyed when the current
-/// transaction completes. See Window.destroy()
-destroying: bool = false,
/// WindowManager.windows
link: wl.list.Link,
@@ -207,7 +202,7 @@ rendering_requested: struct {
box: wlr.Box = .{ .x = 0, .y = 0, .width = 0, .height = 0 },
pub fn create(impl: Impl) error{OutOfMemory}!*Window {
- assert(impl != .none);
+ assert(impl != .destroying);
const window = try util.gpa.create(Window);
errdefer util.gpa.destroy(window);
@@ -258,19 +253,16 @@ pub fn create(impl: Impl) error{OutOfMemory}!*Window {
/// sequence in which the closed event was sent is completed and the following
/// render sequence is completed as well.
pub fn destroy(window: *Window) void {
- assert(window.impl == .none);
+ assert(window.impl == .destroying);
assert(!window.mapped);
- // We can't assert(window.wm_scheduled.state != .ready) since the client may
- // have exited after making its empty initial commit but before the surface
- // is mapped.
switch (window.wm_scheduled.state) {
.init => {},
- .closing, .ready => {
- window.wm_scheduled.state = .closing;
+ .closing => {
server.wm.dirtyWindowing();
return;
},
+ .ready => unreachable,
}
assert(window.object == null);
@@ -573,7 +565,7 @@ pub fn manageFinish(window: *Window) bool {
// This can happen if the window is destroyed after being sent to the wm but
// before being mapped.
- if (window.destroying) {
+ if (window.impl == .destroying) {
assert(window.wm_scheduled.state == .closing);
return false;
}
@@ -620,7 +612,7 @@ pub fn manageFinish(window: *Window) bool {
const track_configure = switch (window.impl) {
.toplevel => |*toplevel| toplevel.configure(),
.xwayland => |*xwindow| xwindow.configure(),
- .none => unreachable,
+ .destroying => unreachable,
};
if (track_configure and window.mapped) {
@@ -674,7 +666,7 @@ pub fn renderStart(window: *Window) void {
window.rendering_scheduled.width = xwindow.xsurface.width;
window.rendering_scheduled.height = xwindow.xsurface.height;
},
- .none => {},
+ .destroying => {},
}
const sent = &window.rendering_sent;
@@ -781,12 +773,12 @@ pub fn rootSurface(window: Window) ?*wlr.Surface {
return switch (window.impl) {
.toplevel => |toplevel| toplevel.wlr_toplevel.base.surface,
.xwayland => |xwindow| xwindow.xsurface.surface,
- .none => null,
+ .destroying => null,
};
}
pub fn sendFrameDone(window: Window) void {
- assert(window.mapped and !window.destroying);
+ assert(window.mapped and window.impl != .destroying);
var now = posix.clock_gettime(posix.CLOCK.MONOTONIC) catch @panic("CLOCK_MONOTONIC not supported");
window.rootSurface().?.sendFrameDone(&now);
@@ -796,35 +788,33 @@ pub fn close(window: Window) void {
switch (window.impl) {
.toplevel => |toplevel| toplevel.wlr_toplevel.sendClose(),
.xwayland => |xwindow| xwindow.xsurface.close(),
- .none => {},
+ .destroying => {},
}
}
pub fn destroyPopups(window: Window) void {
switch (window.impl) {
.toplevel => |toplevel| toplevel.destroyPopups(),
- .xwayland, .none => {},
+ .xwayland, .destroying => {},
}
}
/// Return the current title of the window if any.
pub fn getTitle(window: Window) ?[*:0]const u8 {
- assert(!window.destroying);
return switch (window.impl) {
.toplevel => |toplevel| toplevel.wlr_toplevel.title,
.xwayland => |xwindow| xwindow.xsurface.title,
- .none => unreachable,
+ .destroying => unreachable,
};
}
/// Return the current app_id of the window if any.
pub fn getAppId(window: Window) ?[*:0]const u8 {
- assert(!window.destroying);
return switch (window.impl) {
.toplevel => |toplevel| toplevel.wlr_toplevel.app_id,
// X11 clients don't have an app_id but the class serves a similar role.
.xwayland => |xwindow| xwindow.xsurface.class,
- .none => unreachable,
+ .destroying => unreachable,
};
}
@@ -832,7 +822,7 @@ pub fn getAppId(window: Window) ?[*:0]const u8 {
pub fn map(window: *Window) !void {
log.debug("window '{?s}' mapped", .{window.getTitle()});
- assert(!window.mapped and !window.destroying);
+ assert(!window.mapped and window.impl != .destroying);
window.mapped = true;
}
@@ -842,7 +832,7 @@ pub fn unmap(window: *Window) void {
window.surfaces.save();
- assert(window.mapped and !window.destroying);
+ assert(window.mapped and window.impl != .destroying);
window.mapped = false;
assert(window.wm_scheduled.state != .closing);
diff --git a/river/WindowManager.zig b/river/WindowManager.zig
index 1f1895e..eca05ee 100644
--- a/river/WindowManager.zig
+++ b/river/WindowManager.zig
@@ -412,7 +412,7 @@ fn renderFinish(wm: *WindowManager) void {
if (window.wm_scheduled.state != .closing) {
window.surfaces.dropSaved();
}
- if (window.destroying) {
+ if (window.impl == .destroying) {
window.destroy();
}
}
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index 2a1725b..f2cebe3 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -238,8 +238,7 @@ fn handleDestroy(listener: *wl.Listener(void)) void {
toplevel.wlr_toplevel.base.surface.data = 0;
const window = toplevel.window;
- window.impl = .none;
- window.destroying = true;
+ window.impl = .destroying;
switch (window.wm_scheduled.state) {
.init, .closing => {},
// This can happen if the xdg toplevel is destroyed after the initial