Commit ae47743b5745
tarball2 files changed+45-11
@@ -418,20 +418,21 @@ fn moving_toward_a_stack_showing_one_window_swaps() {
418418
assert_eq!(rect(a).h, AREA.h);419419
}420420
421
-/// A move either changes what is on screen or changes nothing at all. Steps422
-/// around hidden windows used to succeed invisibly and eat the keypress.421
+/// A move either changes what is on screen or changes nothing at all, and a422
+/// window move never rearranges hidden windows among themselves. Steps around423
+/// hidden windows used to succeed invisibly and eat the keypress.423424
#[test]424425
fn moves_are_seen_or_undone() {425426
let dirs = [Dir::Left, Dir::Right, Dir::Up, Dir::Down];426427
let mut runner = proptest::test_runner::TestRunner::deterministic();427
- let ops = prop::collection::vec((0u8..4, 0u8..4, 0u8..3, any::<bool>()), 1..14);428
+ let ops = prop::collection::vec((0u8..4, 0u8..4, 0u8..4, 0u8..32), 1..14);428429
for _ in 0..2000 {429430
let seq = proptest::strategy::ValueTree::current(&ops.new_tree(&mut runner).unwrap());430431
let mut t: Tree<u32> = Tree::default();431432
t.insert_row(0);432433
let mut n = 1;433434
for &(w, d, kind, hide) in &seq {434
- let vis = |x: u32| !(hide && x == 0);435
+ let vis = |x: u32| hide & (1 << x) == 0;435436
if kind == 0 && n < 5 {436437
t.insert_after(n, u32::from(w) % n);437438
n += 1;@@ -448,13 +449,24 @@ fn moves_are_seen_or_undone() {
448449
v449450
};450451
let before = shown(&t);451
- let moved = if kind == 1 {452
- t.merge_window(w, dirs[usize::from(d)], vis)453
- } else {454
- t.move_window(w, dirs[usize::from(d)], vis)452
+ let hidden = |t: &Tree<u32>| {453
+ let mut t = t.clone();454
+ t.retain(|x| !vis(x));455
+ t.shape()456
+ };457
+ let rest = hidden(&t);458
+ let d = dirs[usize::from(d)];459
+ let moved = match kind {460
+ 1 => t.merge_window(w, d, vis),461
+ 2 => t.move_window(w, d, vis),462
+ 3 => t.move_container(w, d, vis),463
+ _ => continue,455464
};456465
t.check();457466
assert_eq!(moved, shown(&t) != before, "{seq:?}");467
+ if kind != 3 {468
+ assert_eq!(hidden(&t), rest, "{seq:?}");469
+ }458470
}459471
}460472
}@@ -187,7 +187,7 @@ impl<W: Copy + Eq + Hash> Tree<W> {
187187
/// visible sibling, enter a sibling container, or step out beside their188188
/// container. Hidden windows never move.189189
pub fn move_window(&mut self, w: W, dir: Dir, vis: impl Fn(W) -> bool) -> bool {190
- let Some(&n) = self.leaves.get(&w) else {190
+ let Some(&n) = self.leaves.get(&w).filter(|_| vis(w)) else {191191
return false;192192
};193193
self.until_seen(&vis, |t| {@@ -199,7 +199,7 @@ impl<W: Copy + Eq + Hash> Tree<W> {
199199
/// Moves the container holding `w` as a rigid block. A window sitting200200
/// directly in the root is its own block.201201
pub fn move_container(&mut self, w: W, dir: Dir, vis: impl Fn(W) -> bool) -> bool {202
- let Some(&n) = self.leaves.get(&w) else {202
+ let Some(&n) = self.leaves.get(&w).filter(|_| vis(w)) else {203203
return false;204204
};205205
self.until_seen(&vis, |t| {@@ -217,7 +217,7 @@ impl<W: Copy + Eq + Hash> Tree<W> {
217217
/// sibling lane that way leaves its stack as `move_window` would, so it218218
/// takes one press to step out and another to merge.219219
pub fn merge_window(&mut self, w: W, dir: Dir, vis: impl Fn(W) -> bool) -> bool {220
- let Some(&n) = self.leaves.get(&w) else {220
+ let Some(&n) = self.leaves.get(&w).filter(|_| vis(w)) else {221221
return false;222222
};223223
self.until_seen(&vis, |t| {@@ -779,6 +779,28 @@ impl<W: Copy + Eq + Hash> Tree<W> {
779779
}780780
781781
#[cfg(test)]782
+ pub(crate) fn shape(&self) -> String783
+ where784
+ W: std::fmt::Debug,785
+ {786
+ fn go<W: Copy + Eq + Hash + std::fmt::Debug>(t: &Tree<W>, n: NodeId) -> String {787
+ match &t.nodes[n].kind {788
+ Kind::Leaf(w, [x, y]) => format!("{w:?}[{x:.6},{y:.6}]"),789
+ Kind::Container {790
+ axis,791
+ children,792
+ expanded,793
+ } => {794
+ let inner: Vec<String> = children.iter().map(|&c| go(t, c)).collect();795
+ let e = expanded.and_then(|e| children.iter().position(|&c| c == e));796
+ format!("{axis:?}{e:?}({})", inner.join(" "))797
+ }798
+ }799
+ }800
+ self.root.map(|r| go(self, r)).unwrap_or_default()801
+ }802
+803
+ #[cfg(test)]782804
pub(crate) fn check(&self) {783805
let reachable = match self.root {784806
Some(r) => {