|
@@ -28,16 +28,10 @@
|
|
|
#include "../SDL_sysvideo.h"
|
|
|
#include "../../events/SDL_events_c.h"
|
|
|
|
|
|
-
|
|
|
#include "../../audio/android/SDL_androidaudio.h"
|
|
|
#include "../../audio/aaudio/SDL_aaudio.h"
|
|
|
#include "../../audio/openslES/SDL_openslES.h"
|
|
|
|
|
|
-/* Number of 'type' events in the event queue */
|
|
|
-static int SDL_NumberOfEvents(Uint32 type)
|
|
|
-{
|
|
|
- return SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type);
|
|
|
-}
|
|
|
|
|
|
#ifdef SDL_VIDEO_OPENGL_EGL
|
|
|
static void android_egl_context_restore(SDL_Window *window)
|
|
@@ -54,7 +48,7 @@ static void android_egl_context_restore(SDL_Window *window)
|
|
|
event.common.timestamp = 0;
|
|
|
SDL_PushEvent(&event);
|
|
|
}
|
|
|
- data->backup_done = 0;
|
|
|
+ data->backup_done = SDL_FALSE;
|
|
|
|
|
|
if (data->has_swap_interval) {
|
|
|
SDL_GL_SetSwapInterval(data->swap_interval);
|
|
@@ -79,165 +73,107 @@ static void android_egl_context_backup(SDL_Window *window)
|
|
|
|
|
|
/* We need to do this so the EGLSurface can be freed */
|
|
|
SDL_GL_MakeCurrent(window, NULL);
|
|
|
- data->backup_done = 1;
|
|
|
+ data->backup_done = SDL_TRUE;
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
/*
|
|
|
* Android_ResumeSem and Android_PauseSem are signaled from Java_org_libsdl_app_SDLActivity_nativePause and Java_org_libsdl_app_SDLActivity_nativeResume
|
|
|
- * When the pause semaphore is signaled, if Android_PumpEvents_Blocking is used, the event loop will block until the resume signal is emitted.
|
|
|
- *
|
|
|
- * No polling necessary
|
|
|
*/
|
|
|
+static SDL_bool Android_EventsInitialized;
|
|
|
+static SDL_bool Android_Paused;
|
|
|
+static SDL_bool Android_PausedAudio;
|
|
|
+static Sint32 Android_PausedWaitTime = -1;
|
|
|
|
|
|
-void Android_PumpEvents_Blocking(SDL_VideoDevice *_this)
|
|
|
+void Android_InitEvents(void)
|
|
|
{
|
|
|
- SDL_VideoData *videodata = _this->internal;
|
|
|
-
|
|
|
- if (videodata->isPaused) {
|
|
|
-#ifdef SDL_VIDEO_OPENGL_EGL
|
|
|
- /* Make sure this is the last thing we do before pausing */
|
|
|
- if (Android_Window && !Android_Window->external_graphics_context) {
|
|
|
- SDL_LockMutex(Android_ActivityMutex);
|
|
|
- android_egl_context_backup(Android_Window);
|
|
|
- SDL_UnlockMutex(Android_ActivityMutex);
|
|
|
+ if (!Android_EventsInitialized) {
|
|
|
+ if (SDL_GetHintBoolean(SDL_HINT_ANDROID_BLOCK_ON_PAUSE, SDL_TRUE)) {
|
|
|
+ Android_PausedWaitTime = -1;
|
|
|
+ } else {
|
|
|
+ Android_PausedWaitTime = 100;
|
|
|
}
|
|
|
-#endif
|
|
|
-
|
|
|
- ANDROIDAUDIO_PauseDevices();
|
|
|
- OPENSLES_PauseDevices();
|
|
|
- AAUDIO_PauseDevices();
|
|
|
+ Android_Paused = SDL_FALSE;
|
|
|
+ Android_EventsInitialized = SDL_TRUE;
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- if (SDL_WaitSemaphore(Android_ResumeSem) == 0) {
|
|
|
+void Android_PumpEvents(void)
|
|
|
+{
|
|
|
+restart:
|
|
|
+ if (Android_Paused) {
|
|
|
+ if (SDL_WaitSemaphoreTimeout(Android_ResumeSem, Android_PausedWaitTime) == 0) {
|
|
|
|
|
|
- videodata->isPaused = 0;
|
|
|
+ Android_Paused = SDL_FALSE;
|
|
|
|
|
|
/* Android_ResumeSem was signaled */
|
|
|
- SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_FOREGROUND);
|
|
|
+ SDL_OnApplicationWillEnterForeground();
|
|
|
|
|
|
- ANDROIDAUDIO_ResumeDevices();
|
|
|
- OPENSLES_ResumeDevices();
|
|
|
- AAUDIO_ResumeDevices();
|
|
|
+ if (Android_PausedAudio) {
|
|
|
+ ANDROIDAUDIO_ResumeDevices();
|
|
|
+ OPENSLES_ResumeDevices();
|
|
|
+ AAUDIO_ResumeDevices();
|
|
|
+ }
|
|
|
|
|
|
- /* Restore the GL Context from here, as this operation is thread dependent */
|
|
|
#ifdef SDL_VIDEO_OPENGL_EGL
|
|
|
+ /* Restore the GL Context from here, as this operation is thread dependent */
|
|
|
if (Android_Window && !Android_Window->external_graphics_context && !SDL_HasEvent(SDL_EVENT_QUIT)) {
|
|
|
- SDL_LockMutex(Android_ActivityMutex);
|
|
|
+ Android_LockActivityMutex();
|
|
|
android_egl_context_restore(Android_Window);
|
|
|
- SDL_UnlockMutex(Android_ActivityMutex);
|
|
|
+ Android_UnlockActivityMutex();
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
/* Make sure SW Keyboard is restored when an app becomes foreground */
|
|
|
if (Android_Window) {
|
|
|
- Android_RestoreScreenKeyboardOnResume(_this, Android_Window);
|
|
|
+ Android_RestoreScreenKeyboardOnResume(SDL_GetVideoDevice(), Android_Window);
|
|
|
}
|
|
|
|
|
|
- SDL_SendAppEvent(SDL_EVENT_DID_ENTER_FOREGROUND);
|
|
|
- SDL_SendWindowEvent(Android_Window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
|
|
|
+ SDL_OnApplicationDidEnterForeground();
|
|
|
}
|
|
|
} else {
|
|
|
- if (videodata->isPausing || SDL_TryWaitSemaphore(Android_PauseSem) == 0) {
|
|
|
+ if (SDL_TryWaitSemaphore(Android_PauseSem) == 0) {
|
|
|
|
|
|
/* Android_PauseSem was signaled */
|
|
|
- if (videodata->isPausing == 0) {
|
|
|
- SDL_SendWindowEvent(Android_Window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0);
|
|
|
- SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_BACKGROUND);
|
|
|
- SDL_SendAppEvent(SDL_EVENT_DID_ENTER_BACKGROUND);
|
|
|
- }
|
|
|
+ SDL_OnApplicationWillEnterBackground();
|
|
|
+ SDL_OnApplicationDidEnterBackground();
|
|
|
|
|
|
- /* We've been signaled to pause (potentially several times), but before we block ourselves,
|
|
|
- * we need to make sure that the very last event (of the first pause sequence, if several)
|
|
|
- * has reached the app */
|
|
|
- if (SDL_NumberOfEvents(SDL_EVENT_DID_ENTER_BACKGROUND) > SDL_GetSemaphoreValue(Android_PauseSem)) {
|
|
|
- videodata->isPausing = 1;
|
|
|
- } else {
|
|
|
- videodata->isPausing = 0;
|
|
|
- videodata->isPaused = 1;
|
|
|
+ /* Make sure we handle potentially multiple pause/resume sequences */
|
|
|
+ while (SDL_GetSemaphoreValue(Android_PauseSem) > 0) {
|
|
|
+ SDL_WaitSemaphore(Android_ResumeSem);
|
|
|
+ SDL_WaitSemaphore(Android_PauseSem);
|
|
|
}
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void Android_PumpEvents_NonBlocking(SDL_VideoDevice *_this)
|
|
|
-{
|
|
|
- SDL_VideoData *videodata = _this->internal;
|
|
|
- static int backup_context = 0;
|
|
|
-
|
|
|
- if (videodata->isPaused) {
|
|
|
-
|
|
|
- if (backup_context) {
|
|
|
|
|
|
+ /* The semantics are that as soon as the enter background event
|
|
|
+ * has been queued, the app will block. The application should
|
|
|
+ * do any life cycle handling in an event filter while the event
|
|
|
+ * was being queued.
|
|
|
+ */
|
|
|
#ifdef SDL_VIDEO_OPENGL_EGL
|
|
|
if (Android_Window && !Android_Window->external_graphics_context) {
|
|
|
- SDL_LockMutex(Android_ActivityMutex);
|
|
|
+ Android_LockActivityMutex();
|
|
|
android_egl_context_backup(Android_Window);
|
|
|
- SDL_UnlockMutex(Android_ActivityMutex);
|
|
|
+ Android_UnlockActivityMutex();
|
|
|
}
|
|
|
#endif
|
|
|
-
|
|
|
- if (videodata->pauseAudio) {
|
|
|
+ if (Android_PausedWaitTime < 0) {
|
|
|
+ /* We're blocking, also pause audio */
|
|
|
ANDROIDAUDIO_PauseDevices();
|
|
|
OPENSLES_PauseDevices();
|
|
|
AAUDIO_PauseDevices();
|
|
|
+ Android_PausedAudio = SDL_TRUE;
|
|
|
}
|
|
|
|
|
|
- backup_context = 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (SDL_TryWaitSemaphore(Android_ResumeSem) == 0) {
|
|
|
-
|
|
|
- videodata->isPaused = 0;
|
|
|
-
|
|
|
- /* Android_ResumeSem was signaled */
|
|
|
- SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_FOREGROUND);
|
|
|
-
|
|
|
- if (videodata->pauseAudio) {
|
|
|
- ANDROIDAUDIO_ResumeDevices();
|
|
|
- OPENSLES_ResumeDevices();
|
|
|
- AAUDIO_ResumeDevices();
|
|
|
- }
|
|
|
-
|
|
|
-#ifdef SDL_VIDEO_OPENGL_EGL
|
|
|
- /* Restore the GL Context from here, as this operation is thread dependent */
|
|
|
- if (Android_Window && !Android_Window->external_graphics_context && !SDL_HasEvent(SDL_EVENT_QUIT)) {
|
|
|
- SDL_LockMutex(Android_ActivityMutex);
|
|
|
- android_egl_context_restore(Android_Window);
|
|
|
- SDL_UnlockMutex(Android_ActivityMutex);
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- /* Make sure SW Keyboard is restored when an app becomes foreground */
|
|
|
- if (Android_Window) {
|
|
|
- Android_RestoreScreenKeyboardOnResume(_this, Android_Window);
|
|
|
- }
|
|
|
-
|
|
|
- SDL_SendAppEvent(SDL_EVENT_DID_ENTER_FOREGROUND);
|
|
|
- SDL_SendWindowEvent(Android_Window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (videodata->isPausing || SDL_TryWaitSemaphore(Android_PauseSem) == 0) {
|
|
|
-
|
|
|
- /* Android_PauseSem was signaled */
|
|
|
- if (videodata->isPausing == 0) {
|
|
|
- SDL_SendWindowEvent(Android_Window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0);
|
|
|
- SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_BACKGROUND);
|
|
|
- SDL_SendAppEvent(SDL_EVENT_DID_ENTER_BACKGROUND);
|
|
|
- }
|
|
|
-
|
|
|
- /* We've been signaled to pause (potentially several times), but before we block ourselves,
|
|
|
- * we need to make sure that the very last event (of the first pause sequence, if several)
|
|
|
- * has reached the app */
|
|
|
- if (SDL_NumberOfEvents(SDL_EVENT_DID_ENTER_BACKGROUND) > SDL_GetSemaphoreValue(Android_PauseSem)) {
|
|
|
- videodata->isPausing = 1;
|
|
|
- } else {
|
|
|
- videodata->isPausing = 0;
|
|
|
- videodata->isPaused = 1;
|
|
|
- backup_context = 1;
|
|
|
- }
|
|
|
+ Android_Paused = SDL_TRUE;
|
|
|
+ goto restart;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void Android_QuitEvents(void)
|
|
|
+{
|
|
|
+ Android_EventsInitialized = SDL_FALSE;
|
|
|
+}
|
|
|
+
|
|
|
#endif /* SDL_VIDEO_DRIVER_ANDROID */
|