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

commitd863318f37b53cdbca4d01e9a6ad37b2a2e03ea4
parent57c3200cac
authorIsaac Freund <[email protected]>
date2024-12-29 13:24
river: implement river_window_v1.close

 river/Window.zig              | 10 +++++++---
 rivercompat/Seat.zig          |  8 ++++++--
 rivercompat/Window.zig        | 12 ++++++++++++
 rivercompat/WindowManager.zig |  3 +++
 4 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/river/Window.zig b/river/Window.zig
index 35ddbbe..989f526 100644
--- a/river/Window.zig
+++ b/river/Window.zig
@@ -99,7 +99,7 @@ pub const WmState = struct {
     },
     maximized: bool = false,
     fullscreen: bool = false, // XXX output
-    closing: bool = false,
+    close: bool = false,
 };
 
 /// The window management protocol object for this window
@@ -394,7 +394,7 @@ fn handleRequest(
             // XXX send protocol error
             window_v1.destroy();
         },
-        .close => uncommitted.closing = true,
+        .close => uncommitted.close = true,
         .get_node => |args| {
             if (window.node.object != null) {
                 // XXX send protocol error
@@ -453,7 +453,7 @@ pub fn commitWmState(window: *Window) void {
         .capabilities = window.uncommitted.capabilities,
         .maximized = window.uncommitted.maximized,
         .fullscreen = window.uncommitted.fullscreen,
-        .closing = window.uncommitted.closing,
+        .close = window.uncommitted.close,
     };
     window.uncommitted.proposed = null;
 }
@@ -617,6 +617,10 @@ pub fn configure(window: *Window) bool {
 
     assert(!window.destroying);
 
+    if (window.committed.close) {
+        window.close();
+    }
+
     const activated = blk: {
         var it = server.wm.sent.seats.iterator(.forward);
         while (it.next()) |seat| {
diff --git a/rivercompat/Seat.zig b/rivercompat/Seat.zig
index 7b04b7e..bd90e29 100644
--- a/rivercompat/Seat.zig
+++ b/rivercompat/Seat.zig
@@ -35,13 +35,17 @@ const gpa = std.heap.c_allocator;
 wm: *WindowManager,
 seat_v1: *river.SeatV1,
 focused: ?*Window = null,
+link: wl.list.Link,
 
 pub fn create(wm: *WindowManager, seat_v1: *river.SeatV1) void {
     const seat = gpa.create(Seat) catch @panic("OOM");
     seat.* = .{
         .wm = wm,
         .seat_v1 = seat_v1,
+        .link = undefined,
     };
+    wm.seats.append(seat);
+
     seat_v1.setListener(*Seat, handleEvent, seat);
 
     XkbBinding.create(seat, xkb.Keysym.n, .{ .mod4 = true });
@@ -67,8 +71,8 @@ pub fn focusNext(seat: *Seat) void {
         if (seat.wm.windows.length() >= 2) {
             seat.focus(seat.wm.windows.last().?);
         }
-    } else if (seat.wm.windows.first()) |top| {
-        seat.focus(top);
+    } else {
+        seat.focus(seat.wm.windows.first());
     }
 }
 
diff --git a/rivercompat/Window.zig b/rivercompat/Window.zig
index 17b51d6..a5659e3 100644
--- a/rivercompat/Window.zig
+++ b/rivercompat/Window.zig
@@ -49,6 +49,18 @@ fn handleEvent(window_v1: *river.WindowV1, event: river.WindowV1.Event, window:
     switch (event) {
         .closed => {
             window_v1.destroy();
+
+            window.link.remove();
+            {
+                var it = window.wm.seats.iterator(.forward);
+                while (it.next()) |seat| {
+                    if (seat.focused == window) {
+                        seat.focused = null;
+                        seat.focusNext();
+                    }
+                }
+            }
+
             gpa.destroy(window);
         },
         .dimensions => {},
diff --git a/rivercompat/WindowManager.zig b/rivercompat/WindowManager.zig
index b0a42c5..056d039 100644
--- a/rivercompat/WindowManager.zig
+++ b/rivercompat/WindowManager.zig
@@ -28,13 +28,16 @@ const Window = @import("Window.zig");
 
 wm_v1: *river.WindowManagerV1,
 windows: wl.list.Head(Window, .link),
+seats: wl.list.Head(Seat, .link),
 
 pub fn init(wm: *WindowManager, wm_v1: *river.WindowManagerV1) void {
     wm.* = .{
         .wm_v1 = wm_v1,
         .windows = undefined,
+        .seats = undefined,
     };
     wm.windows.init();
+    wm.seats.init();
 
     wm_v1.setListener(*WindowManager, handleEvent, wm);
 }