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

commit83cde3679a37c605085c81488fea5263d5db57b7
parented2666268a
authorIsaac Freund <[email protected]>
date2025-01-09 09:26
Window: ensure closed is sent in update sequence

 river/Window.zig | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/river/Window.zig b/river/Window.zig
index 833fc7a..4839e47 100644
--- a/river/Window.zig
+++ b/river/Window.zig
@@ -249,19 +249,23 @@ pub fn create(impl: Impl) error{OutOfMemory}!*Window {
 /// mark this window for destruction when the transaction completes. Otherwise
 /// destroy immediately.
 pub fn destroy(window: *Window, when: enum { lazy, assert }) void {
-    // We can't assert(window.wm_pending.state != .ready) since the client may
-    // have exited after making its empty initial commit but before the surface
-    // is mapped.
     assert(window.impl == .none);
     assert(!window.mapped);
 
-    // We may need to send the closed event and make the window_v1/node_v1 objects
-    // inert here if the client exits after the empty initial commit but before
-    // the window is mapped.
-    window.makeInert();
-
     window.destroying = true;
 
+    // We can't assert(window.wm_pending.state != .ready) since the client may
+    // have exited after making its empty initial commit but before the surface
+    // is mapped.
+    switch (window.wm_pending.state) {
+        .init => {},
+        .closing, .ready => {
+            window.wm_pending.state = .closing;
+            server.wm.dirtyPending();
+            return;
+        },
+    }
+
     {
         var it = server.input_manager.seats.iterator(.forward);
         while (it.next()) |seat| {
@@ -364,7 +368,7 @@ pub fn sendDirty(window: *Window) void {
             window.node.link_inflight.remove();
             window.node.link_inflight.init();
 
-            window.close();
+            window.makeInert();
         },
         .ready => {
             const wm_v1 = server.wm.object orelse return;
@@ -441,7 +445,7 @@ pub fn sendDirty(window: *Window) void {
     }
 }
 
-pub fn makeInert(window: *Window) void {
+fn makeInert(window: *Window) void {
     if (window.object) |window_v1| {
         window.object = null;
         window_v1.sendClosed();