diff --git a/.changes/event-resumed-change.md b/.changes/event-resumed-change.md new file mode 100644 index 000000000..a479ffdfe --- /dev/null +++ b/.changes/event-resumed-change.md @@ -0,0 +1,5 @@ +--- +"tao": minor +--- + +`Event::Resumed` is now only emitted when the app is actually resumed (going back to foreground) so it won't be called on app startup. diff --git a/.changes/will-enter-foreground.md b/.changes/will-enter-foreground.md new file mode 100644 index 000000000..fa97b7e37 --- /dev/null +++ b/.changes/will-enter-foreground.md @@ -0,0 +1,5 @@ +--- +"tao": patch +--- + +Use WillEnterForeground instead of DidBecomeActive for Event::Resumed in iOS. diff --git a/src/event.rs b/src/event.rs index 54b77ce7d..490863cd2 100644 --- a/src/event.rs +++ b/src/event.rs @@ -78,9 +78,21 @@ pub enum Event<'a, T: 'static> { UserEvent(T), /// Emitted when the application has been suspended. + /// + /// ## Platform-specific + /// + /// - **Android**: This is triggered by `onPause` method of the Activity. + /// - **iOS**: This is triggered by `applicationWillResignActive` method of the UIApplicationDelegate. + /// - **Linux / macOS / Windows**: Unsupported. Suspended, /// Emitted when the application has been resumed. + /// + /// ## Platform-specific + /// + /// - **Android**: This is triggered by `onResume` method of the Activity. The first onResume() is ignored to match the iOS implementation, since that is called on activity creation. + /// - **iOS**: This is triggered by `applicationWillEnterForeground` method of the UIApplicationDelegate. + /// - **Linux / macOS / Windows**: Unsupported. Resumed, /// Emitted when all of the event loop's input events have been processed and redraw processing diff --git a/src/platform_impl/android/ndk_glue.rs b/src/platform_impl/android/ndk_glue.rs index a09b4b291..50be718c6 100644 --- a/src/platform_impl/android/ndk_glue.rs +++ b/src/platform_impl/android/ndk_glue.rs @@ -21,7 +21,10 @@ use std::{ fs::File, io::{BufRead, BufReader}, os::unix::prelude::*, - sync::{Arc, Condvar, Mutex, RwLock, RwLockReadGuard}, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, Condvar, Mutex, RwLock, RwLockReadGuard, + }, thread, }; @@ -29,7 +32,7 @@ use std::{ /// in the android project. pub static PACKAGE: OnceCell<&str> = OnceCell::new(); -/// Generate JNI compilant functions that are necessary for +/// Generate JNI compliant functions that are necessary for /// building android apps with tao. /// /// Arguments in order: @@ -123,6 +126,7 @@ static WINDOW_MANAGER: StaticCell> = StaticCell(RefCell::new(N static INPUT_QUEUE: Lazy>> = Lazy::new(|| Default::default()); static CONTENT_RECT: Lazy> = Lazy::new(|| Default::default()); static LOOPER: Lazy>> = Lazy::new(|| Default::default()); +static DID_RESUME: AtomicBool = AtomicBool::new(false); pub fn window_manager() -> std::cell::Ref<'static, Option> { WINDOW_MANAGER.0.borrow() @@ -285,7 +289,12 @@ pub unsafe fn create( } pub unsafe fn resume(_: JNIEnv, _: JClass, _: JObject) { - wake(Event::Resume); + let did_resume = DID_RESUME.swap(true, Ordering::Relaxed); + // first Activity onResume() is called even after onCreate() + // to match the iOS implementation, we ignore the first resume event + if did_resume { + wake(Event::Resume); + } } pub unsafe fn pause(_: JNIEnv, _: JClass, _: JObject) { diff --git a/src/platform_impl/ios/mod.rs b/src/platform_impl/ios/mod.rs index 2d8fda6bc..d35f47a92 100644 --- a/src/platform_impl/ios/mod.rs +++ b/src/platform_impl/ios/mod.rs @@ -50,7 +50,7 @@ //! //! This is how those event are represented in tao: //! -//! - applicationDidBecomeActive is Resumed +//! - applicationWillEnterForeground is Resumed //! - applicationWillResignActive is Suspended //! - applicationWillTerminate is LoopDestroyed //! diff --git a/src/platform_impl/ios/view.rs b/src/platform_impl/ios/view.rs index 8150be1f9..865e2be2f 100644 --- a/src/platform_impl/ios/view.rs +++ b/src/platform_impl/ios/view.rs @@ -611,15 +611,14 @@ pub fn create_delegate_class() { } } - extern "C" fn did_become_active(_: &Object, _: Sel, _: id) { - unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Resumed)) } - } - extern "C" fn will_resign_active(_: &Object, _: Sel, _: id) { unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Suspended)) } } - extern "C" fn will_enter_foreground(_: &Object, _: Sel, _: id) {} + extern "C" fn will_enter_foreground(_: &Object, _: Sel, _: id) { + unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Resumed)) } + } + extern "C" fn did_enter_background(_: &Object, _: Sel, _: id) {} extern "C" fn will_terminate(_: &Object, _: Sel, _: id) { @@ -669,10 +668,6 @@ pub fn create_delegate_class() { application_continue as extern "C" fn(_, _, _, _, _) -> _, ); - decl.add_method( - sel!(applicationDidBecomeActive:), - did_become_active as extern "C" fn(_, _, _), - ); decl.add_method( sel!(applicationWillResignActive:), will_resign_active as extern "C" fn(_, _, _),