mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-08-19 13:21:37 +00:00
Android: add command mecanism so that SDLActivity executes no SDL code,
but defers it to SDL main thread
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -52,8 +52,8 @@ typedef enum
|
||||
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);
|
||||
|
||||
@@ -157,6 +157,10 @@ bool Android_JNI_OpenFileDialog(SDL_DialogFileCallback callback, void *userdata,
|
||||
const SDL_DialogFileFilter *filters, int nfilters, bool forwrite,
|
||||
bool multiple);
|
||||
|
||||
// Pump RPC commands
|
||||
void Android_PumpRPC(SDL_Window *window);
|
||||
|
||||
|
||||
// Ends C function definitions when using C++
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
|
||||
@@ -1513,7 +1513,9 @@ static void SDL_PumpEventsInternal(bool push_sentinel)
|
||||
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
// Android event processing is independent of the video subsystem
|
||||
Android_PumpEvents(0);
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
SDL_Window *window = _this->windows;
|
||||
Android_PumpEvents(window, 0);
|
||||
#else
|
||||
// Get events from the video subsystem
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
@@ -1746,7 +1748,10 @@ bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS)
|
||||
}
|
||||
delay = (expiration - now);
|
||||
}
|
||||
Android_PumpEvents(delay);
|
||||
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
SDL_Window *window = _this->windows;
|
||||
Android_PumpEvents(window, delay);
|
||||
}
|
||||
#else
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
|
||||
@@ -64,7 +64,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;
|
||||
@@ -198,7 +198,7 @@ bool Android_OnPadDown(int device_id, int keycode)
|
||||
{
|
||||
Uint64 timestamp = SDL_GetTicksNS();
|
||||
SDL_joylist_item *item;
|
||||
int button = keycode_to_SDL(keycode);
|
||||
int button = android_keycode_to_SDL(keycode);
|
||||
if (button >= 0) {
|
||||
SDL_LockJoysticks();
|
||||
item = JoystickByDeviceId(device_id);
|
||||
@@ -218,7 +218,7 @@ bool Android_OnPadUp(int device_id, int keycode)
|
||||
{
|
||||
Uint64 timestamp = SDL_GetTicksNS();
|
||||
SDL_joylist_item *item;
|
||||
int button = keycode_to_SDL(keycode);
|
||||
int button = android_keycode_to_SDL(keycode);
|
||||
if (button >= 0) {
|
||||
SDL_LockJoysticks();
|
||||
item = JoystickByDeviceId(device_id);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "../SDL_sysjoystick.h"
|
||||
|
||||
extern int android_keycode_to_SDL(int keycode);
|
||||
extern bool Android_OnPadDown(int device_id, int keycode);
|
||||
extern bool Android_OnPadUp(int device_id, int keycode);
|
||||
extern bool Android_OnJoy(int device_id, int axisnum, float value);
|
||||
|
||||
@@ -1069,7 +1069,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
|
||||
}
|
||||
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
if (!Android_WaitActiveAndLockActivity()) {
|
||||
if (!Android_WaitActiveAndLockActivity(window)) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
@@ -1249,7 +1249,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
|
||||
SDL_renderers = renderer;
|
||||
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
Android_UnlockActivityMutex();
|
||||
Android_UnlockActivityState();
|
||||
#endif
|
||||
|
||||
SDL_ClearError();
|
||||
@@ -1258,7 +1258,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
|
||||
|
||||
error:
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
Android_UnlockActivityMutex();
|
||||
Android_UnlockActivityState();
|
||||
#endif
|
||||
|
||||
if (renderer) {
|
||||
|
||||
@@ -35,43 +35,40 @@
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
static void android_egl_context_restore(SDL_Window *window)
|
||||
{
|
||||
if (window) {
|
||||
SDL_WindowData *data = window->internal;
|
||||
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
|
||||
data->egl_context = (EGLContext)SDL_GL_CreateContext(window);
|
||||
SDL_GL_MakeCurrent(window, (SDL_GLContext)data->egl_context);
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
event.type = SDL_EVENT_RENDER_DEVICE_RESET;
|
||||
event.render.windowID = SDL_GetWindowID(window);
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
data->backup_done = false;
|
||||
|
||||
SDL_GL_SetSwapInterval(data->swap_interval);
|
||||
SDL_WindowData *data = window->internal;
|
||||
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
|
||||
data->egl_context = (EGLContext)SDL_GL_CreateContext(window);
|
||||
SDL_GL_MakeCurrent(window, (SDL_GLContext)data->egl_context);
|
||||
SDL_Event event;
|
||||
SDL_zero(event);
|
||||
event.type = SDL_EVENT_RENDER_DEVICE_RESET;
|
||||
event.render.windowID = SDL_GetWindowID(window);
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
data->backup_done = false;
|
||||
|
||||
SDL_GL_SetSwapInterval(data->swap_interval);
|
||||
}
|
||||
|
||||
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;
|
||||
SDL_Log("android_egl_context_backup ...");
|
||||
// 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
|
||||
|
||||
@@ -110,7 +107,7 @@ static void Android_ResumeAudio(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void Android_OnPause(void)
|
||||
static void Android_OnPause(SDL_Window *window)
|
||||
{
|
||||
SDL_OnApplicationWillEnterBackground();
|
||||
SDL_OnApplicationDidEnterBackground();
|
||||
@@ -121,10 +118,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 +131,7 @@ static void Android_OnPause(void)
|
||||
Android_Paused = true;
|
||||
}
|
||||
|
||||
static void Android_OnResume(void)
|
||||
static void Android_OnResume(SDL_Window *window)
|
||||
{
|
||||
Android_Paused = false;
|
||||
|
||||
@@ -146,10 +141,8 @@ 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
|
||||
|
||||
@@ -176,17 +169,17 @@ static void Android_OnDestroy(void)
|
||||
Android_Destroyed = true;
|
||||
}
|
||||
|
||||
static void Android_HandleLifecycleEvent(SDL_AndroidLifecycleEvent event)
|
||||
static void Android_HandleLifecycleEvent(SDL_Window *window, SDL_AndroidLifecycleEvent event)
|
||||
{
|
||||
switch (event) {
|
||||
case SDL_ANDROID_LIFECYCLE_WAKE:
|
||||
// Nothing to do, just return
|
||||
break;
|
||||
case SDL_ANDROID_LIFECYCLE_PAUSE:
|
||||
Android_OnPause();
|
||||
Android_OnPause(window);
|
||||
break;
|
||||
case SDL_ANDROID_LIFECYCLE_RESUME:
|
||||
Android_OnResume();
|
||||
Android_OnResume(window);
|
||||
break;
|
||||
case SDL_ANDROID_LIFECYCLE_LOWMEMORY:
|
||||
Android_OnLowMemory();
|
||||
@@ -211,14 +204,17 @@ static Sint64 GetLifecycleEventTimeout(bool paused, Sint64 timeoutNS)
|
||||
return timeoutNS;
|
||||
}
|
||||
|
||||
void Android_PumpEvents(Sint64 timeoutNS)
|
||||
void Android_PumpEvents(SDL_Window *window, Sint64 timeoutNS)
|
||||
{
|
||||
SDL_AndroidLifecycleEvent event;
|
||||
bool paused = Android_Paused;
|
||||
|
||||
while (!Android_Destroyed &&
|
||||
Android_WaitLifecycleEvent(&event, GetLifecycleEventTimeout(paused, timeoutNS))) {
|
||||
Android_HandleLifecycleEvent(event);
|
||||
|
||||
Android_PumpRPC(window);
|
||||
|
||||
Android_HandleLifecycleEvent(window, event);
|
||||
|
||||
switch (event) {
|
||||
case SDL_ANDROID_LIFECYCLE_WAKE:
|
||||
@@ -238,24 +234,47 @@ void Android_PumpEvents(Sint64 timeoutNS)
|
||||
}
|
||||
}
|
||||
|
||||
bool Android_WaitActiveAndLockActivity(void)
|
||||
|
||||
void Android_PumpLifecycleEvents(SDL_Window *window)
|
||||
{
|
||||
/* Make sure we have pumped all events so that Android_Paused state is correct */
|
||||
// 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);
|
||||
Android_HandleLifecycleEvent(window, event);
|
||||
}
|
||||
}
|
||||
|
||||
while (Android_Paused && !Android_Destroyed) {
|
||||
Android_PumpEvents(-1);
|
||||
}
|
||||
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();
|
||||
|
||||
// Make sure we have pumped all events so that Android_Paused state is correct
|
||||
Android_PumpLifecycleEvents(window);
|
||||
|
||||
if (Android_Destroyed) {
|
||||
SDL_SetError("Android activity has been destroyed");
|
||||
Android_UnlockActivityState();
|
||||
return false;
|
||||
}
|
||||
|
||||
Android_LockActivityMutex();
|
||||
if (!Android_Paused) {
|
||||
// SDLActivity is Active. return lock'ed
|
||||
Android_PumpRPC(window);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "SDL_internal.h"
|
||||
|
||||
extern void Android_InitEvents(void);
|
||||
extern void Android_PumpEvents(Sint64 timeoutNS);
|
||||
extern bool Android_WaitActiveAndLockActivity(void);
|
||||
extern void Android_PumpEvents(SDL_Window *window, Sint64 timeoutNS);
|
||||
extern bool Android_WaitActiveAndLockActivity(SDL_Window *window);
|
||||
extern void Android_QuitEvents(void);
|
||||
|
||||
extern void Android_PumpLifecycleEvents(SDL_Window *window);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -300,15 +300,15 @@ void Android_SendResize(SDL_Window *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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,86 @@ 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_nativeSurfaceCreated(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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// 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
|
||||
|
||||
@@ -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,11 @@ struct SDL_WindowData
|
||||
|
||||
};
|
||||
|
||||
|
||||
bool Android_nativeSurfaceCreated(SDL_Window *window);
|
||||
bool Android_nativeSurfaceChanged(SDL_Window *window);
|
||||
void Android_nativeSurfaceDestroyed(SDL_Window *window);
|
||||
|
||||
|
||||
|
||||
#endif // SDL_androidwindow_h_
|
||||
|
||||
Reference in New Issue
Block a user