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

commit7f99e467a7b363a35ab4264cf903e4583613985b
parentc8bc54ac50
authorIsaac Freund <[email protected]>
date2026-03-18 18:16
Window: clear focus on unmap

Currently river doesn't clear focus automatically until the window is
destroyed. This isn't sufficient when windows are kept around and
re-mapped later however.

 river/Seat.zig   |  2 +-
 river/Window.zig | 13 ++++++++++---
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/river/Seat.zig b/river/Seat.zig
index 9bc6eda..68af819 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -720,7 +720,7 @@ pub fn focus(seat: *Seat, new_focus: Focus) void {
 }
 
 /// Send keyboard enter/leave events and handle pointer constraints
-/// This should never normally be called from outside of setFocusRaw(), but we make an exception for
+/// This should never normally be called from outside of focus(), but we make an exception for
 /// XwaylandOverrideRedirect surfaces as they don't conform to the Wayland focus model.
 pub fn keyboardEnterOrLeave(seat: *Seat, target_surface: ?*wlr.Surface) void {
     if (target_surface) |wlr_surface| {
diff --git a/river/Window.zig b/river/Window.zig
index 408e70d..ce1dbc6 100644
--- a/river/Window.zig
+++ b/river/Window.zig
@@ -334,9 +334,7 @@ pub fn destroy(window: *Window) void {
     {
         var it = server.input_manager.seats.iterator(.forward);
         while (it.next()) |seat| {
-            if (seat.focused == .window and seat.focused.window == window) {
-                seat.focus(.none);
-            }
+            assert(seat.focused != .window or seat.focused.window != window);
         }
     }
 
@@ -1147,6 +1145,15 @@ pub fn unmap(window: *Window) void {
         handle.destroy();
         window.foreign_toplevel_handle = null;
     }
+
+    {
+        var it = server.input_manager.seats.iterator(.forward);
+        while (it.next()) |seat| {
+            if (seat.focused == .window and seat.focused.window == window) {
+                seat.focus(.none);
+            }
+        }
+    }
 }
 
 pub fn notifyTitle(window: *Window) void {