git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit92400fe7c4a0ab5240c5e3956092d14dae4ae77e
parent845a1a7b36
authorIsaac Freund <ifreund@ifreund.xyz>
date2021-06-17 20:57
xdg-toplevel: remove listeners before view destroy

Currently in handleUnmap() we call View.unmap() before removing
listeners. However View.unmap() may destroy the view before returning
if the transaction started doesn't have to wait on any configures.

To ensure that we don't try to remove listeners which have already been
free'd, do this before calling View.unmap().

 river/Root.zig        | 3 +--
 river/View.zig        | 3 +++
 river/XdgToplevel.zig | 4 ++--
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/river/Root.zig b/river/Root.zig
index a74d0eef..3ea79cff 100644
--- a/river/Root.zig
+++ b/river/Root.zig
@@ -384,13 +384,12 @@ fn commitTransaction(self: *Self) void {
         var view_it = output.views.first;
         while (view_it) |view_node| {
             const view = &view_node.view;
+            view_it = view_node.next;
 
             if (view.destroying) {
-                view_it = view_node.next;
                 view.destroy();
                 continue;
             }
-            defer view_it = view_node.next;
 
             if (view.pending_serial != null and !view.shouldTrackConfigure()) continue;
 
diff --git a/river/View.zig b/river/View.zig
index 816c72e7..5b577748 100644
--- a/river/View.zig
+++ b/river/View.zig
@@ -19,6 +19,7 @@ const Self = @This();
 
 const build_options = @import("build_options");
 const std = @import("std");
+const assert = std.debug.assert;
 const math = std.math;
 const os = std.os;
 const wlr = @import("wlroots");
@@ -486,7 +487,9 @@ pub fn map(self: *Self) void {
 pub fn unmap(self: *Self) void {
     log.debug("view '{s}' unmapped", .{self.getTitle()});
 
+    assert(!self.destroying);
     self.destroying = true;
+
     if (self.saved_buffers.items.len == 0) self.saveBuffers();
 
     if (self.opacity_timer != null) {
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index 96b618bf..ca360c36 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -248,8 +248,6 @@ fn handleMap(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wlr.XdgSurfa
 fn handleUnmap(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wlr.XdgSurface) void {
     const self = @fieldParentPtr(Self, "unmap", listener);
 
-    self.view.unmap();
-
     // Remove listeners that are only active while mapped
     self.commit.link.remove();
     self.request_fullscreen.link.remove();
@@ -257,6 +255,8 @@ fn handleUnmap(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wlr.XdgSur
     self.request_resize.link.remove();
     self.set_title.link.remove();
     self.set_app_id.link.remove();
+
+    self.view.unmap();
 }
 
 /// Called when the surface is comitted