aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authoruser <user@clank>2026-08-14 20:47:39 +0200
committeruser <user@clank>2026-08-14 20:47:39 +0200
commit0260c1c40ba7b2fec58d99ea6daa35f8152e67d0 (patch)
tree420c258370022b6d94f9b51fe366326bf133d81e /tests
parentsl0ppty: drag the crossing to resize both ways (diff)
downloadslosh-0260c1c40ba7b2fec58d99ea6daa35f8152e67d0.tar.gz
slosh-0260c1c40ba7b2fec58d99ea6daa35f8152e67d0.tar.xz
slosh-0260c1c40ba7b2fec58d99ea6daa35f8152e67d0.zip
sl0ppty: hold the boundaries, not a seat number
Three faults in the corner drag, reported as glitches and picking panes up along the way. The drag held an index into the corner list, and that list is rebuilt from the layout every frame — by a drag whose entire job is changing the layout. Move the crossing and the corners are recomputed: the entry you grabbed can shift position, or stop being a corner, and the index then names somebody else's boundaries. That is exactly "it picks up additional panes and loses them again", and it is the rule this codebase already states about the rect and the collapsed flag, applied to something I stored anyway. The drag now carries the boundaries themselves, so it moves what you grabbed until you let go, whatever the layout does underneath. The test drags a deliberately misaligned grid in circles and checks the boundary that was never part of the crossing is untouched throughout. The redraw was the dwell list again. Anything that arms after the pointer rests has to be named in app_next_deadline_ms or it only appears when something else happens to repaint — so it looked intermittent, which is the worst way for it to be wrong. "corner:" is in the list now, next to the three that were already there for the same reason. And a crossing is two cells wide with nothing about it to suggest it is anything, so it marks itself the moment the pointer arrives, before the dwell that arms both boundaries. Passing over one costs a character; resting on one still explains itself.
Diffstat (limited to 'tests')
-rw-r--r--tests/test_corner.py52
1 files changed, 52 insertions, 0 deletions
diff --git a/tests/test_corner.py b/tests/test_corner.py
index a6cef10..83645bc 100644
--- a/tests/test_corner.py
+++ b/tests/test_corner.py
@@ -137,10 +137,62 @@ def test_the_hint_says_both_ways():
os.unlink(l)
+def test_a_drag_keeps_the_boundaries_it_grabbed():
+ """The corner list is rebuilt from the layout every frame, and a drag is
+ the thing changing the layout. Holding an index into it would mean the
+ crossing you grabbed becoming a different entry halfway through -- picking
+ up panes you never touched, and dropping the ones you did."""
+ l = lay(GRID)
+ with Session(SH, cols=70, rows=22, layout=l) as s:
+ s.settle(30)
+ ids = sorted(rects(s))
+ # Put the two column boundaries out of line, so only one of them
+ # belongs to the crossing.
+ s.api("focus", id=ids[2])
+ s.settle(10)
+ for _ in range(4):
+ s.send(r"\x01L")
+ s.settle(30)
+
+ w0 = {p["id"]: p["w"] for p in s.panes()}
+ c = corners(s)[0]
+ s.send(rf"\e[<0;{c['x'] + 1};{c['y'] + 1}M")
+ for step in range(1, 9): # wander, so the layout keeps changing
+ s.send(rf"\e[<32;{c['x'] + 1 + step};{c['y'] + 1 + (step % 3)}M")
+ s.settle(15)
+ s.send(rf"\e[<0;{c['x'] + 9};{c['y'] + 3}m")
+ s.settle(30)
+ w1 = {p["id"]: p["w"] for p in s.panes()}
+
+ top, bottom = ids[:2], ids[2:]
+ check("the boundary it grabbed moved",
+ [w1[i] for i in top] != [w0[i] for i in top],
+ f"{[w0[i] for i in top]} -> {[w1[i] for i in top]}")
+ check("and the one out of line with it was never picked up",
+ [w1[i] for i in bottom] == [w0[i] for i in bottom],
+ f"{[w0[i] for i in bottom]} -> {[w1[i] for i in bottom]}")
+ os.unlink(l)
+
+
+def test_the_crossing_shows_itself_before_you_rest_on_it():
+ l = lay(GRID)
+ with Session(SH, cols=60, rows=20, layout=l) as s:
+ s.settle(30)
+ c = corners(s)[0]
+ s.send(rf"\e[<35;{c['x'] + 1};{c['y'] + 1}M")
+ s.settle(40) # no dwell
+ check("a crossing two cells wide says it is there straight away",
+ CROSS in s.snapshot().screen(), repr(s.snapshot().line(c["y"])))
+ check("without arming the boundaries yet",
+ "\u250a" not in s.snapshot().screen(), "")
+
+
if __name__ == "__main__":
test_a_grid_has_a_corner_where_the_boundaries_cross()
test_a_layout_with_no_crossing_has_no_corner()
test_dragging_it_moves_both_boundaries()
test_resting_on_it_arms_both_boundaries()
test_the_hint_says_both_ways()
+ test_a_drag_keeps_the_boundaries_it_grabbed()
+ test_the_crossing_shows_itself_before_you_rest_on_it()
sys.exit(report())