Simplify Iris app initialization and task updates
This commit is contained in:
1 parent
b5666cdef9
commit
166bac2a93
25 files changed
+330
-282
No files matched your search
+31
-19
@@ -1,5 +1,5 @@
|
||||
use crate::prelude::*;
|
||||
use crate::task::RequestRedraw;
|
||||
use crate::task::WakeTaskQueue;
|
||||
use accesskit_android::Adapter as AccessAdapter;
|
||||
use android_view::{
|
||||
AccessibilityNodeInfo, AccessibilityNodeProvider, Bundle, CallbackCtx, Context,
|
||||
@@ -16,7 +16,7 @@ use std::{cell::RefCell, marker::Sized, rc::Rc, sync::Arc, time::Instant};
|
||||
use super::{
|
||||
access::{AndroidAccessSource, NullActionHandler, raise_if_enabled},
|
||||
insets::{Insets, Shared},
|
||||
render::{AndroidRedrawHandle, AndroidRenderer},
|
||||
render::{AndroidRenderer, AndroidTaskWake},
|
||||
};
|
||||
|
||||
/// Android host state. The renderer follows the `SurfaceView` lifecycle.
|
||||
@@ -100,6 +100,16 @@ pub trait HasAndroidUiState: Sized + 'static {
|
||||
fn android_state_mut(&mut self) -> &mut AndroidUiState;
|
||||
}
|
||||
|
||||
impl HasAndroidUiState for AndroidUiState {
|
||||
fn android_state(&self) -> &AndroidUiState {
|
||||
self
|
||||
}
|
||||
|
||||
fn android_state_mut(&mut self) -> &mut AndroidUiState {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Application state retained for the lifetime of one Android `View`.
|
||||
///
|
||||
/// [`StdRsc`] is the usual [`AndroidResources`] implementation, but the host only
|
||||
@@ -118,6 +128,10 @@ pub trait AndroidAppState: HasAndroidUiState {
|
||||
fn on_insets_changed(&mut self, rsc: &mut Self::Resources, insets: WindowInsets) {}
|
||||
}
|
||||
|
||||
impl AndroidAppState for AndroidUiState {
|
||||
type Resources = StdRsc<Self>;
|
||||
}
|
||||
|
||||
/// Resources the Android host needs to draw and dispatch application events.
|
||||
///
|
||||
/// This deliberately names capabilities rather than storage. Custom bundles
|
||||
@@ -128,12 +142,12 @@ pub trait AndroidResources<State>:
|
||||
where
|
||||
State: 'static,
|
||||
{
|
||||
fn new(redraw: Arc<dyn RequestRedraw>) -> (Self, TaskMsgReceiver<Self>);
|
||||
fn new(wake: Arc<dyn WakeTaskQueue>) -> (Self, TaskMsgReceiver<Self>);
|
||||
}
|
||||
|
||||
impl<State: 'static> AndroidResources<State> for StdRsc<State> {
|
||||
fn new(redraw: Arc<dyn RequestRedraw>) -> (Self, TaskMsgReceiver<Self>) {
|
||||
StdRsc::new(redraw)
|
||||
fn new(wake: Arc<dyn WakeTaskQueue>) -> (Self, TaskMsgReceiver<Self>) {
|
||||
StdRsc::new(wake)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,8 +237,12 @@ impl<State: AndroidAppState> IrisViewPeer<State> {
|
||||
|
||||
self.update_ime_selection(ctx);
|
||||
|
||||
let ui_state = self.state.android_state_mut();
|
||||
ui_state.cursor.end_frame();
|
||||
self.state.android_state_mut().cursor.end_frame();
|
||||
self.request_frame_if_needed(ctx);
|
||||
}
|
||||
|
||||
fn request_frame_if_needed(&self, ctx: &mut CallbackCtx) {
|
||||
let ui_state = self.state.android_state();
|
||||
let render_state = self.rsc.ui().render_state();
|
||||
if render_state
|
||||
.get()
|
||||
@@ -720,18 +738,12 @@ impl<State: AndroidAppState> ViewPeer for IrisViewPeer<State> {
|
||||
self.render(ctx, now);
|
||||
}
|
||||
|
||||
/// Where `AndroidRedrawHandle::request_redraw` (`android/render.rs`)
|
||||
/// actually lands: `View.postDelayed`'s Runnable resolves to this, on
|
||||
/// the UI thread, which is what makes it safe to call from a background
|
||||
/// task's own thread when `post_frame_callback`'s `Choreographer`
|
||||
/// requirement (a `Looper` on the *calling* thread) is not. Same body
|
||||
/// as `do_frame` -- draining tasks and rendering immediately is a
|
||||
/// perfectly good answer to "a background fetch has new state," and
|
||||
/// avoids a second frame-scheduling path to keep in sync with the real
|
||||
/// one.
|
||||
/// Where `AndroidTaskWake::wake` lands on the UI thread. Applying an
|
||||
/// update and drawing it are deliberately separate: retained widget
|
||||
/// invalidation decides whether this wake needs a frame.
|
||||
fn delayed_callback(&mut self, ctx: &mut CallbackCtx) {
|
||||
self.drain_tasks();
|
||||
self.render(ctx, Instant::now());
|
||||
self.request_frame_if_needed(ctx);
|
||||
}
|
||||
|
||||
fn as_input_connection(&mut self) -> Option<&mut dyn InputConnection> {
|
||||
@@ -835,8 +847,8 @@ pub fn new_peer<'local, State: AndroidAppState>(
|
||||
log::info!("iris: new_peer content_scale={content_scale}");
|
||||
let vm = env.get_java_vm().unwrap();
|
||||
let global_view = env.new_global_ref(&view.0).unwrap();
|
||||
let redraw: Arc<dyn RequestRedraw> = Arc::new(AndroidRedrawHandle::new(vm, global_view));
|
||||
let (mut rsc, task_recv) = State::Resources::new(redraw);
|
||||
let wake: Arc<dyn WakeTaskQueue> = Arc::new(AndroidTaskWake::new(vm, global_view));
|
||||
let (mut rsc, task_recv) = State::Resources::new(wake);
|
||||
rsc.ui_mut().set_density(content_scale);
|
||||
let shared = Rc::new(RefCell::new(Shared::default()));
|
||||
let ui_state = AndroidUiState::new(shared.clone(), content_scale);
|
||||
|
||||
Reference in new issue
Block a user