macro_rules! android_app {
($state_ty:ty, $build:expr $(,)?) => { ... };
($state_ty:ty, $state_init:expr, $build:expr $(,)?) => { ... };
}Expand description
Bind a generated app’s State/build to the fixed Android JNI exports
(a Makepad app_main! precedent).
Stamps out the twenty-two Java_dev_frust_FrustSurfaceView_native* symbols
the Kotlin FrustSurfaceView declares external, each delegating to the
non-generic runtime in [jni_glue]. nativeInit constructs the app’s erased
view tree from a state factory and $build; the rest operate on the
opaque jlong handle. The three IME exports (nativeImeApply,
nativeImeState, nativeImeAction) carry the soft-keyboard
state-sync contract: Kotlin pushes a whole editing state in
(nativeImeApply), pulls the reconciled state back out (nativeImeState), and
forwards an editor action (Enter) via nativeImeAction. nativeSetAppearance
flips the app’s theme brightness from the platform’s dark-mode
preference, and nativeSetReduceMotion does the same for the platform’s
reduced-motion accessibility preference (a different sensor over the same
transport — Settings.Global.ANIMATOR_DURATION_SCALE, not
Configuration). nativeAppIsDark is the read half of the appearance
seam: it returns whether the app’s currently active theme is dark, so
Kotlin’s status-bar icon contrast can follow the APP’s resolved theme
(which an app-forced frust::set_app_theme override may have pinned away
from the platform’s own preference) instead of re-reading
Configuration.uiMode directly. nativeOnDeepLink delivers a cold-start/running
platform deep link into the process-wide deep-link source.
nativeInitAccessibility attaches the accesskit Android
adapter to the host view. Two more exports:
nativeOnInsetsChanged delivers the platform window insets (SafeArea), and
nativeOnBackPress routes a hardware/gesture back press through the framework
(returning whether it consumed it). nativeOnSurfaceChanged also gained a
trailing density argument alongside these. nativeSystemUiState
returns the app-facing frust::set_system_ui_mode override slot’s
packed (generation, mode) state for a per-frame Kotlin poll. Two more,
additive over those seventeen: nativeSetSurfaceMode
latches a translucent GPU surface pre-init (a one-way opt-in — see
frust_shell_common::surface_mode’s module docs), and
nativePlatformViewCommands returns the native-sibling-compositor command
backlog (the differ) as JSON for Kotlin’s own per-frame poll, mirroring
nativeSystemUiState’s generation-gated shape but JSON-encoded (the
ViewCommand vocabulary) rather than packed into a jlong. One more:
nativeSetFrameTimeline pushes the Choreographer frame
timeline’s expectedPresentationTimeNanos − frameTimeNanos (API 33+, the
one signal only the JVM side can read) into the scroll-sync tail — additive
and optional, 0/never-called leaves the platform-view release path
gate-only. nativeInit also
initializes the process-wide [frust_reactive::ReactiveRuntime] (see
[jni_glue::native_init]) before the state factory runs, so a State’s own
construction may already create signals/controllers.
The macro is defined on every target but only expands to real code where
its call site is gated, e.g. in the generated src/lib.rs:
#[cfg(target_os = "android")]
frust::android_app!(AppState, move |s| root.build(s));Two forms:
android_app!($state_ty, $build)—$state_tymust implementDefault; the state is built via<$state_ty as Default>::default.android_app!($state_ty, $state_init, $build)—$state_initis aFnOnce() -> $state_tyfactory (e.g. a closure or a bare function path likeMyState::new), for aStatethat doesn’t implementDefault. The 2-arg form delegates to this one.
$build is the root component’s build closure, a FnMut(&mut State) -> impl View<State> (move |s| root.build(s)).