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