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

commit789de762a55ccc9a7dd88f241816592ccb452916
parent2fa36e2266
authorIsaac Freund <[email protected]>
date2025-07-04 22:54
Window: fix destroy post initial commit/pre map (take 2)

I think I've got all the edge cases handled now. Discount "fuzzing"
with `while true; do foot sleep 0.01&; done` no longer hits any
assertion failures.

 river/Window.zig      | 9 +++++++--
 river/XdgToplevel.zig | 3 ++-
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/river/Window.zig b/river/Window.zig
index d63bbd7..9bed396 100644
--- a/river/Window.zig
+++ b/river/Window.zig
@@ -571,6 +571,13 @@ fn handleRequest(
 pub fn manageFinish(window: *Window) bool {
     const wm_requested = &window.wm_requested;
 
+    // This can happen if the window is destroyed after being sent to the wm but
+    // before being mapped.
+    if (window.destroying) {
+        assert(window.wm_scheduled.state == .closing);
+        return false;
+    }
+
     if (!window.initialized) {
         if (wm_requested.dimensions != null) {
             window.initialized = true;
@@ -579,8 +586,6 @@ pub fn manageFinish(window: *Window) bool {
         }
     }
 
-    assert(!window.destroying);
-
     window.configure_scheduled.ssd = wm_requested.ssd;
     window.configure_scheduled.tiled = wm_requested.tiled;
     window.configure_scheduled.capabilities = wm_requested.capabilities;
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index e443884..2a1725b 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -248,7 +248,8 @@ fn handleDestroy(listener: *wl.Listener(void)) void {
         // called due to the window not being mapped.
         .ready => {
             assert(!window.mapped);
-            window.wm_scheduled.state = .init;
+            window.wm_scheduled.state = .closing;
+            server.wm.dirtyWindowing();
         },
     }
 }