From 87fe6a84653716f2c41f0b2da66e0d3e32e6b496 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Sat, 1 Apr 2023 14:41:33 +0200 Subject: [PATCH] native-activity: Propagate `onNativeWindowRedrawNeeded` callback to main loop --- android-activity/Cargo.toml | 4 ++-- android-activity/src/native_activity/glue.rs | 22 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/android-activity/Cargo.toml b/android-activity/Cargo.toml index 70223dd..f0de17e 100644 --- a/android-activity/Cargo.toml +++ b/android-activity/Cargo.toml @@ -17,7 +17,7 @@ license = "MIT OR Apache-2.0" # # In general it's only the final application crate that needs # to decide on a backend. -default=[] +default = [] game-activity = [] native-activity = [] @@ -43,4 +43,4 @@ targets = [ "x86_64-linux-android", ] -rustdoc-args = ["--cfg", "docsrs" ] \ No newline at end of file +rustdoc-args = ["--cfg", "docsrs"] diff --git a/android-activity/src/native_activity/glue.rs b/android-activity/src/native_activity/glue.rs index 4562030..8e47e8a 100644 --- a/android-activity/src/native_activity/glue.rs +++ b/android-activity/src/native_activity/glue.rs @@ -127,6 +127,8 @@ impl NativeActivityGlue { (*(*activity).callbacks).onWindowFocusChanged = Some(on_window_focus_changed); (*(*activity).callbacks).onNativeWindowCreated = Some(on_native_window_created); (*(*activity).callbacks).onNativeWindowResized = Some(on_native_window_resized); + (*(*activity).callbacks).onNativeWindowRedrawNeeded = + Some(on_native_window_redraw_needed); (*(*activity).callbacks).onNativeWindowDestroyed = Some(on_native_window_destroyed); (*(*activity).callbacks).onInputQueueCreated = Some(on_input_queue_created); (*(*activity).callbacks).onInputQueueDestroyed = Some(on_input_queue_destroyed); @@ -407,6 +409,16 @@ impl WaitableNativeActivityState { guard.write_cmd(AppCmd::WindowResized); } + pub fn notify_window_redraw_needed(&self, native_window: *mut ndk_sys::ANativeWindow) { + let mut guard = self.mutex.lock().unwrap(); + // set_window always syncs .pending_window back to .window before returning. This callback + // from Android can never arrive at an interim state, and validates that Android: + // 1. Only provides resizes in between onNativeWindowCreated and onNativeWindowDestroyed; + // 2. Doesn't call it on a bogus window pointer that we don't know about. + debug_assert_eq!(guard.window.as_ref().unwrap().ptr().as_ptr(), native_window); + guard.write_cmd(AppCmd::WindowRedrawNeeded); + } + unsafe fn set_input(&self, input_queue: *mut ndk_sys::AInputQueue) { let mut guard = self.mutex.lock().unwrap(); @@ -722,6 +734,16 @@ unsafe extern "C" fn on_native_window_resized( }); } +unsafe extern "C" fn on_native_window_redraw_needed( + activity: *mut ndk_sys::ANativeActivity, + window: *mut ndk_sys::ANativeWindow, +) { + log::debug!("NativeWindowRedrawNeeded: {:p} -- {:p}\n", activity, window); + try_with_waitable_activity_ref(activity, |waitable_activity| { + waitable_activity.notify_window_redraw_needed(window) + }); +} + unsafe extern "C" fn on_native_window_destroyed( activity: *mut ndk_sys::ANativeActivity, window: *mut ndk_sys::ANativeWindow,