diff options
| author | user <user@clank> | 2026-08-13 19:39:18 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-13 19:39:18 +0200 |
| commit | ae726b5bb3ff8e9e8f2bef0e9fbc9d4dcb62a79e (patch) | |
| tree | a6cc3f56559c05b812d6bf6998d2b768c8672162 /docs | |
| parent | build: cut the edit loop from 52s to 5s with more codegen units (diff) | |
| download | sl0ppi-ae726b5bb3ff8e9e8f2bef0e9fbc9d4dcb62a79e.tar.gz sl0ppi-ae726b5bb3ff8e9e8f2bef0e9fbc9d4dcb62a79e.tar.xz sl0ppi-ae726b5bb3ff8e9e8f2bef0e9fbc9d4dcb62a79e.zip | |
sl0p: make the split button work on stacked panes too
Reported still dead on a live session after the previous fix. Stacks move the
frame twice more, and neither move was in the hit-test:
- a stack list is drawn over the top rows of its visible member, pushing that
pane's frame down. The renderer applies this as a frame geom override
(reserved_top_rows); the click side did not, so every pane in a stack was
clickable one row above its own title. frame_rect_with_top_reserved() now
applies the same shift, before the gap inset, in the same order as render;
- a stack's collapsed members drew a button on their one-row title. Nothing
could honour it -- that row is the stack's picker, and "split the pane that
is not on screen" is not a thing to ask anyway. They no longer draw one, and
the click side mirrors the condition. 120 snapshot lines change, every one
of them a one-liner losing its button and nothing else (same width, same
content otherwise; audited mechanically).
Both confirmed by reintroducing each bug and watching the check fail. A third
candidate fix -- resolving a click to the stack's visible member, on the theory
that get_pane_at could return a collapsed sibling -- turned out to be
unnecessary: collapsed members have one-row geoms, so position lookup already
lands on the right pane. Removed rather than kept "just in case".
The check itself was wrong twice before it was right, in the direction that
matters most (reporting failures that were its own): it now reads until the pty
goes quiet instead of for a fixed time, and parses only a freshly forced
repaint, so a half-arrived screen cannot look like a button drawn where it is
not. It clicks every button it can see, and runs against config/config.kdl as
well, whose stacks the minimal config never had.
When the two disagree, the server's own log settles it: log::info! in
intercept_split_button_click, read /tmp/sl0ppij-$UID/sl0ppij-log/.
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/HANDOVER.md | 32 | ||||
| -rw-r--r-- | docs/roadmap.md | 23 |
2 files changed, 46 insertions, 9 deletions
diff --git a/docs/HANDOVER.md b/docs/HANDOVER.md index 6f7f89b..7590af8 100644 --- a/docs/HANDOVER.md +++ b/docs/HANDOVER.md @@ -32,6 +32,16 @@ not drawn in: click test proved nothing. There is now `Pane::frame_rect()` — the rect the frame is actually drawn in — and both the button and (already) the status bar buttons derive from it. +5. **Stacks put the frame somewhere else again**, found only after the above + shipped and the button was still dead on a live session: + - a stack list is drawn over the top rows of its visible member, pushing that + pane's frame down (`reserved_top_rows`, applied by the renderer as a frame + geom override). `frame_rect_with_top_reserved()` applies the same shift, or + every pane in a stack is clickable one row above its own title; + - a stack's **collapsed** members drew a button on their one-row title, which + nothing could honour — that row is the stack's picker. They no longer draw + one (120 snapshot lines, all of them exactly that), and the click side + mirrors the condition. The centre-aligned path, the strong lead in the previous handover, was fine. @@ -44,9 +54,25 @@ exist so this cannot come back: multi-client indication is itself a `+`. - `packaging/checks/split-button-live.py` (`make check-live`) — spawns a real session at a pty, reads the glyph off the screen, attaches a second client to - force the middle builder, then clicks the columns it *found the glyph in* and - confirms the split. Verified to fail on the pre-fix commit for both reasons - (button absent with 2 clients; click in the gap does nothing). + force the middle builder, splits and stacks, and then clicks **every** button + it can see, expecting one new pane each time. Run twice: with a minimal config + and with `config/config.kdl`, because the minimal one has no stacks and that + is where the second round of bugs lived. Each fix was confirmed by putting it + back and watching the check fail. + +Two things about that check are load-bearing, both learned the hard way when it +reported failures that were its own fault: + +- **read until the pty goes quiet**, not for a fixed time. A repaint arrives in + many chunks and half of one looks exactly like a button drawn where it is not. +- **force a full repaint (resize) and parse only that**, because the screen + model here is 80 lines of regex, not a terminal, and stale cells from a + previous layout are indistinguishable from real ones. + +When the check and the code disagree, `log::info!` in +`intercept_split_button_click` and read `/tmp/sl0ppij-$UID/sl0ppij-log/` — the +server's own numbers settled it in one run, after an hour of screen-scraping +theories. One more bug fell out of the width assertion: `render_my_focus` built its full and short forms from the same separator vectors, and `Vec::append` drains — so diff --git a/docs/roadmap.md b/docs/roadmap.md index cf7692c..9afed17 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -228,11 +228,15 @@ to hide it: - the title was budgeted before the button, so a title longer than the frame (i.e. any shell showing a path) consumed its columns; - the click hit-tested the pane's allocation while the frame is drawn inset by - the pane gap, putting the clickable columns two to the right of the glyph. + the pane gap, putting the clickable columns two to the right of the glyph; +- and, found after that shipped, stacks move the frame twice more: a stack list + pushes the visible member's frame down by its reserved rows, and the collapsed + members drew a button on a one-row title that nothing could ever honour. The first three are fixed in `ui/pane_boundaries_frame.rs` by reserving the anchored button before anything else and never discarding the right side; the -fourth by `Pane::frame_rect()`, the rect the frame is actually drawn in. +rest by `Pane::frame_rect_with_top_reserved()`, the rect the frame is actually +drawn in, and by not drawing a button on a stack's collapsed members. **How to re-run the check** -- unit tests were necessary and insufficient here for the fourth time, so this one reads the screen: @@ -241,10 +245,17 @@ for the fourth time, so this one reads the screen: make check-live # packaging/checks/split-button-live.py ``` -It starts a session at a pty with the live frame config, finds the `+` on the -frame, attaches a second client (the middle builder), and clicks the columns the -glyph was found in, expecting `2 -> 3` panes. Confirmed to fail on the commit -before the fix, for both the render and the click. +It starts a session at a pty, finds the `+` on the frame, attaches a second +client (the middle builder), splits and stacks, then clicks every button it can +see and expects one new pane per click. It runs twice, with a minimal config and +with `config/config.kdl` -- the real one, whose stacks are where the second +round of bugs was. Every fix was confirmed by reintroducing it and watching the +check fail. + +If it ever disagrees with the code, do not theorise about the screen: put a +`log::info!` in `intercept_split_button_click` and read +`/tmp/sl0ppij-$UID/sl0ppij-log/`. The server's own geometry settles in one run +what screen-scraping cannot. ## Standing risks |
