fix(ui): let a canvas be sized without collapsing its panel - #106
Merged
Conversation
Canvas ids and widget handles are separate counters that both start at 1, so the same small integer means different things to canvas_* and to the widget functions, and passing one where the other belongs is silent. width(canvas_create(...), 46) therefore pins WIDGET number <canvas id> to 46px. In a three-pane editor that was the inspector panel: it collapsed to roughly the chip's own width and every child reflowed into it. Reproduced here in a three-pane layout, where the wrong call left the panel at 46 and the other two panes measuring 0, and the right call leaves the panel at its full 116 with the chip at exactly the 46 it asked for. Nothing in that picture points at the real mistake, which is why the report reads as the canvas acting as a strut on its parent, and why it could not be reduced: which widget the id collides with depends on construction order, so it only appears in a layout big enough for the collision to land somewhere that matters. canvas_size(id, w, h) takes the id the caller is holding and does the conversion itself, so the natural call is the correct one. canvas_create and canvas_widget now say plainly that the two numbering spaces overlap, that neither rejects the other's numbers, and that canvas_widget is the whole of the boundary between them. The numbering itself is left alone on purpose: 56 spec routes address canvases by their small wire id, and win32 open-codes the same bounds check in 18 places with internal callers that already pass normalized ids, so renumbering there could not be verified from here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…apse # Conflicts: # CHANGELOG.md # ci.sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root cause
Canvas ids and widget handles are separate counters that both start at 1.
canvas_createreturns a canvas id;width/height/fill_width/styletake a widget handle. Neither space rejects the other's numbers, so passing one
where the other belongs does something, silently, to an unrelated widget.
That is exactly what the report ran into:
The chip was the second canvas, so its id was 2, and widget 2 in that editor
was the inspector panel.
Reproduced
A three-pane layout here, reading widths back with
get_width:width(canvas_id, 46)canvas_size(chip, 46, 14)The panel collapses to the chip's width, and in this layout the other two panes
go to 0 as well: the whole layout, not one panel. This also explains why the
reporter could not reduce it. Which widget the id collides with depends on
construction order, so it only shows up in a layout big enough for the
collision to land somewhere that matters, and the symptom, a panel sized like
the canvas, points at the canvas rather than at the id.
Fix
canvas_size(id, w, h)takes the canvas id the caller is holding and does theconversion itself, so the natural call is the correct one.
canvas_create'swidth and height are only a natural size (priority 150, so a canvas can
absorb a stack's slack), which is why a chip needs an explicit one at all.
canvas_createandcanvas_widgetnow state in the API docs that the twonumbering spaces overlap, that neither rejects the other's numbers, and that
canvas_widgetis the whole of the boundary between them.What this deliberately does not do
It does not renumber the id spaces to make the mix-up impossible. That is the
fix that would remove the trap entirely rather than paving over it, and it is
not something I could verify from here:
/canvas/1/click),so the wire numbering has to stay.
open-codes the same bounds check in 18 places, and some internal callers pass
ids that are already normalized. A blind offset there would double-subtract
somewhere and I can only compile-check win32 from this machine.
So the trap is removed for the case that actually bit, and the overlap is
documented at both ends rather than left to be rediscovered.
Verification
aeb .all.aebuilds clean, zero warnings.panelcanvas_demoreportsright=116 chip=46: the panel keeps its width andthe chip gets exactly the size it asked for.
spec_panelcanvas_demoasserts the panel's rows are not squeezed into thechip and that all three panes still have a width. Wired into ci.sh as phase
5e20, so it runs on AppKit and GTK4.
Closes #98
🤖 Generated with Claude Code