Skip to main content

Module authoring

Module authoring 

Source
Expand description

Everything needed to author a custom View/Widget pair.

frust alone is sufficient: an app that implements its own layout/paint/event widget should need no framework dependency but this crate. If something is reachable through neither this module nor the flat facade, that is a bug — file it rather than reaching for frust-core directly.

use frust::authoring::*; covers the widget-authoring vocabulary proper. Two neighbouring surfaces are deliberately not duplicated here because they are already reachable flat, and a real widget usually wants them too:

For anything the by-name lists below omit, reach for the whole-crate valves: frust::kurbo, frust::peniko, frust::accesskit.

Not feature-gated (unlike the design-system re-exports above): an app that disables every catalog (--no-default-features) still needs this seam to build its own design system, so it always resolves.

§The EditingState split

frust_core::event::EditingState (flat, right here in authoring) and frust_text::editor::EditingState (nested in text) are two genuinely distinct types — the first is the retained IME-surface payload an event-routing widget publishes/receives (ImeState/ImeEvent), the second is TextEditor’s own byte-indexed editing snapshot. A glob importing both into one scope will not compile (use frust::authoring::*; use frust::authoring::text::*; collides on the name); reach for the flat one for event/IME plumbing and authoring::text::EditingState only alongside a TextEditor you’re driving yourself.

§Example: a one-child container widget

A container that offsets its single child, wired through the full lifecycle — build, rebuild, teardown, layout, paint, event routing, semantics forwarding — with only frust named. Ported from frust_widgets::authoring’s own worked example (the toolkit this module re-exports), which an app cannot reach directly without depending on frust-widgets itself.

use frust::authoring::*;

/// The declarative half: a child plus the offset to apply to it.
struct OffsetView<State: 'static> {
    offset: Point,
    child: AnyView<State>,
}

/// The view-fn app code calls; `any` erases the concrete child view.
fn offset<State: 'static, V: View<State>>(offset: Point, child: V) -> OffsetView<State> {
    OffsetView { offset, child: any(child) }
}

/// The retained half: the live child pod plus the applied offset.
struct OffsetWidget {
    offset: Point,
    child: ChildPod,
}

impl<State: 'static> View<State> for OffsetView<State> {
    type Element = OffsetWidget;

    fn build(&self, ctx: &mut BuildCtx<'_>) -> OffsetWidget {
        OffsetWidget { offset: self.offset, child: build_child(&self.child, ctx) }
    }

    fn rebuild(
        &self,
        prev: &Self,
        element: &mut OffsetWidget,
        ctx: &mut BuildCtx<'_>,
    ) -> ChangeFlags {
        let mut flags = ChangeFlags::NONE;
        if prev.offset != self.offset {
            element.offset = self.offset;
            flags |= ChangeFlags::LAYOUT;
        }
        flags | rebuild_child(&prev.child, &self.child, &mut element.child, ctx)
    }

    fn teardown(&self, element: &mut OffsetWidget, ctx: &mut BuildCtx<'_>) {
        teardown_child(&self.child, &mut element.child, ctx);
    }
}

impl Widget for OffsetWidget {
    fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints) -> Size {
        let size = self.child.layout_child(ctx, bc);
        self.child.set_origin(self.offset);
        bc.constrain(size)
    }

    fn paint(&mut self, ctx: &mut PaintCtx, scene: &mut dyn PaintScene) {
        self.child.paint_child(ctx, scene);
    }

    fn event(&mut self, ctx: &mut EventCtx, event: &InputEvent) -> EventResult {
        // Never re-hit-test a captured child by hand — this helper owns the
        // capture/focus fast paths and the blur-on-outside-tap rule.
        route_event_single(&mut self.child, ctx, event)
    }

    fn semantics(&self, ctx: &mut SemanticsCtx) {
        // A transparent wrapper still MUST forward, or the child's whole
        // subtree drops out of the accessibility tree.
        self.child.semantics_child(ctx);
    }
}

Modules§

scene
The renderer-agnostic display list, for widgets painting below PaintScene.
text
Text shaping/measurement for widgets laying out their own glyph runs.

Macros§

visit_children
Implement Widget::visit_children for the container whose impl Widget block this is written in, forwarding the named fields in the order given.

Structs§

Affine
A 2D affine transform.
AnyView
A type-erased View: lets a piece of UI change its concrete view type between frames (e.g. a conditional if cond { text(..) } else { button(..) }) while still fitting the statically-typed rebuild machinery.
BezPath
A Bézier path.
BoxConstraints
Immutable min/max size bounds passed down during layout.
BuildCtx
Context threaded through View::build / View::rebuild.
ChangeFlags
Bitflags describing what work a View::rebuild pass invalidated.
ChildPod
A container’s owned child: a boxed widget plus the layout geometry and capture bookkeeping the container maintains for it.
CornerInset
The inset vocabulary LayoutCtx::window_insets/PaintCtx::window_insets return — lifted because a widget that lays itself out around the status bar, notch, or on-screen keyboard cannot otherwise name the value those accessors hand it. A bar laying out around the iPadOS window control names the corner value, CornerInsets. The footprint of a system window control at one corner, in logical pixels.
CornerInsets
The inset vocabulary LayoutCtx::window_insets/PaintCtx::window_insets return — lifted because a widget that lays itself out around the status bar, notch, or on-screen keyboard cannot otherwise name the value those accessors hand it. A bar laying out around the iPadOS window control names the corner value, CornerInsets. Window-control footprints at the four window corners, in logical pixels.
CornerRadii
The paint vocabulary PaintScene’s per-corner and dashed methods name — fill_rounded_rect_radii/push_clip_rounded_radii take a CornerRadii, stroke_path_dashed a DashPattern. Lifted for the same reason WindowInsets is: a widget calling those methods cannot otherwise name their arguments. Re-exported through frust-core’s paint surface, so this is the same type scene::CornerRadii names. The per-corner radii and dash-pattern vocabulary PaintScene’s own signatures name, re-exported from frust-scene so a widget calling PaintScene::fill_rounded_rect_radii/PaintScene::push_clip_rounded_radii/ PaintScene::stroke_path_dashed can name their arguments through the same paint surface it already paints through (mirrors the crate-root accesskit re-export). Per-corner radii for a rounded rectangle, in the pre-transform coordinate space.
DashPattern
The paint vocabulary PaintScene’s per-corner and dashed methods name — fill_rounded_rect_radii/push_clip_rounded_radii take a CornerRadii, stroke_path_dashed a DashPattern. Lifted for the same reason WindowInsets is: a widget calling those methods cannot otherwise name their arguments. Re-exported through frust-core’s paint surface, so this is the same type scene::CornerRadii names. The per-corner radii and dash-pattern vocabulary PaintScene’s own signatures name, re-exported from frust-scene so a widget calling PaintScene::fill_rounded_rect_radii/PaintScene::push_clip_rounded_radii/ PaintScene::stroke_path_dashed can name their arguments through the same paint surface it already paints through (mirrors the crate-root accesskit re-export). A stroke’s dash pattern: an on run, an off gap, and a phase offset into that repeating cycle — all lengths in the pre-transform coordinate space.
DiscardScene
A PaintScene sink that accepts every paint command and records nothing — the zero-GPU-cost target for a subtree that still needs its paint pass driven for the pass’s side effects (hero-rect reporting through PaintCtx::with_hero_registry, other paint-time widget state) even though its pixels will never be composited. The navigator’s transition machinery is the motivating case: a page whose resolved alpha is 0 still has to paint to report hero rects and advance animating children, but every command it emits is otherwise wasted GPU work.
EditingState
The event-pass/IME-surface EditingState — see this module’s own docs for the split against text::EditingState, frust_text::editor’s distinct, byte-indexed type. ImeContentType is the input-purpose hint an editable widget publishes on its ImeState so a shell can lock a secret field’s keyboard down. The full editing state of a text field, the one struct every IME bridge syncs.
EventCtx
Context threaded into crate::widget::Widget::event.
EventOutcome
The result of a whole crate::app::RenderRoot::event pass.
HeroFrames
A tagged-rect reporter threaded through the paint pass, letting a container discover where tagged (“hero”) descendants painted and drive a shared-element morph between two of them across a navigation transition.
ImageData
Owned shareable image resource.
ImageSource
A decode-once, cheaply-clonable handle around a decoded RGBA8 image.
ImeState
The event-pass/IME-surface EditingState — see this module’s own docs for the split against text::EditingState, frust_text::editor’s distinct, byte-indexed type. ImeContentType is the input-purpose hint an editable widget publishes on its ImeState so a shell can lock a secret field’s keyboard down. The IME-relevant surface a focused editable widget publishes for the shell.
KeyEvent
A keyboard key event delivered down the focus path (never hit-tested).
LayoutCtx
Context passed to Widget::layout.
Line
A single line.
Modifiers
The chord of modifier keys held when a KeyEvent fired.
Node
The accessibility-node vocabulary a widget that contributes a semantics node needs — as opposed to one that only forwards a child’s.
NodeId
The accessibility-node vocabulary a widget that contributes a semantics node needs — as opposed to one that only forwards a child’s.
OverlayKey
The overlay registry’s own vocabulary, re-exported from frust-core so a design system naming a band, an input class, a light-dismiss policy or a surface identity does it through this one module: an OverlaySlot’s setters take exactly these types, and a widget that cannot name them cannot configure one. An overlay owner’s identity, allocated once by the owner and quoted back to it by every InputEvent::Overlay the root routes into its surface.
OverlayPlacement
The overlay-portal authoring surface: the slot a widget that floats its own surface holds, what that surface is anchored to, and the placement geometry every anchored pattern needs.
OverlaySlot
The overlay-portal authoring surface: the slot a widget that floats its own surface holds, what that surface is anchored to, and the placement geometry every anchored pattern needs.
PaintCtx
Context passed to Widget::paint.
PaintOutcome
The result of a whole crate::app::RenderRoot::paint pass.
Point
A 2D point.
PointerEvent
A single pointer event in the coordinate space of the widget receiving it.
Rect
A rectangle.
RoundedRect
A rectangle with rounded corners.
SemanticsCtx
Collects accesskit::Nodes during a semantics pass, tracking the current absolute origin/size (mirroring paint’s origin threading) and the parent/child structure.
SemanticsUpdate
A collected accessibility tree produced by RenderRoot::semantics.
Size
A 2D size.
Stroke
The visual style of a stroke.
Vec2
A 2D vector.
WidgetId
A stable identity for a node in the widget tree.
WindowEdgeInsets
The inset vocabulary LayoutCtx::window_insets/PaintCtx::window_insets return — lifted because a widget that lays itself out around the status bar, notch, or on-screen keyboard cannot otherwise name the value those accessors hand it. A bar laying out around the iPadOS window control names the corner value, CornerInsets. Per-edge inset amounts, in logical pixels.
WindowInsets
The inset vocabulary LayoutCtx::window_insets/PaintCtx::window_insets return — lifted because a widget that lays itself out around the status bar, notch, or on-screen keyboard cannot otherwise name the value those accessors hand it. A bar laying out around the iPadOS window control names the corner value, CornerInsets. The window’s inset state, mirroring Flutter’s ViewportMetrics (media_query.dart).
WindowMetrics
The window-shape value recovered via use_context::<WindowMetrics>() inside Component::build — lifted alongside WindowInsets for the same reason: a widget or component laying itself out around window size/scale/orientation cannot otherwise name the value. See WindowMetrics’s own doc for the plain-value delivery contract, the alongside-not-superseding relationship with WindowInsets, and the derived-orientation/rebuild-cost notes. The window’s shape and platform-occlusion state, delivered to app code as a plain provide_context-carried value — logical size, device-pixel scale, a derived orientation, and the current WindowInsets.

Enums§

Action
The accessibility-node vocabulary a widget that contributes a semantics node needs — as opposed to one that only forwards a child’s.
Brush
Describes the color content of a filled or stroked shape.
CursorIcon
The cursor vocabulary a widget requests through EventCtx::set_cursor — lifted so a design system’s own controls can name a shape (Pointer on a button, Text over an editable, Grabbing on a live drag) without a direct frust-core dependency. Also re-exported flat as frust::CursorIcon. The pointer cursor a widget asks the host to display.
EditCommand
The clipboard/selection vocabulary an editable widget matches on — InputEvent::EditCommand carries one of these four verbs, already decoded from whatever chord, hardware key or edit-menu tap produced it. A widget answers copy/cut through EventCtx::write_clipboard and asks for a paste through EventCtx::request_paste; the shell owns the host clipboard at both ends. Also re-exported flat as frust::EditCommand, for the same reason CursorIcon is: a design system’s public API can name a verb without authoring a widget. A semantic clipboard / selection command delivered to the focused editable.
EventResult
What a widget did with an event.
Fill
Describes the rule that determines the interior portion of a shape.
HeroDirective
What a reported hero should do this paint — the reply PaintCtx::report_hero hands back to a tagged (“hero”) wrapper.
ImeContentType
The event-pass/IME-surface EditingState — see this module’s own docs for the split against text::EditingState, frust_text::editor’s distinct, byte-indexed type. ImeContentType is the input-purpose hint an editable widget publishes on its ImeState so a shell can lock a secret field’s keyboard down. What kind of content a focused editable field holds — the hint a widget publishes so each shell can configure the platform input method.
ImeEvent
The event-pass/IME-surface EditingState — see this module’s own docs for the split against text::EditingState, frust_text::editor’s distinct, byte-indexed type. ImeContentType is the input-purpose hint an editable widget publishes on its ImeState so a shell can lock a secret field’s keyboard down. An input-method (IME) event delivered down the focus path (never hit-tested).
InputEvent
An input event delivered to the widget tree.
Key
A logical key press: either a semantic NamedKey or a run of typed text.
Live
The accessibility-node vocabulary a widget that contributes a semantics node needs — as opposed to one that only forwards a child’s.
NamedKey
A named (non-character) key: the control keys an editable widget reacts to.
Orientation
The window-shape value recovered via use_context::<WindowMetrics>() inside Component::build — lifted alongside WindowInsets for the same reason: a widget or component laying itself out around window size/scale/orientation cannot otherwise name the value. See WindowMetrics’s own doc for the plain-value delivery contract, the alongside-not-superseding relationship with WindowInsets, and the derived-orientation/rebuild-cost notes. A window’s derived portrait/landscape orientation.
OutsideTap
The overlay registry’s own vocabulary, re-exported from frust-core so a design system naming a band, an input class, a light-dismiss policy or a surface identity does it through this one module: an OverlaySlot’s setters take exactly these types, and a widget that cannot name them cannot configure one. What a registered surface wants to hear about a press that landed on nothing floated — the light-dismiss policy, a per-surface boolean everywhere this pattern exists.
OverlayAlign
The overlay-portal authoring surface: the slot a widget that floats its own surface holds, what that surface is anchored to, and the placement geometry every anchored pattern needs.
OverlayAnchor
The overlay-portal authoring surface: the slot a widget that floats its own surface holds, what that surface is anchored to, and the placement geometry every anchored pattern needs.
OverlayBand
The overlay registry’s own vocabulary, re-exported from frust-core so a design system naming a band, an input class, a light-dismiss policy or a surface identity does it through this one module: an OverlaySlot’s setters take exactly these types, and a widget that cannot name them cannot configure one. Which z-band a registered surface paints and hit-tests in.
OverlayInput
The overlay registry’s own vocabulary, re-exported from frust-core so a design system naming a band, an input class, a light-dismiss policy or a surface identity does it through this one module: an OverlaySlot’s setters take exactly these types, and a widget that cannot name them cannot configure one. Whether a registered surface takes pointer input at all.
OverlaySide
The overlay-portal authoring surface: the slot a widget that floats its own surface holds, what that surface is anchored to, and the placement geometry every anchored pattern needs.
PointerButton
Which physical (or synthetic) button a pointer event carries.
PointerPhase
The lifecycle phase of a pointer gesture.
Role
The accessibility-node vocabulary a widget that contributes a semantics node needs — as opposed to one that only forwards a child’s.
ScrollDelta
A scroll amount, in either discrete lines or continuous pixels.
ThemeTextColor
Which themed color role a text’s glyphs default to when no explicit .color()/.style() was set and a theme is active.
ThemeTextType
Which type-scale role a text’s font FAMILY resolves from at layout, when opted into with TextView::themed_family and a theme is active — one variant per TypeScale slot (15 baseline roles plus their 15 _emphasized siblings).
TickClass
The class of a continuation-frame request a widget makes during paint — how urgent the next frame is, so the mobile frame gate can decide whether it may be paced (see crate::app::RenderRoot::paint and the frame gate).
Toggled
The accessibility-node vocabulary a widget that contributes a semantics node needs — as opposed to one that only forwards a child’s.

Constants§

PRESSED_OPACITY
Pressed-state overlay opacity (source: androidx Compose Material3 StateTokens v0_210, retrieved 2026-07-17 — supersedes material-web v0.192’s 12%).

Traits§

PaintScene
The renderer-agnostic paint target a widget draws into.
Shape
A generic trait for open and closed shapes.
View
A declarative description of a piece of UI.
VisitPods
A field shape a container can hold children in, visitable in declaration order — the traversal half of the visit_children! seam.
Widget
A retained UI element living in the widget tree.

Functions§

any
Erase view into an AnyView — the free-function spelling of AnyView::new, mirroring the text(..)/button(..) view-fn vocabulary.
build_child
Build a ChildPod wrapping an AnyView’s element.
erase_callback
Erase a view-held Rc<dyn Fn(&mut State)> app-state callback into the widget-held ErasedCallback adapter the interactive widgets invoke during the event pass.
erase_callback_arg
Like erase_callback, but for callbacks that also carry a value argument (Checkbox’s bool, Slider’s f64).
place
The overlay-portal authoring surface: the slot a widget that floats its own surface holds, what that surface is anchored to, and the placement geometry every anchored pattern needs.
rebuild_child
Reconcile one AnyView child in place through its ChildPod.
rebuild_children
Diff a child list against its live ChildPods, extracting each child’s AnyView through view_of (identity for a plain Vec<AnyView>, |c| &c.view for Flex’s FlexChild wrapper) and its optional ChildKey through key_of (|_| None for keyless containers, |c| c.key for Flex) — the one shared reconciler for every multi-child container.
route_event
Route a pointer/scroll/keyboard/IME event — or a broadcast — to a container’s children.
route_event_single
Route a pointer/scroll event — or a broadcast — to a container’s single child.
teardown_child
Tear down one AnyView child through its ChildPod.

Type Aliases§

Color
A convenient alias for the color type used for Brush.
ErasedArgCallback
A widget-held, State-erased callback adapter carrying one value argument (see erase_callback_arg).
ErasedCallback
A widget-held, State-erased app-state callback adapter (see erase_callback).
TypedArgCallback
A view-held, typed callback carrying one value argument (Checkbox’s bool, Slider’s f64), erased to ErasedArgCallback on build.