atagen

monolith

public
Star0
Watch0

Commit f50ebc6999a6

tarball

atagen <boss@atagen.co>2026-10-19 07:51 UTC

3 files changed+16-0
layout: focus a window that goes fullscreen over the focused one

A client turning fullscreen on itself, over xdg or X11, left keyboard focus on a window it now covered, which is invisible but still typed into. Layout::focus_if_covering moves focus to it unless the focused window is its own transient, so a dialog stays usable.
Modified file: crates/layout/src/lib.rs+14 additions
@@ -763,6 +763,20 @@ impl Layout {
763763 false
764764 }
765765
766+ /// Moves focus to a fullscreen `w` when it covers the focused window,
767+ /// unless that is one of its own transients.
768+ pub fn focus_if_covering(&mut self, w: WindowId) {
769+ let Some(win) = self.windows.get(w).filter(|win| win.fullscreen) else {
770+ return;
771+ };
772+ let covers = self.focused().is_some_and(|f| {
773+ f != w && self.windows[f].output == win.output && !self.descends(f, w)
774+ });
775+ if covers && self.visible(w) {
776+ self.focus(w);
777+ }
778+ }
779+
766780 /// Whether a fullscreen window on `w`'s output hides it. The fullscreen
767781 /// window's transients are not hidden, and a window that is itself
768782 /// fullscreen takes over.
Modified file: crates/monolith/src/xdg.rs+1 additions
@@ -131,6 +131,7 @@ impl State {
131131 .is_some_and(|w| w.fullscreen != on);
132132 if toggled {
133133 self.wm.layout.toggle_fullscreen(id);
134+ self.wm.layout.focus_if_covering(id);
134135 }
135136 if target.is_some() || toggled {
136137 self.apply_layout();
Modified file: crates/monolith/src/xwayland.rs+1 additions
@@ -396,6 +396,7 @@ impl State {
396396 .is_some_and(|w| w.fullscreen != on)
397397 {
398398 self.wm.layout.toggle_fullscreen(id);
399+ self.wm.layout.focus_if_covering(id);
399400 self.apply_layout();
400401 }
401402 }