Skip to main content

Crate frust_shell_common

Crate frust_shell_common 

Source
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 PlatformViewFrame collection (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§

SurfaceModeWatcher
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 — current is a plain peek, not a diffed poll, per the module docs’ Layering and thread contract.
SystemUiWatcher
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 a set_system_ui_mode call since the last poll.
ThemeOverrideWatcher
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 a set_app_theme/clear_app_theme call since the last poll.
WindowMetricsPublisher
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§

ResolvedSurfaceMode
What the platform actually gave us, as opposed to what the host declared (SurfaceMode) — see the module docs’ The RESOLVED slot.
SurfaceMode
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.
SystemUiMode
The requested system-bar visibility mode (Flutter SystemUiMode parity — see the module docs’ platform-behavior-differences section for where Android/iOS diverge from this vocabulary).
SystemUiOverlay
One of the two system bars a SystemUiMode::Manual mode can name — Flutter’s SystemUiOverlay kept here for doc/mapping parity even though SystemUiMode::Manual itself uses named bools (top/bottom) rather than a Vec<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 a SystemUiWatcher’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 (None when set_default_theme has never been called). Non-destructive — a shell may need it again when reverting an app override via clear_app_theme, to re-seed the base (see the module docs’ Non-destructive read section); unlike crate::font_registry::FontRegistryWatcher::poll, repeated calls with no intervening set_default_theme all 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 single u64 for 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 at error and return default.
logical_corner_insets
Convert platform window-control corner extents into logical CornerInsets.
logical_insets
Build a logical (density-independent) WindowInsets from 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 by scale so glyphs re-rasterise sharp at physical resolution.
new_boxed_app
Erase an app’s State/build into a Box<dyn AppTree>.
new_boxed_app_with
Erase an app’s State/build into a Box<dyn AppTree>, building the initial State from 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 (see ResolvedSurfaceMode::resolve).
resolved_surface_mode
Read the resolved surface mode — ResolvedSurfaceMode::Unknown until 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 as guard, 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 the 1.0 fallback.
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 via RenderRoot::set_theme, and use_context::<Theme>() via provide_context) the next time the running shell polls ThemeOverrideWatcher::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 — unlike ThemeOverrideWatcher::poll, this does not consume or depend on any per-caller “last seen” state.
window_metrics
Assemble the app-facing WindowMetrics from a shell’s raw surface dimensions, its already-sanitize_scaled scale, and the window’s already-logical WindowInsets.