pub struct BuildCtx<'a> { /* private fields */ }Expand description
Context threaded through View::build / View::rebuild.
Three responsibilities: allocating unique WidgetIds (it borrows the id
counter owned by the render root so ids stay monotonic across passes),
carrying the effective focus chain — whether every link from the root down
to the node being built/rebuilt/torn down is focused (see
BuildCtx::has_focus) — and carrying the element-replaced signal a
same-typed element swap raises for its enclosing reconciler (see
BuildCtx::mark_element_replaced).
Implementations§
Source§impl<'a> BuildCtx<'a>
impl<'a> BuildCtx<'a>
Sourcepub fn new(next_id: &'a mut u64) -> Self
pub fn new(next_id: &'a mut u64) -> Self
Create a context borrowing the render root’s id counter.
The focus chain seeds true — “unknown, assume live”. A caller that
does not thread the chain therefore keeps the pre-chain behavior (every
reconciler under it treats a focused pod as the live one) instead of
silently suppressing a release it owed: over-releasing costs the user one
tap, while under-releasing strands the shell’s IME surface over a widget
that no longer exists and nothing on an idle screen ever corrects it (the
same default-to-must-run rule the frame gate follows). The seams that
know the real value — RenderRoot::rebuild’s
view diff and ComponentWidget’s
inner context — set it explicitly with BuildCtx::set_has_focus.
Sourcepub fn has_focus(&self) -> bool
pub fn has_focus(&self) -> bool
Whether the recorded focus path is live all the way from the root to the
node currently being built/rebuilt/torn down — the rebuild-pass mirror of
PaintCtx::has_focus, composed the
same way (self.focused && ctx.has_focus()).
This is what makes a focused ChildPod flag
deep inside a blurred branch harmless. A container-routed blur clears the
focus link at the nearest common ancestor only, so flags below it
legitimately go stale until focus next enters that subtree; a pod under a
cleared link sees has_focus() == false here, exactly as it sees false
in paint and exactly as focus-routed events never reach it. A reconciler
therefore raises mark_focus_orphaned
only when ctx.has_focus() && pod.is_focused() — only when the pod losing
its identity is the one whose session is actually live.
Sourcepub fn set_has_focus(&mut self, has_focus: bool)
pub fn set_has_focus(&mut self, has_focus: bool)
Seed the effective focus chain (see BuildCtx::has_focus).
For the two kinds of seam that start a chain rather than descend one:
RenderRoot’s view diff, which seeds it from the
root’s own session mirror, and a component-style widget that builds an
inner BuildCtx over its own id counter
(ComponentWidget is the in-crate
one) and must carry its outer chain across that boundary. A container
descending into a child pod uses BuildCtx::with_focus_link instead — it
can only narrow, which is what keeps this an AND-chain.
Sourcepub fn with_focus_link<R>(
&mut self,
link_focused: bool,
f: impl FnOnce(&mut Self) -> R,
) -> R
pub fn with_focus_link<R>( &mut self, link_focused: bool, f: impl FnOnce(&mut Self) -> R, ) -> R
Run f with the focus chain extended by one link, restoring the caller’s
chain when it returns.
link_focused is the descended-into pod’s own
ChildPod::is_focused flag, so the
closure sees self.has_focus() && link_focused: a cleared link anywhere
above forces false for the whole subtree below it, and no descent can
ever widen the chain. The rebuild-pass counterpart of
ChildPod::paint_child’s
set_has_focus(self.focused && ctx.has_focus()), in the scoped-closure
shape SemanticsCtx::descend_into_pod
already uses for the semantics pass.
Sourcepub fn mark_element_replaced(&mut self)
pub fn mark_element_replaced(&mut self)
Report that this view’s rebuild replaced its element’s widget while
keeping the element type — an enum view switching arms (Either,
EitherOf3 .. EitherOf8 in frust-widgets) is the shape this exists
for.
A reconciler detects an AnyView concrete-type swap by comparing the
boxed widget’s type id across the rebuild; on a swap it drops the child
pod’s capture (active) and focus (focused) links, because the fresh
widget never saw the Down and never claimed focus. An enum element keeps
one static type across an arm swap, so that comparison cannot see it.
Calling this makes the enclosing reconciler treat the rebuild exactly like
a concrete-type swap.
Scope rule. The nearest enclosing
track_element_replaced scope consumes
the signal. An enum nested inline inside another enum (no pod between
them) therefore propagates to the outer one’s scope — the same pod lost
its widget — while a pod anywhere inside the swapped subtree runs its own
scope and consumes its own signal, leaving the outer pod’s flags intact.
A signal raised where no scope encloses it (a root-level enum, or a
container that rebuilds a child without a pod) is inert or, at worst,
reaches the next scope up: an over-release, never an under-release.
Sourcepub fn track_element_replaced<R>(
&mut self,
f: impl FnOnce(&mut Self) -> R,
) -> (R, bool)
pub fn track_element_replaced<R>( &mut self, f: impl FnOnce(&mut Self) -> R, ) -> (R, bool)
Run f as a tracking scope for
mark_element_replaced, returning
f’s result and whether anything inside it raised the signal.
The caller’s pending value is saved and cleared before f runs and
restored afterwards, so a scope sees only signals raised inside it and a
signal raised by an earlier sibling is neither consumed nor lost. A
reconciler wraps each child’s nested rebuild in this and ORs the result
into its own type-swap detection.