aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsaac Freund <mail@isaacfreund.com>2023-03-10 14:15:15 +0100
committerIsaac Freund <mail@isaacfreund.com>2023-03-10 14:15:15 +0100
commitfcb184f0bd8153138fd1671b73e72492dcbd7eb8 (patch)
tree4e494d59e8eb35973f071a32b8e594c357e682e7
parentfc6d1cca15f39755e00b2c89501ef3975f63e562 (diff)
downloadriver-fcb184f0bd8153138fd1671b73e72492dcbd7eb8.tar.gz
river-fcb184f0bd8153138fd1671b73e72492dcbd7eb8.tar.xz
View: add `none` impl tag for better safety checks
-rw-r--r--river/View.zig16
-rw-r--r--river/XdgToplevel.zig4
-rw-r--r--river/XwaylandView.zig4
3 files changed, 22 insertions, 2 deletions
diff --git a/river/View.zig b/river/View.zig
index 5589376..48ccadf 100644
--- a/river/View.zig
+++ b/river/View.zig
@@ -46,6 +46,12 @@ pub const Constraints = struct {
const Impl = union(enum) {
xdg_toplevel: XdgToplevel,
xwayland_view: if (build_options.xwayland) XwaylandView else noreturn,
+ /// 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 view.
+ /// The xdg_toplevel could simply be set to undefined instead, but using a
+ /// tag like this gives us better safety checks.
+ none,
};
pub const State = struct {
@@ -163,6 +169,8 @@ post_fullscreen_box: wlr.Box = undefined,
foreign_toplevel_handle: ForeignToplevelHandle = .{},
pub fn create(impl: Impl) error{OutOfMemory}!*Self {
+ assert(impl != .none);
+
const view = try util.gpa.create(Self);
errdefer util.gpa.destroy(view);
@@ -210,6 +218,8 @@ pub fn create(impl: Impl) error{OutOfMemory}!*Self {
/// mark this view for destruction when the transaction completes. Otherwise
/// destroy immediately.
pub fn destroy(view: *Self) void {
+ assert(view.impl == .none);
+
view.destroying = true;
// If there are still saved buffers, then this view needs to be kept
@@ -284,6 +294,7 @@ pub fn configure(self: *Self) bool {
if (build_options.xwayland) return xwayland_view.configure();
unreachable;
},
+ .none => unreachable,
}
}
@@ -292,6 +303,7 @@ pub fn rootSurface(self: Self) *wlr.Surface {
return switch (self.impl) {
.xdg_toplevel => |xdg_toplevel| xdg_toplevel.rootSurface(),
.xwayland_view => |xwayland_view| xwayland_view.rootSurface(),
+ .none => unreachable,
};
}
@@ -362,6 +374,7 @@ pub fn close(self: Self) void {
switch (self.impl) {
.xdg_toplevel => |xdg_toplevel| xdg_toplevel.close(),
.xwayland_view => |xwayland_view| xwayland_view.close(),
+ .none => unreachable,
}
}
@@ -370,6 +383,7 @@ pub fn destroyPopups(self: Self) void {
switch (self.impl) {
.xdg_toplevel => |xdg_toplevel| xdg_toplevel.destroyPopups(),
.xwayland_view => {},
+ .none => unreachable,
}
}
@@ -379,6 +393,7 @@ pub fn getTitle(self: Self) ?[*:0]const u8 {
return switch (self.impl) {
.xdg_toplevel => |xdg_toplevel| xdg_toplevel.getTitle(),
.xwayland_view => |xwayland_view| xwayland_view.getTitle(),
+ .none => unreachable,
};
}
@@ -388,6 +403,7 @@ pub fn getAppId(self: Self) ?[*:0]const u8 {
return switch (self.impl) {
.xdg_toplevel => |xdg_toplevel| xdg_toplevel.getAppId(),
.xwayland_view => |xwayland_view| xwayland_view.getAppId(),
+ .none => unreachable,
};
}
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index 1a9b983..f0bd28e 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -178,7 +178,9 @@ fn handleDestroy(listener: *wl.Listener(void)) void {
// The wlr_surface may outlive the wlr_xdg_surface so we must clean up the user data.
self.xdg_toplevel.base.surface.data = 0;
- self.view.destroy();
+ const view = self.view;
+ view.impl = .none;
+ view.destroy();
}
fn handleMap(listener: *wl.Listener(void)) void {
diff --git a/river/XwaylandView.zig b/river/XwaylandView.zig
index f36e2af..274e8ed 100644
--- a/river/XwaylandView.zig
+++ b/river/XwaylandView.zig
@@ -153,7 +153,9 @@ fn handleDestroy(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandS
self.request_configure.link.remove();
self.set_override_redirect.link.remove();
- self.view.destroy();
+ const view = self.view;
+ view.impl = .none;
+ view.destroy();
}
pub fn handleMap(listener: *wl.Listener(*wlr.XwaylandSurface), xwayland_surface: *wlr.XwaylandSurface) void {