Expand description
Platform-agnostic shell plumbing shared by every Frust platform shell.
The Android (frust-shell-android) and iOS shells both need the same
non-FFI machinery: the AppTree type-erasure that lets a non-generic
native handle drive any app’s State/build, a handful of pure
helpers for crossing an FFI boundary safely (guard) and turning an
untrusted density into HiDPI layout math (sanitize_scale/logical_size/
logical_insets/logical_corner_insets, the last two converting platform
per-edge insets and window-control corners into a logical
WindowInsets /
CornerInsets),
the shared window-shape publish path (window_metrics assembling a
logical WindowMetrics and
WindowMetricsPublisher deciding — on all three shells — whether it
actually changed and so may be re-provided to app code),
the app-facing theme override slot (set_app_theme/clear_app_theme/
ThemeOverrideWatcher — see [theme_override]’s module docs for the
layering rationale), the perf module’s frame-timing/startup-span
instrumentation, the frame_gate module’s shared skip-frame decision
(FrameGate/FrameInputs/FrameDecision) the mobile shells consult
to idle on unchanged frames, the resample
module’s pointer-event resampling (PointerResampler) plus deadline-aware
pacing helpers the mobile shells drive from their touch + frame paths, and
the render_split module’s UI→render-thread plumbing
(render_channel’s latest-wins scene handoff + RenderCommand/Ack
lifecycle vocabulary, gated by render_thread_enabled, plus
scene_return_channel’s reverse give-back slot restoring buffer reuse
across the split) the shells split the frame pipeline across. The
platform_view module is the differ turning frust-core‘s
per-paint-pass platform-view frames into an idempotent
ViewCommand/PlatformViewState backlog both mobile shells’ FFI peek
getters serve, and [surface_mode] is the
process-global translucent-surface pair: the host declaration latch
(declare_host_translucent_surface/SurfaceModeWatcher) — settable
only by each shell’s own JNI/C-ABI host-glue callback, never re-exported
past this crate — each shell’s
surface-creation path reads pre-configure, plus the resolved slot
(publish_resolved_surface_mode/resolved_surface_mode) each mobile
shell publishes the live surface’s actual verdict
into, so app code can observe a RefusedTranslucent platform refusal
instead of an invisible native sibling. Behind the non-default gpu
cargo feature, [gpu] carries the process-wide GPU-device slot
([gpu::install_gpu_handle]/[gpu::gpu_handle]) a shell’s render
executor installs its device into once, type-erased so this crate still
names no GPU type — see the module’s own docs.
This crate is deliberately platform-free: it depends on frust-core
(retained tree / RenderRoot) plus frust-scene/frust-text/
frust-theme for the types a shell composes around it, but never on
jni/ndk/winit. It contains no unsafe and no FFI, so it compiles
unchanged on the host and on aarch64-linux-android/iOS with no cfg
gymnastics. Each platform shell keeps its own FFI boundary (JNI exports,
raw-window handling) and reuses this crate rather than duplicating the
plumbing.
Re-exports§
pub use frame_gate::FrameDecision;pub use frame_gate::FrameGate;pub use frame_gate::FrameInputs;pub use frame_gate::FramePacing;pub use frame_gate::anim_pacing_kill_switch_engaged;pub use platform_view::PlatformViewState;pub use platform_view::ViewCommand;pub use render_split::Ack;pub use render_split::AckWaiter;pub use render_split::FrameMeta;pub use render_split::NO_RENDER_THREAD_VAR;pub use render_split::RenderBatch;pub use render_split::RenderCommand;pub use render_split::RenderEvent;pub use render_split::RenderPhase;pub use render_split::RenderReceiver;pub use render_split::RenderSender;pub use render_split::SceneFrame;pub use render_split::SceneReturnReceiver;pub use render_split::SceneReturnSender;pub use render_split::SurfaceSize;pub use render_split::ack_pair;pub use render_split::next_render_phase;pub use render_split::render_channel;pub use render_split::render_thread_enabled;pub use render_split::scene_return_channel;pub use resample::PointerResampler;pub use resample::RawPointerSample;
Modules§
- font_
registry - App-facing pending-font registry:
frust::register_app_fonts. - frame_
gate FrameGate: the shared skip-frame decision the mobile shells consult each tick.- perf
- Frame-timing and startup-span perf instrumentation shared by every shell.
- platform_
view - Platform-agnostic native-sibling compositor logic: turns the raw,
per-paint-pass
PlatformViewFramecollection (frust-core) into an idempotent, generation-stamped command list —ViewCommand— both mobile shells’ FFI peek getters serve to their platform side (docs/SHELLS_ARCHITECTURE.md’s platform-view embedding flow). - render_
split - Render-thread-split plumbing shared by every shell.
- resample
- Pointer-event resampling + deadline-aware pacing helpers shared by the mobile shells.
Structs§
- Surface
Mode Watcher - Per-shell-instance reader over the process-wide latch. Kept as a type
(mirroring
crate::theme_override::ThemeOverrideWatcher/crate::system_ui::SystemUiWatcher’s shape) even though it carries no state of its own —currentis a plain peek, not a diffed poll, per the module docs’ Layering and thread contract. - System
UiWatcher - Per-shell-instance watcher over the process-wide system-UI slot: each
shell owns one, polling it once per frame (mirroring
crate::theme_override::ThemeOverrideWatcher) to detect aset_system_ui_modecall since the last poll. - Theme
Override Watcher - Per-shell-instance watcher over the process-wide override slot: each of the
three shells owns one, polling it once per frame (desktop: before rebuild in
RedrawRequested; mobile: at the top of the frame callback) to detect aset_app_theme/clear_app_themecall since the last poll. - Window
Metrics Publisher - Per-shell-instance change detector over the window’s
WindowMetrics: each of the three shells owns one and drives it from its own resize/insets entry points, publishing only what it reports as changed.
Enums§
- Resolved
Surface Mode - What the platform actually gave us, as opposed to what the host
declared (
SurfaceMode) — see the module docs’ The RESOLVED slot. - Surface
Mode - Whether a shell’s GPU surface should be created with an alpha channel.
See the module docs’ Latch contract — this only ever moves
Opaque→Translucent, never back. - System
UiMode - The requested system-bar visibility mode (Flutter
SystemUiModeparity — see the module docs’ platform-behavior-differences section for where Android/iOS diverge from this vocabulary). - System
UiOverlay - One of the two system bars a
SystemUiMode::Manualmode can name — Flutter’sSystemUiOverlaykept here for doc/mapping parity even thoughSystemUiMode::Manualitself uses named bools (top/bottom) rather than aVec<SystemUiOverlay>, the more Rust-idiomatic shape for a fixed two-element set.
Traits§
- AppTree
- Type-erased app tree: the one seam that lets a shell’s native handle stay
non-generic while still driving a concrete
State/build/View.
Functions§
- clear_
app_ theme - Clear a previously-set override, returning to the platform’s own
light/dark-derived default theme on the next poll (see
set_app_theme). - current_
system_ ui_ mode - A cheap peek at the slot’s current
(generation, mode)pair, for a caller that wants the raw state without consuming/tracking aSystemUiWatcher’s “last seen” cursor — e.g.encoded_state, or an FFI glue module polling from the platform side. - declare_
host_ translucent_ surface - Declare that the native host window has already been configured
translucent (
PixelFormat.TRANSLUCENT/isOpaque = false) so this shell’s next GPU surface should be created with an alpha channel too. - default_
theme - Read the seeded default, if any (
Nonewhenset_default_themehas never been called). Non-destructive — a shell may need it again when reverting an app override viaclear_app_theme, to re-seed the base (see the module docs’ Non-destructive read section); unlikecrate::font_registry::FontRegistryWatcher::poll, repeated calls with no interveningset_default_themeall return the same value rather than draining the slot. - effective_
brightness_ for_ platform_ change - The override-wins-over-appearance rule (see the module docs), as a pure,
shared decision every shell’s platform-appearance handler (
WindowEvent:: ThemeChanged/nativeSetAppearance/frust_set_appearance) calls before mutating its stored theme’s brightness: - encoded_
state - Pack the slot’s current
(generation, mode)into a singleu64for an FFI getter to return verbatim — see the module docs’ FFI-encoding section for the exact bit layout. Each mobile shell exports this unchanged; its own Kotlin/Swift decoder is built against it. - guard
- Run
f, catching any panic so it can never unwind across the FFI boundary (undefined behaviour); on panic, log aterrorand returndefault. - logical_
corner_ insets - Convert platform window-control corner extents into logical
CornerInsets. - logical_
insets - Build a logical (density-independent)
WindowInsetsfrom the platform’s raw physical-px per-edge inset values and an already-sanitize_scaled scale factor. - logical_
size - Logical (density-independent) size from a physical pixel size and an
already-
sanitize_scaled scale factor, mirroring the desktop shell’s HiDPI math: lay out in logical pixels, then scale the scene byscaleso glyphs re-rasterise sharp at physical resolution. - new_
boxed_ app - Erase an app’s
State/buildinto aBox<dyn AppTree>. - new_
boxed_ app_ with - Erase an app’s
State/buildinto aBox<dyn AppTree>, building the initialStatefrom a caller-supplied factory rather than a ready-made value. - publish_
resolved_ surface_ mode - Publish the live surface’s resolved translucency, mapped against the
host declaration into a
ResolvedSurfaceMode(seeResolvedSurfaceMode::resolve). - resolved_
surface_ mode - Read the resolved surface mode —
ResolvedSurfaceMode::Unknownuntil a shell publishes one (no surface yet, or a shell with no Mode B seam, e.g. the desktop preview). - run_
guarded_ thread - Run a shell-spawned render-thread body, catching any panic so the thread
exits cleanly instead of unwinding out of the thread closure — following
the same
catch_unwind+AssertUnwindSafe+error-log convention asguard, but for a whole-thread closure rather than an FFI entry point. - sanitize_
scale - Sanitize a raw density (e.g. a JNI
jfloat) into a scale safe to divide or multiply by: finite and strictly positive, else the1.0fallback. - set_
app_ theme - Force the app’s active
Theme, overriding whatever the platform’s own light/dark preference would otherwise select — reaching BOTH delivery paths (widget paint/layout viaRenderRoot::set_theme, anduse_context::<Theme>()viaprovide_context) the next time the running shell pollsThemeOverrideWatcher::poll(once per frame — see the module docs). - set_
default_ theme - Supply the base theme a shell seeds itself with, in place of its built-in
fallback. Call before the first frame — typically from a design-system
plugin’s
install(). - set_
system_ ui_ mode - Request a system-bar visibility mode, reaching whichever shell is running
the next time it polls (once per frame — see the module docs’ thread
contract). Callable from any thread; the process-wide slot is a plain
Mutex, not a UI-thread-only primitive. - theme_
override_ active - Whether an app-forced override is active right now, for a shell’s
appearance-change handler to consult before applying a platform brightness
flip (see
effective_brightness_for_platform_change). Reads the slot directly — unlikeThemeOverrideWatcher::poll, this does not consume or depend on any per-caller “last seen” state. - window_
metrics - Assemble the app-facing
WindowMetricsfrom a shell’s raw surface dimensions, its already-sanitize_scaled scale, and the window’s already-logicalWindowInsets.