Skip to content

fix(agent): press a control the renderer laid out flat - #54

Merged
pathscale merged 1 commit into
masterfrom
fix/click-a-control-with-no-area
Sep 7, 2026
Merged

pathscale merged 1 commit into
masterfrom
fix/click-a-control-with-no-area

Conversation

@pathscale

Copy link
Copy Markdown
Owner

What was wrong

AgentAction::Click is dispatched at a node id: activate_agent_node sends every phase with DomEvent::new(node_id, ..). The coordinate it resolves first is only the number the event carries in clientX/clientY.

It shared resolve_agent_node with Hover, which really does move a pointer to a point — and that resolver refused any node whose box had no area. One predicate standing for two facts, and the wrong one won for a whole class of control.

What it cost

Anything sized entirely by its label lays out at zero height on a host with no font catalogue — which is what a Linux CI runner is, and what qa-inspect-host is on any platform since it stopped enabling system-fonts.

Measured on the @pathscale/ui component sweep, same page, same build, only the font catalogue differing:

control no fonts fonts
button:Open dialog 0x0, hidden 78x24, visible
button:Open popover 0x0, hidden 92x24, visible
link:Link 0x0, hidden 25x20, visible
button:Collapsible 0x0, hidden 71x24, visible
button:Send (Composer) 0x0, hidden 31x21, visible

All five are attached, styled visible, enabled, with working handlers. All five were unpressable for want of a coordinate none of them would have used. A <Button> was unaffected: its padding gives it 26x36 with no glyph at all.

The change

The area requirement is a parameter. Hover keeps it, and now says why it failed (no layout box a pointer can reach); Click and DoubleClick do not.

Everything that is a genuine reason not to press still refuses: the node must exist, be attached with a valid layout ancestry, not be display: none / visibility: hidden / hidden / aria-hidden, and not be disabled. None of those is a box size.

Tests

Three, with the degenerate case asserted before the behaviour so a pass cannot be vacuous:

  • a control with no area is pressable
  • the same control still refuses a hover — this is why the requirement became a parameter rather than being deleted
  • a display: none control is still refused

cargo test -p tauri-runtime-blitz --all-features — 41 pass, 0 fail. cargo clippy --all-targets --all-features -D warnings — clean.

Note on the snapshot's visible

SemanticNode.visible is node_is_visible(..) && rect has area, so it conflates "the author hid this" with "the renderer gave it no area". That is why this was hard to see: a display:none control and a flat one are indistinguishable to a consumer. Not changed here — it is a protocol-shaped decision — but worth recording.

`Click` is dispatched at a node id: `activate_agent_node` sends every phase
with `DomEvent::new(node_id, ..)`, and the coordinate it resolves first is only
the number the event carries in `clientX`/`clientY`. It shared its resolver
with `Hover`, which really does move a pointer to a point, and that resolver
refused any node whose box had no area.

So one predicate stood for two facts, and the wrong one won for a whole class
of control. Anything sized entirely by its label -- a bare `<a>`, a trigger
with no padding -- lays out at zero height on a host with no font catalogue,
which is what a Linux CI runner is and what `qa-inspect-host` is on any
platform since it stopped enabling `system-fonts`. Measured on the
@pathscale/ui sweep: Dialog's and Popover's triggers, Link, Collapsible and
Composer's Send all report `0x0` with no fonts and `78x24`, `92x24`, `25x20`,
`71x24` and `31x21` with them. Attached, styled visible, enabled, handlers
intact; unpressable for want of a coordinate none of them would have used.

The requirement is a parameter now. `Hover` keeps it and says why it failed;
`Click` and `DoubleClick` do not. Everything that is a reason not to press
still refuses: the node must exist, be attached with valid layout ancestry,
not be `display: none`, `visibility: hidden`, `hidden` or `aria-hidden`, and
not be disabled. None of those is a box size.

Three tests, with the degenerate case asserted first so a pass cannot be
vacuous: a flat control is pressable, the same control still refuses a hover,
and a `display: none` control is still refused outright.
@pathscale
pathscale merged commit 6b9634f into master Sep 7, 2026
3 checks passed
@pathscale
pathscale deleted the fix/click-a-control-with-no-area branch September 7, 2026 11:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant