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

commit63cc6c655b9dfca40c56414031558c3f79d5cc07
parentf4ea8e977a
authorLucas Galante <[email protected]>
date2026-06-16 12:41
fix(tag): resolve window rendering deadlock when switching tags

 src/server/window_manager.rs | 32 ++++++++++++++++++--------------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index 511859b..97de8fa 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -1087,6 +1087,24 @@ impl WindowManager {
                 }
             }
         }
+        // If the focused window is no longer visible on the active tags, refocus
+        let seats_list = &mut (*self.server).input_manager.seats as *mut ffi::wl_list as *mut WlList;
+        let mut curr_seat = (*seats_list).next;
+        while curr_seat != seats_list {
+            let next_seat = (*curr_seat).next;
+            let seat = crate::container_of!(curr_seat, crate::seat::Seat, link);
+            let mut focused_visible = false;
+            if let crate::seat::Focus::Window(w) = (*seat).focused {
+                if !w.is_null() && !(*w).closed && !(*w).minimized && ((*w).tags & self.active_tags) != 0 {
+                    focused_visible = true;
+                }
+            }
+            if !focused_visible {
+                self.focus_next_visible_window(seat);
+            }
+            curr_seat = next_seat;
+        }
+
         self.update_status();
         self.rendering_scheduled.dirty = true;
     }
@@ -1484,9 +1502,6 @@ impl WindowManager {
                     _ => 1,
                 };
                 self.active_tags = 1 << (tag - 1);
-                if let Some(seat) = self.first_seat() {
-                    self.focus_next_visible_window(seat);
-                }
                 self.dirty_windowing();
             }
             Action::Toggle1 | Action::Toggle2 | Action::Toggle3 | Action::Toggle4 => {
@@ -1501,17 +1516,6 @@ impl WindowManager {
                 if self.active_tags == 0 {
                     self.active_tags = 1;
                 }
-                if let Some(seat) = self.first_seat() {
-                    let mut current_visible = false;
-                    if let crate::seat::Focus::Window(fw) = (*seat).focused {
-                        if !fw.is_null() && !(*fw).closed && ((*fw).tags & self.active_tags) != 0 {
-                            current_visible = true;
-                        }
-                    }
-                    if !current_visible {
-                        self.focus_next_visible_window(seat);
-                    }
-                }
                 self.dirty_windowing();
             }
             Action::SetTag1 | Action::SetTag2 | Action::SetTag3 | Action::SetTag4 => {