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

commit6d34e61d619a877ed470bbbfde0d59cc0efea47a
parentd77a94bec2
authorLucas Galante <[email protected]>
date2026-08-08 15:55
fix: status feed reports Focus::None honestly

focused_window() falls back to the most recent real window so the bar
doesn't flash while overlay UI briefly holds focus — but that fallback
also swallowed explicit Focus::None (a desktop click), leaving the bar
showing the last window as if it still had focus while keystrokes went
nowhere. build_status_update now bypasses the fallback when the seat
focus is literally None; the overlay case keeps it.

Co-Authored-By: Claude Fable 5 <[email protected]>

 src/server/status_server.rs | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/src/server/status_server.rs b/src/server/status_server.rs
index 5df62b4..6ceab64 100644
--- a/src/server/status_server.rs
+++ b/src/server/status_server.rs
@@ -296,7 +296,21 @@ fn format_for_subscription(sub: Subscription, update: &StatusUpdate) -> String {
 }
 
 pub unsafe fn build_status_update(wm: &crate::window_manager::WindowManager) -> StatusUpdate {
-    let focused_window = wm.focused_window();
+    // `focused_window()` falls back to the most recent real window so the
+    // bar doesn't flash while overlay UI (the launcher) briefly holds
+    // focus. But an explicit Focus::None (desktop click) is a real,
+    // user-visible state — keystrokes go nowhere — and the status feed
+    // must report it honestly instead of showing the last window as if it
+    // still had focus.
+    let seat_focus_is_none = wm
+        .first_seat()
+        .map(|s| matches!((*s).focused, crate::seat::Focus::None))
+        .unwrap_or(false);
+    let focused_window = if seat_focus_is_none {
+        std::ptr::null_mut()
+    } else {
+        wm.focused_window()
+    };
 
     let text = format!("Mode: {:?} | Zoom: {:.2} | Pan: ({:.0}, {:.0})", wm.mode, wm.desk_zoom, wm.desk_pan_x, wm.desk_pan_y);
     let escaped = text.replace('\\', "\\\\").replace('"', "\\\"");