atagen

monolith

public
Star0
Watch0

Commit 1c1f70798e98

tarball

atagen <boss@atagen.co>2026-10-22 05:51 UTC

3 files changed+41-6
layout: carry the windows an extended window covers when retagging it

Retagging only the extended window broke the block move_window keeps whole. Its expansion stopped applying on the old tag, so every window it covered popped into view where the user had just been, and it landed on the new tag as a plain tile. set_tag now retags the shown windows in Tree::group, including covered members on other viewed tags, since extending over them already treated them as part of the block.
Modified file: crates/layout/src/lib.rs+14 additions−6 deletions
@@ -729,13 +729,21 @@ impl Layout {
729729 }
730730 }
731731
732- /// Retags a window. It keeps its slot and disappears if the new tag is
733- /// not viewed.
732+ /// Retags a window along with the windows it is extended over. They keep
733+ /// their slots and disappear if the new tag is not viewed.
734734 pub fn set_tag(&mut self, w: WindowId, tag: TagId) {
735- if self.tags.contains_key(tag)
736- && let Some(win) = self.windows.get_mut(w)
737- {
738- win.tag = tag;
735+ let Some(win) = self.windows.get(w) else {
736+ return;
737+ };
738+ if !self.tags.contains_key(tag) {
739+ return;
740+ }
741+ let group = match win.output {
742+ Some(o) => self.outputs[o].tree.group_windows(w, self.vis_on(o)),
743+ None => vec![w],
744+ };
745+ for g in group {
746+ self.windows[g].tag = tag;
739747 }
740748 }
741749
Modified file: crates/layout/src/tests.rs+16 additions
@@ -350,6 +350,22 @@ fn extended_windows_move_their_group() {
350350 assert!(rect(c).right() <= rect(b).x && rect(b).y == rect(c).y);
351351 }
352352
353+#[test]
354+fn retagging_an_extended_window_leaves_hidden_members() {
355+ let (a, b, c, d) = (1, 2, 3, 4);
356+ let shown = |w| w != d;
357+ let mut t: Tree<u32> = Tree::default();
358+ t.insert_row(a);
359+ t.insert_after(b, a);
360+ t.insert_after(c, b);
361+ t.insert_after(d, c);
362+ assert!(t.toggle_expand(b, 0, 1, shown));
363+ let mut group = t.group_windows(b, shown);
364+ group.sort();
365+ assert_eq!(group, [a, b, c]);
366+ assert_eq!(t.group_windows(a, shown), [a]);
367+}
368+
353369 /// A window alone on screen in a container of hidden ones expands among the
354370 /// windows it is shown beside, not inside the container nobody can see.
355371 #[test]
Modified file: crates/layout/src/tree.rs+11 additions
@@ -298,6 +298,17 @@ impl<W: Copy + Eq + Hash> Tree<W> {
298298 self.group(w, &vis).is_some()
299299 }
300300
301+ /// The shown windows in the block `w` moves as, `w` alone when it is not
302+ /// extended.
303+ pub fn group_windows(&self, w: W, vis: impl Fn(W) -> bool) -> Vec<W> {
304+ let Some(g) = self.group(w, &vis) else {
305+ return vec![w];
306+ };
307+ let mut out = Vec::new();
308+ self.shown_leaves(g, &vis, &mut out);
309+ out
310+ }
311+
301312 /// Whether a visible window extended over `w` takes all its room.
302313 pub fn eclipsed(&self, w: W, vis: impl Fn(W) -> bool) -> bool {
303314 let Some(&leaf) = self.leaves.get(&w) else {