This commit is contained in:
Sylvain Becker 2026-06-05 21:13:47 +02:00 committed by GitHub
commit 854e351ac3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 1717 additions and 680 deletions

File diff suppressed because it is too large Load diff

View file

@ -38,22 +38,8 @@ extern "C" {
// this appears to be broken right now (on Android, not SDL, I think...?).
#define ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES 0
// Life cycle
typedef enum
{
SDL_ANDROID_LIFECYCLE_WAKE,
SDL_ANDROID_LIFECYCLE_PAUSE,
SDL_ANDROID_LIFECYCLE_RESUME,
SDL_ANDROID_LIFECYCLE_LOWMEMORY,
SDL_ANDROID_LIFECYCLE_DESTROY,
SDL_NUM_ANDROID_LIFECYCLE_EVENTS
} SDL_AndroidLifecycleEvent;
void Android_SendLifecycleEvent(SDL_AndroidLifecycleEvent event);
bool Android_WaitLifecycleEvent(SDL_AndroidLifecycleEvent *event, Sint64 timeoutNS);
void Android_LockActivityMutex(void);
void Android_UnlockActivityMutex(void);
void Android_LockActivityState(void);
void Android_UnlockActivityState(void);
void Android_SetAllowRecreateActivity(bool enabled);
@ -159,6 +145,11 @@ bool Android_JNI_ShowFileDialog(SDL_DialogFileCallback callback, void *userdata,
const SDL_DialogFileFilter *filters, int nfilters, SDL_FileDialogType type,
bool multiple, const char *initialPath);
// Pump RPC commands
void Android_PumpRPC(SDL_Window *window);
void Android_WaitForResume(void);
// Ends C function definitions when using C++
#ifdef __cplusplus
/* *INDENT-OFF* */

View file

@ -42,7 +42,6 @@
#include "../video/SDL_sysvideo.h"
#ifdef SDL_PLATFORM_ANDROID
#include "../core/android/SDL_android.h"
#include "../video/android/SDL_androidevents.h"
#endif
@ -1153,7 +1152,7 @@ static void SDL_CutEvent(SDL_EventEntry *entry)
static void SDL_SendWakeupEvent(void)
{
#ifdef SDL_PLATFORM_ANDROID
Android_SendLifecycleEvent(SDL_ANDROID_LIFECYCLE_WAKE);
Android_WakeUp();
#else
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this == NULL || !_this->SendWakeupEvent) {
@ -1539,7 +1538,7 @@ static void SDL_PumpEventsInternal(bool push_sentinel)
#ifdef SDL_PLATFORM_ANDROID
// Android event processing is independent of the video subsystem
Android_PumpEvents(0);
Android_PumpEvents();
#else
// Get events from the video subsystem
SDL_VideoDevice *_this = SDL_GetVideoDevice();
@ -1573,7 +1572,12 @@ void SDL_PumpEvents(void)
bool SDL_PollEvent(SDL_Event *event)
{
return SDL_WaitEventTimeoutNS(event, 0);
bool ret = SDL_WaitEventTimeoutNS(event, 0);
#ifdef SDL_PLATFORM_ANDROID
Android_BlockEventLoop();
#endif
return ret;
}
#ifndef SDL_PLATFORM_ANDROID
@ -1763,16 +1767,16 @@ bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS)
return true;
}
Uint64 delay = -1;
Uint64 delay = SDL_MS_TO_NS(10);
if (timeoutNS > 0) {
Uint64 now = SDL_GetTicksNS();
if (now >= expiration) {
// Timeout expired and no events
return false;
}
delay = (expiration - now);
delay = SDL_min((expiration - now), delay);
}
Android_PumpEvents(delay);
SDL_DelayNS(delay);
}
#else
SDL_VideoDevice *_this = SDL_GetVideoDevice();

View file

@ -66,7 +66,7 @@ static int numjoysticks = 0;
* This code manipulation is done to get a sequential list of codes.
* FIXME: This is only suited for the case where we use a fixed number of buttons determined by ANDROID_MAX_NBUTTONS
*/
static int keycode_to_SDL(int keycode)
int Android_keycode_to_SDL(int keycode)
{
// FIXME: If this function gets too unwieldy in the future, replace with a lookup table
int button = 0;
@ -172,7 +172,7 @@ static int keycode_to_SDL(int keycode)
return button;
}
static int scancode_to_SDL(int scancode)
int Android_scancode_to_SDL(int scancode)
{
int button = 0;
switch (scancode) {
@ -226,9 +226,9 @@ bool Android_OnPadDown(int device_id, int keycode, int scancode)
{
Uint64 timestamp = SDL_GetTicksNS();
SDL_joylist_item *item;
int button = keycode_to_SDL(keycode);
int button = Android_keycode_to_SDL(keycode);
if (button < 0) {
button = scancode_to_SDL(scancode);
button = Android_scancode_to_SDL(scancode);
}
if (button >= 0) {
SDL_LockJoysticks();
@ -249,9 +249,9 @@ bool Android_OnPadUp(int device_id, int keycode, int scancode)
{
Uint64 timestamp = SDL_GetTicksNS();
SDL_joylist_item *item;
int button = keycode_to_SDL(keycode);
int button = Android_keycode_to_SDL(keycode);
if (button < 0) {
button = scancode_to_SDL(scancode);
button = Android_scancode_to_SDL(scancode);
}
if (button >= 0) {
SDL_LockJoysticks();

View file

@ -28,6 +28,8 @@
#include "../SDL_sysjoystick.h"
extern int Android_keycode_to_SDL(int keycode);
extern int Android_scancode_to_SDL(int scancode);
extern bool Android_OnPadDown(int device_id, int keycode, int scancode);
extern bool Android_OnPadUp(int device_id, int keycode, int scancode);
extern bool Android_OnJoy(int device_id, int axisnum, float value);

View file

@ -22,6 +22,10 @@
#include "SDL_internal.h"
#include "SDL_main_callbacks.h"
#ifdef SDL_PLATFORM_ANDROID
#include "../video/android/SDL_androidevents.h"
#endif
static SDL_AppEvent_func SDL_main_event_callback;
static SDL_AppIterate_func SDL_main_iteration_callback;
static SDL_AppQuit_func SDL_main_quit_callback;
@ -123,6 +127,11 @@ SDL_AppResult SDL_IterateMainCallbacks(bool pump_events)
if (pump_events) {
SDL_PumpEvents();
}
#ifdef SDL_PLATFORM_ANDROID
Android_BlockEventLoop();
#endif
SDL_DispatchMainCallbackEvents();
SDL_AppResult rc = (SDL_AppResult)SDL_GetAtomicInt(&apprc);

View file

@ -1083,7 +1083,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
}
#ifdef SDL_PLATFORM_ANDROID
if (!Android_WaitActiveAndLockActivity()) {
if (!Android_WaitActiveAndLockActivity(window)) {
return NULL;
}
#endif
@ -1263,7 +1263,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
SDL_renderers = renderer;
#ifdef SDL_PLATFORM_ANDROID
Android_UnlockActivityMutex();
Android_UnlockActivityState();
#endif
SDL_ClearError();
@ -1272,7 +1272,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
error:
#ifdef SDL_PLATFORM_ANDROID
Android_UnlockActivityMutex();
Android_UnlockActivityState();
#endif
if (renderer) {

View file

@ -33,10 +33,14 @@
#ifdef SDL_VIDEO_OPENGL_EGL
static void android_egl_context_restore(SDL_Window *window)
// Restore EGL context when we have both:
// nativeSurfaceCreated()
// and SDLActivity hasFocus();
void Android_egl_context_restore(SDL_Window *window)
{
if (window) {
SDL_WindowData *data = window->internal;
SDL_WindowData *data = window->internal;
if (data->backup_done && data->egl_surface != EGL_NO_SURFACE) {
SDL_GL_MakeCurrent(window, NULL);
if (!SDL_GL_MakeCurrent(window, (SDL_GLContext)data->egl_context)) {
// The context is no longer valid, create a new one
@ -54,24 +58,22 @@ static void android_egl_context_restore(SDL_Window *window)
}
}
static void android_egl_context_backup(SDL_Window *window)
static void Android_egl_context_backup(SDL_Window *window)
{
if (window) {
int interval = 0;
// Keep a copy of the EGL Context so we can try to restore it when we resume
SDL_WindowData *data = window->internal;
data->egl_context = SDL_GL_GetCurrentContext();
int interval = 0;
// Keep a copy of the EGL Context so we can try to restore it when we resume
SDL_WindowData *data = window->internal;
data->egl_context = SDL_GL_GetCurrentContext();
// Save/Restore the swap interval / vsync
if (SDL_GL_GetSwapInterval(&interval)) {
data->has_swap_interval = 1;
data->swap_interval = interval;
}
// We need to do this so the EGLSurface can be freed
SDL_GL_MakeCurrent(window, NULL);
data->backup_done = true;
// Save/Restore the swap interval / vsync
if (SDL_GL_GetSwapInterval(&interval)) {
data->has_swap_interval = 1;
data->swap_interval = interval;
}
// We need to do this so the EGLSurface can be freed
SDL_GL_MakeCurrent(window, NULL);
data->backup_done = true;
}
#endif
@ -103,6 +105,7 @@ static void Android_PauseAudio(void)
static void Android_ResumeAudio(void)
{
if (Android_PausedAudio) {
OPENSLES_ResumeDevices();
AAUDIO_ResumeDevices();
@ -110,7 +113,12 @@ static void Android_ResumeAudio(void)
}
}
static void Android_OnPause(void)
bool Android_RenderingAvailable()
{
return !Android_Paused;
}
void Android_OnPause(SDL_Window *window)
{
SDL_OnApplicationWillEnterBackground();
SDL_OnApplicationDidEnterBackground();
@ -121,10 +129,8 @@ static void Android_OnPause(void)
* was being queued.
*/
#ifdef SDL_VIDEO_OPENGL_EGL
if (Android_Window && !Android_Window->external_graphics_context) {
Android_LockActivityMutex();
android_egl_context_backup(Android_Window);
Android_UnlockActivityMutex();
if (window && !window->external_graphics_context) {
Android_egl_context_backup(window);
}
#endif
@ -136,7 +142,7 @@ static void Android_OnPause(void)
Android_Paused = true;
}
static void Android_OnResume(void)
void Android_OnResume(SDL_Window *window)
{
Android_Paused = false;
@ -146,22 +152,15 @@ static void Android_OnResume(void)
#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)) {
Android_LockActivityMutex();
android_egl_context_restore(Android_Window);
Android_UnlockActivityMutex();
if (window && !window->external_graphics_context && !SDL_HasEvent(SDL_EVENT_QUIT)) {
Android_egl_context_restore(window);
}
#endif
SDL_OnApplicationDidEnterForeground();
}
static void Android_OnLowMemory(void)
{
SDL_SendAppEvent(SDL_EVENT_LOW_MEMORY);
}
static void Android_OnDestroy(void)
void Android_OnDestroy(void)
{
// Make sure we unblock any audio processing before we quit
Android_ResumeAudio();
@ -176,86 +175,77 @@ static void Android_OnDestroy(void)
Android_Destroyed = true;
}
static void Android_HandleLifecycleEvent(SDL_AndroidLifecycleEvent event)
void Android_PumpEvents()
{
switch (event) {
case SDL_ANDROID_LIFECYCLE_WAKE:
// Nothing to do, just return
break;
case SDL_ANDROID_LIFECYCLE_PAUSE:
Android_OnPause();
break;
case SDL_ANDROID_LIFECYCLE_RESUME:
Android_OnResume();
break;
case SDL_ANDROID_LIFECYCLE_LOWMEMORY:
Android_OnLowMemory();
break;
case SDL_ANDROID_LIFECYCLE_DESTROY:
Android_OnDestroy();
break;
default:
break;
}
}
static Sint64 GetLifecycleEventTimeout(bool paused, Sint64 timeoutNS)
{
if (Android_Paused) {
if (Android_BlockOnPause) {
timeoutNS = -1;
} else if (timeoutNS == 0) {
timeoutNS = SDL_MS_TO_NS(100);
}
}
return timeoutNS;
}
void Android_PumpEvents(Sint64 timeoutNS)
{
SDL_AndroidLifecycleEvent event;
bool paused = Android_Paused;
while (!Android_Destroyed &&
Android_WaitLifecycleEvent(&event, GetLifecycleEventTimeout(paused, timeoutNS))) {
Android_HandleLifecycleEvent(event);
switch (event) {
case SDL_ANDROID_LIFECYCLE_WAKE:
// Finish handling events quickly if we're not paused
timeoutNS = 0;
break;
case SDL_ANDROID_LIFECYCLE_PAUSE:
// Finish handling events at the current timeout and return to process events one more time before blocking.
break;
case SDL_ANDROID_LIFECYCLE_RESUME:
// Finish handling events at the resume state timeout
paused = false;
break;
default:
break;
}
}
}
bool Android_WaitActiveAndLockActivity(void)
{
/* Make sure we have pumped all events so that Android_Paused state is correct */
SDL_AndroidLifecycleEvent event;
while (!Android_Destroyed && Android_WaitLifecycleEvent(&event, 0)) {
Android_HandleLifecycleEvent(event);
}
while (Android_Paused && !Android_Destroyed) {
Android_PumpEvents(-1);
}
SDL_VideoDevice *_this = SDL_GetVideoDevice();
SDL_Window *window = _this ? _this->windows : NULL;
if (Android_Destroyed) {
SDL_SetError("Android activity has been destroyed");
return;
}
Android_PumpRPC(window);
}
// return 'true' if app has been blocked
bool Android_BlockEventLoop()
{
if (Android_Destroyed) {
return false;
}
Android_LockActivityMutex();
if (Android_Paused) {
if (Android_BlockOnPause) {
SDL_Log("BlockOnPause");
Android_WaitForResume();
SDL_Log("BlockOnPause...resume");
// app has been blocked. now we're unblocked.
// pump to get 'resume' command (eg RPC_cmd_nativeResume).
SDL_VideoDevice *_this = SDL_GetVideoDevice();
SDL_Window *window = _this ? _this->windows : NULL;
Android_PumpRPC(window);
return true;
}
}
return false;
}
bool Android_WaitActiveAndLockActivity(SDL_Window *window)
{
retry:
// Lock first.
// So no new lifecycle event comes in the meantimes from the SDLActivity,
// Hence SDLActivity won't change state.
Android_LockActivityState();
// Pump all events so that Android_Paused state is correct
Android_PumpRPC(window);
if (Android_Destroyed) {
SDL_SetError("Android activity has been destroyed");
Android_UnlockActivityState();
return false;
}
if (!Android_Paused) {
// SDLActivity is Active. return lock'ed
return true;
} else {
// Still Paused
// Unlock and wait for the SDLActivity to send new cycle events
// or for the user to move the app to foreground.
Android_UnlockActivityState();
SDL_Delay(10);
goto retry;
}
return true;
}

View file

@ -21,6 +21,16 @@
#include "SDL_internal.h"
extern void Android_InitEvents(void);
extern void Android_PumpEvents(Sint64 timeoutNS);
extern bool Android_WaitActiveAndLockActivity(void);
extern void Android_PumpEvents(void);
extern bool Android_BlockEventLoop(void);
extern bool Android_WaitActiveAndLockActivity(SDL_Window *window);
extern void Android_QuitEvents(void);
#ifdef SDL_VIDEO_OPENGL_EGL
void Android_egl_context_restore(SDL_Window *window);
#endif
void Android_OnPause(SDL_Window *window);
void Android_OnResume(SDL_Window *window);
void Android_OnDestroy(void);
void Android_WakeUp(void);
bool Android_RenderingAvailable(void);

View file

@ -49,13 +49,13 @@ SDL_GLContext Android_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *win
{
SDL_GLContext result;
if (!Android_WaitActiveAndLockActivity()) {
if (!Android_WaitActiveAndLockActivity(window)) {
return NULL;
}
result = SDL_EGL_CreateContext(_this, window->internal->egl_surface);
Android_UnlockActivityMutex();
Android_UnlockActivityState();
return result;
}
@ -64,8 +64,6 @@ bool Android_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
bool result;
Android_LockActivityMutex();
/* The following two calls existed in the original Java code
* If you happen to have a device that's affected by their removal,
* please report to our bug tracker. -- Gabriel
@ -75,8 +73,6 @@ bool Android_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
_this->egl_data->eglWaitGL();*/
result = SDL_EGL_SwapBuffers(_this, window->internal->egl_surface);
Android_UnlockActivityMutex();
return result;
}

View file

@ -455,7 +455,7 @@ void Android_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window)
void Android_RestoreScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window)
{
if (_this->screen_keyboard_shown) {
if (_this && _this->screen_keyboard_shown && window) {
Android_ShowScreenKeyboard(_this, window, window->text_input_props);
}
}

View file

@ -298,17 +298,22 @@ void Android_SendResize(SDL_Window *window)
if (window) {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, Android_SurfaceWidth, Android_SurfaceHeight);
}
// onNativeResize() should probably merged in to onNativeSurfaceChanged() so that
// both RPC commands are executed atomically without user app trying to render inbetween
// (and so Android_NativeSurfaceResized is called from Android_NativeSurfaceChanged())
Android_NativeSurfaceResized(window);
}
void Android_SetWindowSafeAreaInsets(int left, int right, int top, int bottom)
void Android_SetWindowSafeAreaInsets(SDL_Window *window, int left, int right, int top, int bottom)
{
Android_SafeInsetLeft = left;
Android_SafeInsetRight = right;
Android_SafeInsetTop = top;
Android_SafeInsetBottom = bottom;
if (Android_Window) {
SDL_SetWindowSafeAreaInsets(Android_Window, left, right, top, bottom);
if (window) {
SDL_SetWindowSafeAreaInsets(window, left, right, top, bottom);
}
}

View file

@ -30,7 +30,7 @@ extern void Android_SetScreenResolution(int surfaceWidth, int surfaceHeight, int
extern void Android_SetFormat(int format_wanted, int format_got);
extern void Android_SetOrientation(SDL_DisplayOrientation orientation);
extern void Android_SendResize(SDL_Window *window);
extern void Android_SetWindowSafeAreaInsets(int left, int right, int top, int bottom);
extern void Android_SetWindowSafeAreaInsets(SDL_Window *window, int left, int right, int top, int bottom);
extern void Android_SetDarkMode(bool enabled);
// Private display data

View file

@ -34,18 +34,32 @@
// Currently only one window
SDL_Window *Android_Window = NULL;
static bool window_created = false;
bool Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props)
{
SDL_WindowData *data;
bool result = true;
if (!Android_WaitActiveAndLockActivity()) {
// Android_WaitActiveAndLockActivity() process some RPC:
// "onSurfaceCreated" that needs "window->internal"
// and also "nativeSetScreenResolution"
data = (SDL_WindowData *)SDL_calloc(1, sizeof(*data));
if (!data) {
return false;
}
if (Android_Window) {
#ifdef SDL_VIDEO_OPENGL_EGL
data->egl_surface = EGL_NO_SURFACE;
#endif
window->internal = data;
if (!Android_WaitActiveAndLockActivity(window)) {
return false;
}
if (window_created) {
result = SDL_SetError("Android only supports one window");
goto endfunction;
}
@ -63,44 +77,23 @@ bool Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Proper
SDL_SetMouseFocus(window);
SDL_SetKeyboardFocus(window);
data = (SDL_WindowData *)SDL_calloc(1, sizeof(*data));
if (!data) {
if (!Android_NativeSurfaceCreated(window)) {
result = false;
goto endfunction;
}
data->native_window = Android_JNI_GetNativeWindow();
if (!data->native_window) {
SDL_free(data);
result = SDL_SetError("Could not fetch native window");
if (!Android_NativeSurfaceChanged(window)) {
result = false;
goto endfunction;
}
SDL_SetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER, data->native_window);
/* Do not create EGLSurface for Vulkan window since it will then make the window
incompatible with vkCreateAndroidSurfaceKHR */
#ifdef SDL_VIDEO_OPENGL_EGL
if (window->flags & SDL_WINDOW_OPENGL) {
data->egl_surface = SDL_EGL_CreateSurface(_this, window, (NativeWindowType)data->native_window);
if (data->egl_surface == EGL_NO_SURFACE) {
ANativeWindow_release(data->native_window);
SDL_free(data);
result = false;
goto endfunction;
}
}
SDL_SetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_ANDROID_SURFACE_POINTER, data->egl_surface);
#endif
SDL_SetWindowSafeAreaInsets(window, Android_SafeInsetLeft, Android_SafeInsetRight, Android_SafeInsetTop, Android_SafeInsetBottom);
window->internal = data;
Android_Window = window;
window_created = true;
endfunction:
Android_UnlockActivityMutex();
Android_UnlockActivityState();
return result;
}
@ -112,54 +105,48 @@ void Android_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window)
SDL_FullscreenResult Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_FullscreenOp fullscreen)
{
Android_LockActivityMutex();
SDL_WindowData *data;
int old_w, old_h, new_w, new_h;
if (window == Android_Window) {
SDL_WindowData *data;
int old_w, old_h, new_w, new_h;
// If the window is being destroyed don't change visible state
if (!window->is_destroying) {
Android_JNI_SetWindowStyle(fullscreen);
}
// If the window is being destroyed don't change visible state
if (!window->is_destroying) {
Android_JNI_SetWindowStyle(fullscreen);
/* Ensure our size matches reality after we've executed the window style change.
*
* It is possible that we've set width and height to the full-size display, but on
* Samsung DeX or Chromebooks or other windowed Android environments, our window may
* still not be the full display size.
*/
if (!SDL_IsDeXMode() && !SDL_IsChromebook()) {
goto endfunction;
}
data = window->internal;
if (!data || !data->native_window) {
if (data && !data->native_window) {
SDL_SetError("Missing native window");
}
goto endfunction;
}
/* Ensure our size matches reality after we've executed the window style change.
*
* It is possible that we've set width and height to the full-size display, but on
* Samsung DeX or Chromebooks or other windowed Android environments, our window may
* still not be the full display size.
*/
if (!SDL_IsDeXMode() && !SDL_IsChromebook()) {
goto endfunction;
}
old_w = window->w;
old_h = window->h;
data = window->internal;
if (!data || !data->native_window) {
if (data && !data->native_window) {
SDL_SetError("Missing native window");
}
goto endfunction;
}
new_w = ANativeWindow_getWidth(data->native_window);
new_h = ANativeWindow_getHeight(data->native_window);
old_w = window->w;
old_h = window->h;
if (new_w < 0 || new_h < 0) {
SDL_SetError("ANativeWindow_getWidth/Height() fails");
}
new_w = ANativeWindow_getWidth(data->native_window);
new_h = ANativeWindow_getHeight(data->native_window);
if (new_w < 0 || new_h < 0) {
SDL_SetError("ANativeWindow_getWidth/Height() fails");
}
if (old_w != new_w || old_h != new_h) {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, new_w, new_h);
}
if (old_w != new_w || old_h != new_h) {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, new_w, new_h);
}
endfunction:
Android_UnlockActivityMutex();
return SDL_FULLSCREEN_SUCCEEDED;
}
@ -176,29 +163,108 @@ void Android_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, bool
void Android_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
Android_LockActivityMutex();
window_created = false;
if (window == Android_Window) {
Android_Window = NULL;
if (window->internal) {
SDL_WindowData *data = window->internal;
if (window->internal) {
Android_NativeSurfaceDestroyed(window);
SDL_free(window->internal);
window->internal = NULL;
}
}
#ifdef SDL_VIDEO_OPENGL_EGL
if (data->egl_surface != EGL_NO_SURFACE) {
SDL_EGL_DestroySurface(_this, data->egl_surface);
}
#endif
if (data->native_window) {
ANativeWindow_release(data->native_window);
}
SDL_free(window->internal);
window->internal = NULL;
// Those functions called from RPC onNativeSurface{Created,Changed,Destroyed}()
// and SDL_{Create,Destroy}Window();
bool Android_NativeSurfaceCreated(SDL_Window *window)
{
if (window) {
SDL_WindowData *data = window->internal;
data->native_window = Android_JNI_GetNativeWindow();
SDL_SetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER, data->native_window);
if (data->native_window == NULL) {
SDL_SetError("Could not fetch native window");
return false;
}
return true;
}
Android_UnlockActivityMutex();
return false;
}
// Resize surface
void Android_NativeSurfaceResized(SDL_Window *window)
{
if (window) {
SDL_WindowData *data = window->internal;
if (data->native_window) {
int format = 0;
int new_w = ANativeWindow_getWidth(data->native_window);
int new_h = ANativeWindow_getHeight(data->native_window);
ANativeWindow_setBuffersGeometry(data->native_window, new_w, new_h, format);
}
}
}
bool Android_NativeSurfaceChanged(SDL_Window *window)
{
if (window) {
#ifdef SDL_VIDEO_OPENGL_EGL
/* Do not create EGLSurface for Vulkan window since it will then make the window
incompatible with vkCreateAndroidSurfaceKHR */
if (window->flags & SDL_WINDOW_OPENGL) {
SDL_VideoDevice *_this = SDL_GetVideoDevice();
SDL_WindowData *data = window->internal;
// Make sure native_window is valid
if (!data->native_window) {
if (!Android_NativeSurfaceCreated(window)) {
return false;
}
}
// If the surface has been previously destroyed by onNativeSurfaceDestroyed
// or if it is the first time, recreate it.
if (data->egl_surface == EGL_NO_SURFACE) {
data->egl_surface = SDL_EGL_CreateSurface(_this, window, (NativeWindowType)data->native_window);
SDL_SetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_ANDROID_SURFACE_POINTER, data->egl_surface);
}
if (data->egl_surface == EGL_NO_SURFACE) {
if (data->native_window) {
ANativeWindow_release(data->native_window);
data->native_window = 0;
}
return false;
}
}
#endif
return true;
}
return false;
}
void Android_NativeSurfaceDestroyed(SDL_Window *window)
{
if (window) {
SDL_WindowData *data = window->internal;
#ifdef SDL_VIDEO_OPENGL_EGL
if (data->egl_surface != EGL_NO_SURFACE) {
SDL_EGL_DestroySurface(SDL_GetVideoDevice(), data->egl_surface);
data->egl_surface = EGL_NO_SURFACE;
}
#endif
if (data->native_window) {
ANativeWindow_release(data->native_window);
data->native_window = NULL;
}
}
}
#endif // SDL_VIDEO_DRIVER_ANDROID

View file

@ -33,7 +33,6 @@ extern void Android_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern void Android_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, bool resizable);
extern void Android_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern SDL_Window *Android_Window;
struct SDL_WindowData
{
@ -48,4 +47,9 @@ struct SDL_WindowData
};
bool Android_NativeSurfaceCreated(SDL_Window *window);
bool Android_NativeSurfaceChanged(SDL_Window *window);
void Android_NativeSurfaceDestroyed(SDL_Window *window);
void Android_NativeSurfaceResized(SDL_Window *window);
#endif // SDL_androidwindow_h_