From fc7a63cbf3dcec176046b3ba047f40d367213cfb Mon Sep 17 00:00:00 2001 From: Zach Coleman Date: Fri, 17 Nov 2023 08:23:06 -0500 Subject: [PATCH] Enhance mobile suspend MainLoop Notifications --- doc/classes/MainLoop.xml | 9 +++++---- doc/classes/Node.xml | 13 +++++++------ platform/android/os_android.cpp | 6 ++++++ platform/ios/app_delegate.mm | 8 ++++++++ platform/ios/os_ios.h | 3 +++ platform/ios/os_ios.mm | 28 ++++++++++++++++++++++++++++ 6 files changed, 57 insertions(+), 10 deletions(-) diff --git a/doc/classes/MainLoop.xml b/doc/classes/MainLoop.xml index b01a3f7a0e6..458b3d4107a 100644 --- a/doc/classes/MainLoop.xml +++ b/doc/classes/MainLoop.xml @@ -119,19 +119,20 @@ Notification received from the OS when the application is resumed. - Specific to the Android platform. + Specific to the Android and iOS platforms. Notification received from the OS when the application is paused. - Specific to the Android platform. + Specific to the Android and iOS platforms. + [b]Note:[/b] On iOS, you only have approximately 5 seconds to finish a task started by this signal. If you go over this allotment, iOS will kill the app instead of pausing it. Notification received from the OS when the application is focused, i.e. when changing the focus from the OS desktop or a thirdparty application to any open window of the Godot instance. - Implemented on desktop platforms. + Implemented on desktop and mobile platforms. Notification received from the OS when the application is defocused, i.e. when changing the focus from any open window of the Godot instance to the OS desktop or a thirdparty application. - Implemented on desktop platforms. + Implemented on desktop and mobile platforms. Notification received when text server is changed. diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 4f09a0c6162..1b33666daa1 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -1151,19 +1151,20 @@ Notification received from the OS when the application is resumed. - Implemented only on Android. + Specific to the Android and iOS platforms. Notification received from the OS when the application is paused. - Implemented only on Android. + Specific to the Android and iOS platforms. + [b]Note:[/b] On iOS, you only have approximately 5 seconds to finish a task started by this signal. If you go over this allotment, iOS will kill the app instead of pausing it. - Notification received from the OS when the application is focused, i.e. when changing the focus from the OS desktop or a third-party application to any open window of the Godot instance. - Implemented on desktop platforms. + Notification received from the OS when the application is focused, i.e. when changing the focus from the OS desktop or a thirdparty application to any open window of the Godot instance. + Implemented on desktop and mobile platforms. - Notification received from the OS when the application is defocused, i.e. when changing the focus from any open window of the Godot instance to the OS desktop or a third-party application. - Implemented on desktop platforms. + Notification received from the OS when the application is defocused, i.e. when changing the focus from any open window of the Godot instance to the OS desktop or a thirdparty application. + Implemented on desktop and mobile platforms. Notification received when the [TextServer] is changed. diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 0d82bec75db..a86cf430425 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -324,11 +324,17 @@ void OS_Android::main_loop_end() { void OS_Android::main_loop_focusout() { DisplayServerAndroid::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_OUT); + if (OS::get_singleton()->get_main_loop()) { + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT); + } audio_driver_android.set_pause(true); } void OS_Android::main_loop_focusin() { DisplayServerAndroid::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_IN); + if (OS::get_singleton()->get_main_loop()) { + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN); + } audio_driver_android.set_pause(false); } diff --git a/platform/ios/app_delegate.mm b/platform/ios/app_delegate.mm index 8a16f8fcc12..32ebf7be441 100644 --- a/platform/ios/app_delegate.mm +++ b/platform/ios/app_delegate.mm @@ -167,6 +167,14 @@ static ViewController *mainViewController = nil; OS_IOS::get_singleton()->on_focus_in(); } +- (void)applicationDidEnterBackground:(UIApplication *)application { + OS_IOS::get_singleton()->on_enter_background(); +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + OS_IOS::get_singleton()->on_exit_background(); +} + - (void)dealloc { self.window = nil; } diff --git a/platform/ios/os_ios.h b/platform/ios/os_ios.h index 06724d763fa..9248d303871 100644 --- a/platform/ios/os_ios.h +++ b/platform/ios/os_ios.h @@ -129,6 +129,9 @@ public: void on_focus_out(); void on_focus_in(); + + void on_enter_background(); + void on_exit_background(); }; #endif // IOS_ENABLED diff --git a/platform/ios/os_ios.mm b/platform/ios/os_ios.mm index 6ac21fa9c83..078f8e84941 100644 --- a/platform/ios/os_ios.mm +++ b/platform/ios/os_ios.mm @@ -601,6 +601,10 @@ void OS_IOS::on_focus_out() { DisplayServerIOS::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_OUT); } + if (OS::get_singleton()->get_main_loop()) { + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT); + } + [AppDelegate.viewController.godotView stopRendering]; audio_driver.stop(); @@ -615,10 +619,34 @@ void OS_IOS::on_focus_in() { DisplayServerIOS::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_IN); } + if (OS::get_singleton()->get_main_loop()) { + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN); + } + [AppDelegate.viewController.godotView startRendering]; audio_driver.start(); } } +void OS_IOS::on_enter_background() { + // Do not check for is_focused, because on_focus_out will always be fired first by applicationWillResignActive. + + if (OS::get_singleton()->get_main_loop()) { + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_PAUSED); + } + + on_focus_out(); +} + +void OS_IOS::on_exit_background() { + if (!is_focused) { + on_focus_in(); + + if (OS::get_singleton()->get_main_loop()) { + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_RESUMED); + } + } +} + #endif // IOS_ENABLED