Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
xdg-toplevel: handle destroy before xdg-decoration
river/XdgDecoration.zig | 15 ++++++++++-----
river/XdgToplevel.zig | 5 +++++
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/river/XdgDecoration.zig b/river/XdgDecoration.zig
index 91ab481..cfbb0e8 100644
--- a/river/XdgDecoration.zig
+++ b/river/XdgDecoration.zig
@@ -52,11 +52,7 @@ pub fn init(wlr_decoration: *wlr.XdgToplevelDecorationV1) void {
xdg_toplevel.view.pending.ssd = ssd;
}
-fn handleDestroy(
- listener: *wl.Listener(*wlr.XdgToplevelDecorationV1),
- _: *wlr.XdgToplevelDecorationV1,
-) void {
- const decoration = @fieldParentPtr(XdgDecoration, "destroy", listener);
+pub fn deinit(decoration: *XdgDecoration) void {
const xdg_toplevel: *XdgToplevel = @ptrFromInt(decoration.wlr_decoration.toplevel.base.data);
decoration.destroy.link.remove();
@@ -66,6 +62,15 @@ fn handleDestroy(
xdg_toplevel.decoration = null;
}
+fn handleDestroy(
+ listener: *wl.Listener(*wlr.XdgToplevelDecorationV1),
+ _: *wlr.XdgToplevelDecorationV1,
+) void {
+ const decoration = @fieldParentPtr(XdgDecoration, "destroy", listener);
+
+ decoration.deinit();
+}
+
fn handleRequestMode(
listener: *wl.Listener(*wlr.XdgToplevelDecorationV1),
_: *wlr.XdgToplevelDecorationV1,
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index 7560e25..e2105c3 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -193,6 +193,11 @@ pub fn destroyPopups(self: Self) void {
fn handleDestroy(listener: *wl.Listener(void)) void {
const self = @fieldParentPtr(Self, "destroy", listener);
+ // This can be be non-null here if the client commits a protocol error or
+ // if it exits without destroying its wayland objects.
+ if (self.decoration) |*decoration| {
+ decoration.deinit();
+ }
assert(self.decoration == null);
// Remove listeners that are active for the entire lifetime of the view