atagen

monolith

public
Star0
Watch0

Commit bae1138a3e88

tarball

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

3 files changed+16-14
launch: put windows on homeless unless something places them

Since 1cf303f made focus at map time the last resort, any window without a rule, token, parent, spawn record or owning ancestor fell to launch_tag, which picked the first viewed tag whenever the focus was on homeless. Viewing an empty tag 1 then pulled every unattributed window onto it. launch_tag now follows the focused window's tag even when that is homeless, and unattributed windows only take the focused output.
Modified file: crates/layout/src/lib.rs+7 additions−8 deletions
@@ -302,16 +302,13 @@ impl Layout {
302302 }
303303 }
304304
305- /// The tag a launch from `o` belongs to. The focused window's tag, else
306- /// the first viewed tag, else homeless. Homeless is always on screen, so
307- /// focusing one of its windows does not mean the user left their tag.
305+ /// The tag a launch from `o` belongs to, the focused window's tag or else
306+ /// homeless.
308307 pub fn launch_tag(&self, o: OutputId) -> TagId {
309308 self.focused_on(o)
310309 .map(|w| &self.windows[w])
311- .filter(|w| w.scratchpad.is_none() && !w.sticky && w.tag != self.homeless)
312- .map(|w| w.tag)
313- .or_else(|| self.outputs.get(o)?.viewed.first().copied())
314- .unwrap_or(self.homeless)
310+ .filter(|w| w.scratchpad.is_none() && !w.sticky)
311+ .map_or(self.homeless, |w| w.tag)
315312 }
316313
317314 pub fn view_everywhere(&mut self, tag: TagId) {
@@ -777,7 +774,9 @@ impl Layout {
777774 };
778775 if let Some(s) = win.scratchpad {
779776 let o = win.output.or(self.active);
780- let tag = o.map_or(self.homeless, |o| self.launch_tag(o));
777+ let tag = o
778+ .and_then(|o| self.outputs.get(o)?.viewed.first().copied())
779+ .unwrap_or(self.homeless);
781780 self.leave_scratchpad(s, w);
782781 let win = &mut self.windows[w];
783782 win.output = o;
Modified file: crates/monolith/src/launch.rs+7 additions−4 deletions
@@ -1,7 +1,8 @@
11 //! Launch context. A window goes to the output and tag the user was on when
22 //! its launch began. Its process and then each ancestor is matched against
33 //! processes that own a mapped window and the programs monolith spawned, the
4-//! nearest match deciding, and the focus at map time is the last resort.
4+//! nearest match deciding. Anything unmatched goes to the homeless tag on
5+//! the focused output.
56
67 use crate::state::State;
78 use monolith_layout::{OutputId, TagId};
@@ -48,10 +49,12 @@ impl State {
4849 /// Where the window of process `pid` belongs. The nearest of `pid` and
4950 /// its ancestors that owns a mapped window decides, so a program's later
5051 /// windows follow its first one wherever the user moved it. Failing that
51- /// the nearest program monolith spawned recently, then the focus now.
52+ /// the nearest program monolith spawned recently, then the homeless tag
53+ /// on the focused output.
5254 pub fn launch_of(&self, pid: Option<u32>) -> (Option<OutputId>, TagId) {
55+ let unknown = || (self.wm.layout.active_output(), self.wm.layout.homeless());
5356 let Some(pid) = pid else {
54- return self.launch_context();
57+ return unknown();
5558 };
5659 let owners: Vec<(u32, OutputId, TagId)> = self
5760 .wm
@@ -71,7 +74,7 @@ impl State {
7174 .map(|&(_, output, tag)| (Some(output), tag))
7275 .or_else(|| self.services.launches.get(p))
7376 })
74- .unwrap_or_else(|| self.launch_context())
77+ .unwrap_or_else(unknown)
7578 }
7679
7780 pub fn window_pid(&self, window: &smithay::desktop::Window) -> Option<u32> {
Modified file: design/decisions.md+2 additions−2 deletions
@@ -78,9 +78,9 @@ Running log of settled decisions and open questions. Research backing lives in `
7878
7979 - Interrupts replan, they never stack. No plan-length cap.
8080 - Velocity matching is best-effort, applied only where the replan continues the current axis.
81-- Launch context resolves through a graceful ranking. Window rule, xdg-activation token, parent toplevel, tracked systemd scope or cgroup, PID ancestry, focus at map time. The target is where the user was when the launch command began. Windows placed on an unviewed tag mark it urgent.
81+- Launch context resolves through a graceful ranking. Window rule, xdg-activation token, parent toplevel, tracked systemd scope or cgroup, PID ancestry, then the focused output with the homeless tag. The target is where the user was when the launch command began. Windows placed on an unviewed tag mark it urgent.
8282 - Nested sessions are a first-class, permanently supported backend.
83-- A launch belongs to the focused window's tag, unless that is homeless, then to the first viewed tag. Homeless is always on screen, so focusing its windows does not mean the user left their tag.
83+- A launch belongs to the focused window's tag, homeless included, and to homeless when nothing is focused. A window nothing attributes lands on homeless on the focused output, never on a viewed tag by default (reversed 2026-10-19).
8484 - VRR defaults to `fullscreen`, on only while a fullscreen window shows on a capable output. Under VRR frames go out as soon as there is something new, and cursor-only frames are capped at 60 Hz.
8585 - Layer-shell exclusive zones are insets on the layout output, so fullscreen still covers the whole output. The top layer hides under fullscreen, the overlay layer does not.
8686 - An activation token takes focus only if monolith made it or its requester held the keyboard, and only within 10 s. Otherwise the window is marked urgent. A token arriving before a window's first buffer may still move it to its launch context unless a rule placed it.