Expand description
What a screen reader is told, and where each of those things actually is.
build_semantics_tree_from_applier answers the first half and carries no
geometry at all; a LayoutBox carries the geometry and knows nothing about
semantics. Every question of the form “is this control big enough / on the
display / where the label says it is” needs both halves joined, and the join
existed in exactly one place: inside the desktop robot, behind an AppShell,
a window and an event loop. A unit test that wants to audit a widget tree’s
touch targets could not reach it.
This is that join, headless. One composition, one measure pass, and a tree of
PlacedSemanticsNode carrying two boxes per node, because they are two
different questions and a Wear scaling list is precisely where they diverge:
PlacedSemanticsNode::layout_boundsis the box the measure pass gave the node — what the widget asked for and what an unscaled row occupies. This is the box the desktop robot reports, and the one to assert a widget’s own declared minimum against.PlacedSemanticsNode::touch_boundsis the axis-aligned box the renderer draws and the hit test inverts, ancestor graphics layers included. A row that a scaling ramp shrinks to 0.73 is only tappable where it is drawn (cranpose-render-common’sa_shrunken_row_is_only_tappable_where_it_is_drawnsettles that), so this is the box a finger has to find. It isNonefor a node the hit graph carries no region for — a label, a header, anything that is described but not dispatchable.
§Every walk here reads the RETAINED tree, deliberately
compute_layout returns a [LayoutTree] built from the Placements a
MeasurePolicy returned. The scene the
renderer is handed is not: build_graph_from_applier walks the retained
node state and drops any node whose is_placed is false, and is_placed is
set by placeable.place(x, y) — not by pushing a Placement into a vec.
The two disagreed once and a whole widget set laid out correctly in every
assertion while reaching the device as an empty screen.
So the layout boxes here come from build_layout_tree_from_applier and not
from the tree compute_layout hands back. All three walks — layout,
semantics, scene — then apply the same is_placed filter, and a node that
one of them loses is lost by all of them. A caller cannot be handed bounds
for a control the renderer never drew.
Structs§
- Placed
Semantics Node - One semantics node, with the geometry it was placed and drawn at.
Functions§
- placed_
semantics_ from_ applier - Lay
rootout atsizeand read back its semantics with geometry.