atagen

monolith

public
Star0
Watch0

Commit 0dfd45c37ecb

tarball

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

2 files changed+22-5
xdg: tile windows whose size cap is larger than the output

floats() floated every toplevel with a maximum size, including clients that declare an effectively unbounded one. A cap now only floats a window when it is smaller than the whole usable area, the largest tile the window could be given.
Modified file: crates/monolith/src/windows.rs+15 additions−2 deletions
@@ -47,7 +47,11 @@ impl State {
4747 f64::from(r.size.h),
4848 )
4949 });
50- let auto = float.is_some() || window.toplevel().is_some_and(crate::xdg::floats);
50+ let room = self.room(output);
51+ let auto = float.is_some()
52+ || window
53+ .toplevel()
54+ .is_some_and(|t| crate::xdg::floats(t, room));
5155 let floating = rule.floating.unwrap_or(auto);
5256 let id = self
5357 .wm
@@ -85,6 +89,14 @@ impl State {
8589 self.apply_layout();
8690 }
8791
92+ /// The size of the largest tile a window on `output`, or the active one,
93+ /// could get.
94+ fn room(&self, output: Option<OutputId>) -> Option<(f64, f64)> {
95+ let layout = &self.wm.layout;
96+ let usable = layout.output(output.or(layout.active_output())?)?.usable();
97+ Some((usable.w, usable.h))
98+ }
99+
88100 /// Where a transient of `parent` belongs, which is where its parent is.
89101 /// A scratchpad or sticky parent has no tag of its own to follow.
90102 fn parent_context(&self, parent: Option<WindowId>) -> Option<(Option<OutputId>, TagId)> {
@@ -250,11 +262,12 @@ impl State {
250262 /// or fixed-size. At its first buffer it is still held on its seed, so it
251263 /// never shows tiled.
252264 pub(crate) fn float_if_hinted(&mut self, id: WindowId) -> bool {
265+ let room = self.room(self.wm.layout.window(id).and_then(|w| w.output));
253266 let hinted = self
254267 .wm
255268 .window(id)
256269 .and_then(|w| w.toplevel())
257- .is_some_and(crate::xdg::floats);
270+ .is_some_and(|t| crate::xdg::floats(t, room));
258271 let tiled = self
259272 .wm
260273 .layout
Modified file: crates/monolith/src/xdg.rs+7 additions−3 deletions
@@ -19,10 +19,14 @@ use smithay::wayland::shell::xdg::{
1919 };
2020 use smithay::wayland::xdg_foreign::{XdgForeignHandler, XdgForeignState};
2121
22-/// Dialogs, and windows that cap their size and so could never fill a tile.
23-pub fn floats(toplevel: &ToplevelSurface) -> bool {
22+/// Dialogs, and windows that cap their size below `room`, the largest tile they
23+/// could be given, and so could never fill it.
24+pub fn floats(toplevel: &ToplevelSurface, room: Option<(f64, f64)>) -> bool {
2425 let (_, max) = size_hints(toplevel);
25- is_dialog(toplevel) || (max.w > 0 && max.h > 0)
26+ let capped = max.w > 0
27+ && max.h > 0
28+ && room.is_none_or(|(w, h)| f64::from(max.w) < w || f64::from(max.h) < h);
29+ is_dialog(toplevel) || capped
2630 }
2731
2832 /// A toplevel with a parent, whether set through xdg_shell or xdg-foreign, or