From 5a079a2d114f96d4847d1ee305d5b7c16eeec50e Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 27 Dec 2025 12:03:39 -0800 Subject: Initial commit --- .../src/video/android/SDL_androidclipboard.c | 44 ++ .../src/video/android/SDL_androidclipboard.h | 30 ++ .../src/video/android/SDL_androidevents.c | 269 ++++++++++++ .../src/video/android/SDL_androidevents.h | 26 ++ .../SDL-3.2.8/src/video/android/SDL_androidgl.c | 88 ++++ .../SDL-3.2.8/src/video/android/SDL_androidgl.h | 31 ++ .../src/video/android/SDL_androidkeyboard.c | 468 +++++++++++++++++++++ .../src/video/android/SDL_androidkeyboard.h | 32 ++ .../src/video/android/SDL_androidmessagebox.c | 33 ++ .../src/video/android/SDL_androidmessagebox.h | 27 ++ .../SDL-3.2.8/src/video/android/SDL_androidmouse.c | 250 +++++++++++ .../SDL-3.2.8/src/video/android/SDL_androidmouse.h | 31 ++ .../SDL-3.2.8/src/video/android/SDL_androidpen.c | 98 +++++ .../SDL-3.2.8/src/video/android/SDL_androidpen.h | 25 ++ .../SDL-3.2.8/src/video/android/SDL_androidtouch.c | 96 +++++ .../SDL-3.2.8/src/video/android/SDL_androidtouch.h | 27 ++ .../SDL-3.2.8/src/video/android/SDL_androidvideo.c | 331 +++++++++++++++ .../SDL-3.2.8/src/video/android/SDL_androidvideo.h | 52 +++ .../src/video/android/SDL_androidvulkan.c | 171 ++++++++ .../src/video/android/SDL_androidvulkan.h | 52 +++ .../src/video/android/SDL_androidwindow.c | 204 +++++++++ .../src/video/android/SDL_androidwindow.h | 51 +++ 22 files changed, 2436 insertions(+) create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidclipboard.c create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidclipboard.h create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidevents.c create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidevents.h create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidgl.c create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidgl.h create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidkeyboard.c create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidkeyboard.h create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidmessagebox.c create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidmessagebox.h create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidmouse.c create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidmouse.h create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidpen.c create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidpen.h create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidtouch.c create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidtouch.h create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidvideo.c create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidvideo.h create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidvulkan.c create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidvulkan.h create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidwindow.c create mode 100644 contrib/SDL-3.2.8/src/video/android/SDL_androidwindow.h (limited to 'contrib/SDL-3.2.8/src/video/android') diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidclipboard.c b/contrib/SDL-3.2.8/src/video/android/SDL_androidclipboard.c new file mode 100644 index 0000000..ec02350 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidclipboard.c @@ -0,0 +1,44 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_ANDROID + +#include "SDL_androidvideo.h" +#include "SDL_androidclipboard.h" +#include "../../core/android/SDL_android.h" + +bool Android_SetClipboardText(SDL_VideoDevice *_this, const char *text) +{ + return Android_JNI_SetClipboardText(text); +} + +char *Android_GetClipboardText(SDL_VideoDevice *_this) +{ + return Android_JNI_GetClipboardText(); +} + +bool Android_HasClipboardText(SDL_VideoDevice *_this) +{ + return Android_JNI_HasClipboardText(); +} + +#endif // SDL_VIDEO_DRIVER_ANDROID diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidclipboard.h b/contrib/SDL-3.2.8/src/video/android/SDL_androidclipboard.h new file mode 100644 index 0000000..d102112 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidclipboard.h @@ -0,0 +1,30 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifndef SDL_androidclipboard_h_ +#define SDL_androidclipboard_h_ + +extern bool Android_SetClipboardText(SDL_VideoDevice *_this, const char *text); +extern char *Android_GetClipboardText(SDL_VideoDevice *_this); +extern bool Android_HasClipboardText(SDL_VideoDevice *_this); + +#endif // SDL_androidclipboard_h_ diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidevents.c b/contrib/SDL-3.2.8/src/video/android/SDL_androidevents.c new file mode 100644 index 0000000..e32d272 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidevents.c @@ -0,0 +1,269 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_ANDROID + +#include "SDL_androidevents.h" +#include "SDL_androidkeyboard.h" +#include "SDL_androidwindow.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_events_c.h" + +#include "../../audio/aaudio/SDL_aaudio.h" +#include "../../audio/openslES/SDL_openslES.h" + + +#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; + + if (data->has_swap_interval) { + 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(); + + // 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 + +/* + * Android_ResumeSem and Android_PauseSem are signaled from Java_org_libsdl_app_SDLActivity_nativePause and Java_org_libsdl_app_SDLActivity_nativeResume + */ +static bool Android_EventsInitialized; +static bool Android_BlockOnPause = true; +static bool Android_Paused; +static bool Android_PausedAudio; +static bool Android_Destroyed; + +void Android_InitEvents(void) +{ + if (!Android_EventsInitialized) { + Android_BlockOnPause = SDL_GetHintBoolean(SDL_HINT_ANDROID_BLOCK_ON_PAUSE, true); + Android_Paused = false; + Android_Destroyed = false; + Android_EventsInitialized = true; + } +} + +static void Android_PauseAudio(void) +{ + OPENSLES_PauseDevices(); + AAUDIO_PauseDevices(); + Android_PausedAudio = true; +} + +static void Android_ResumeAudio(void) +{ + if (Android_PausedAudio) { + OPENSLES_ResumeDevices(); + AAUDIO_ResumeDevices(); + Android_PausedAudio = false; + } +} + +static void Android_OnPause(void) +{ + SDL_OnApplicationWillEnterBackground(); + SDL_OnApplicationDidEnterBackground(); + + /* 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) { + Android_LockActivityMutex(); + android_egl_context_backup(Android_Window); + Android_UnlockActivityMutex(); + } +#endif + + if (Android_BlockOnPause) { + // We're blocking, also pause audio + Android_PauseAudio(); + } + + Android_Paused = true; +} + +static void Android_OnResume(void) +{ + Android_Paused = false; + + SDL_OnApplicationWillEnterForeground(); + + Android_ResumeAudio(); + +#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(); + } +#endif + + // Make sure SW Keyboard is restored when an app becomes foreground + if (Android_Window) { + Android_RestoreScreenKeyboardOnResume(SDL_GetVideoDevice(), Android_Window); + } + + SDL_OnApplicationDidEnterForeground(); +} + +static void Android_OnLowMemory(void) +{ + SDL_SendAppEvent(SDL_EVENT_LOW_MEMORY); +} + +static void Android_OnDestroy(void) +{ + // Make sure we unblock any audio processing before we quit + Android_ResumeAudio(); + + /* Discard previous events. The user should have handled state storage + * in SDL_EVENT_WILL_ENTER_BACKGROUND. After nativeSendQuit() is called, no + * events other than SDL_EVENT_QUIT and SDL_EVENT_TERMINATING should fire */ + SDL_FlushEvents(SDL_EVENT_FIRST, SDL_EVENT_LAST); + SDL_SendQuit(); + SDL_SendAppEvent(SDL_EVENT_TERMINATING); + + Android_Destroyed = true; +} + +static void Android_HandleLifecycleEvent(SDL_AndroidLifecycleEvent event) +{ + 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) +{ + while (Android_Paused && !Android_Destroyed) { + Android_PumpEvents(-1); + } + + if (Android_Destroyed) { + SDL_SetError("Android activity has been destroyed"); + return false; + } + + Android_LockActivityMutex(); + return true; +} + +void Android_QuitEvents(void) +{ + Android_EventsInitialized = false; +} + +#endif // SDL_VIDEO_DRIVER_ANDROID diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidevents.h b/contrib/SDL-3.2.8/src/video/android/SDL_androidevents.h new file mode 100644 index 0000000..bb57d3b --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidevents.h @@ -0,0 +1,26 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +extern void Android_InitEvents(void); +extern void Android_PumpEvents(Sint64 timeoutNS); +extern bool Android_WaitActiveAndLockActivity(void); +extern void Android_QuitEvents(void); diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidgl.c b/contrib/SDL-3.2.8/src/video/android/SDL_androidgl.c new file mode 100644 index 0000000..37fb2d5 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidgl.c @@ -0,0 +1,88 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#if defined(SDL_VIDEO_DRIVER_ANDROID) && defined(SDL_VIDEO_OPENGL_EGL) + +// Android SDL video driver implementation + +#include "../SDL_egl_c.h" +#include "SDL_androidwindow.h" + +#include "SDL_androidvideo.h" +#include "SDL_androidevents.h" +#include "SDL_androidgl.h" +#include "../../core/android/SDL_android.h" + +#include + +#include + +bool Android_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context) +{ + if (window && context) { + return SDL_EGL_MakeCurrent(_this, window->internal->egl_surface, context); + } else { + return SDL_EGL_MakeCurrent(_this, NULL, NULL); + } +} + +SDL_GLContext Android_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window) +{ + SDL_GLContext result; + + if (!Android_WaitActiveAndLockActivity()) { + return NULL; + } + + result = SDL_EGL_CreateContext(_this, window->internal->egl_surface); + + Android_UnlockActivityMutex(); + + return result; +} + +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 + */ + + /*_this->egl_data->eglWaitNative(EGL_CORE_NATIVE_ENGINE); + _this->egl_data->eglWaitGL();*/ + result = SDL_EGL_SwapBuffers(_this, window->internal->egl_surface); + + Android_UnlockActivityMutex(); + + return result; +} + +bool Android_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path) +{ + return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType)0, 0); +} + +#endif // SDL_VIDEO_DRIVER_ANDROID diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidgl.h b/contrib/SDL-3.2.8/src/video/android/SDL_androidgl.h new file mode 100644 index 0000000..99c84d0 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidgl.h @@ -0,0 +1,31 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifndef SDL_androidgl_h_ +#define SDL_androidgl_h_ + +extern SDL_GLContext Android_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window); +extern bool Android_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context); +extern bool Android_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window); +extern bool Android_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path); + +#endif // SDL_androidgl_h_ diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidkeyboard.c b/contrib/SDL-3.2.8/src/video/android/SDL_androidkeyboard.c new file mode 100644 index 0000000..03af7c6 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidkeyboard.c @@ -0,0 +1,468 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_ANDROID + +#include + +#include "../../events/SDL_events_c.h" + +#include "SDL_androidkeyboard.h" + +#include "../../core/android/SDL_android.h" + +#define TYPE_CLASS_TEXT 0x00000001 +#define TYPE_CLASS_NUMBER 0x00000002 +#define TYPE_CLASS_PHONE 0x00000003 +#define TYPE_CLASS_DATETIME 0x00000004 + +#define TYPE_DATETIME_VARIATION_NORMAL 0x00000000 +#define TYPE_DATETIME_VARIATION_DATE 0x00000010 +#define TYPE_DATETIME_VARIATION_TIME 0x00000020 + +#define TYPE_NUMBER_VARIATION_NORMAL 0x00000000 +#define TYPE_NUMBER_VARIATION_PASSWORD 0x00000010 +#define TYPE_NUMBER_FLAG_SIGNED 0x00001000 +#define TYPE_NUMBER_FLAG_DECIMAL 0x00002000 + +#define TYPE_TEXT_FLAG_CAP_CHARACTERS 0x00001000 +#define TYPE_TEXT_FLAG_CAP_WORDS 0x00002000 +#define TYPE_TEXT_FLAG_CAP_SENTENCES 0x00004000 +#define TYPE_TEXT_FLAG_AUTO_CORRECT 0x00008000 +#define TYPE_TEXT_FLAG_AUTO_COMPLETE 0x00010000 +#define TYPE_TEXT_FLAG_MULTI_LINE 0x00020000 +#define TYPE_TEXT_FLAG_IME_MULTI_LINE 0x00040000 +#define TYPE_TEXT_FLAG_NO_SUGGESTIONS 0x00080000 + +#define TYPE_TEXT_VARIATION_NORMAL 0x00000000 +#define TYPE_TEXT_VARIATION_URI 0x00000010 +#define TYPE_TEXT_VARIATION_EMAIL_ADDRESS 0x00000020 +#define TYPE_TEXT_VARIATION_EMAIL_SUBJECT 0x00000030 +#define TYPE_TEXT_VARIATION_SHORT_MESSAGE 0x00000040 +#define TYPE_TEXT_VARIATION_LONG_MESSAGE 0x00000050 +#define TYPE_TEXT_VARIATION_PERSON_NAME 0x00000060 +#define TYPE_TEXT_VARIATION_POSTAL_ADDRESS 0x00000070 +#define TYPE_TEXT_VARIATION_PASSWORD 0x00000080 +#define TYPE_TEXT_VARIATION_VISIBLE_PASSWORD 0x00000090 +#define TYPE_TEXT_VARIATION_WEB_EDIT_TEXT 0x000000a0 +#define TYPE_TEXT_VARIATION_FILTER 0x000000b0 +#define TYPE_TEXT_VARIATION_PHONETIC 0x000000c0 +#define TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS 0x000000d0 +#define TYPE_TEXT_VARIATION_WEB_PASSWORD 0x000000e0 + + +static SDL_Scancode Android_Keycodes[] = { + SDL_SCANCODE_UNKNOWN, // AKEYCODE_UNKNOWN + SDL_SCANCODE_SOFTLEFT, // AKEYCODE_SOFT_LEFT + SDL_SCANCODE_SOFTRIGHT, // AKEYCODE_SOFT_RIGHT + SDL_SCANCODE_AC_HOME, // AKEYCODE_HOME + SDL_SCANCODE_AC_BACK, // AKEYCODE_BACK + SDL_SCANCODE_CALL, // AKEYCODE_CALL + SDL_SCANCODE_ENDCALL, // AKEYCODE_ENDCALL + SDL_SCANCODE_0, // AKEYCODE_0 + SDL_SCANCODE_1, // AKEYCODE_1 + SDL_SCANCODE_2, // AKEYCODE_2 + SDL_SCANCODE_3, // AKEYCODE_3 + SDL_SCANCODE_4, // AKEYCODE_4 + SDL_SCANCODE_5, // AKEYCODE_5 + SDL_SCANCODE_6, // AKEYCODE_6 + SDL_SCANCODE_7, // AKEYCODE_7 + SDL_SCANCODE_8, // AKEYCODE_8 + SDL_SCANCODE_9, // AKEYCODE_9 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_STAR + SDL_SCANCODE_UNKNOWN, // AKEYCODE_POUND + SDL_SCANCODE_UP, // AKEYCODE_DPAD_UP + SDL_SCANCODE_DOWN, // AKEYCODE_DPAD_DOWN + SDL_SCANCODE_LEFT, // AKEYCODE_DPAD_LEFT + SDL_SCANCODE_RIGHT, // AKEYCODE_DPAD_RIGHT + SDL_SCANCODE_SELECT, // AKEYCODE_DPAD_CENTER + SDL_SCANCODE_VOLUMEUP, // AKEYCODE_VOLUME_UP + SDL_SCANCODE_VOLUMEDOWN, // AKEYCODE_VOLUME_DOWN + SDL_SCANCODE_POWER, // AKEYCODE_POWER + SDL_SCANCODE_UNKNOWN, // AKEYCODE_CAMERA + SDL_SCANCODE_CLEAR, // AKEYCODE_CLEAR + SDL_SCANCODE_A, // AKEYCODE_A + SDL_SCANCODE_B, // AKEYCODE_B + SDL_SCANCODE_C, // AKEYCODE_C + SDL_SCANCODE_D, // AKEYCODE_D + SDL_SCANCODE_E, // AKEYCODE_E + SDL_SCANCODE_F, // AKEYCODE_F + SDL_SCANCODE_G, // AKEYCODE_G + SDL_SCANCODE_H, // AKEYCODE_H + SDL_SCANCODE_I, // AKEYCODE_I + SDL_SCANCODE_J, // AKEYCODE_J + SDL_SCANCODE_K, // AKEYCODE_K + SDL_SCANCODE_L, // AKEYCODE_L + SDL_SCANCODE_M, // AKEYCODE_M + SDL_SCANCODE_N, // AKEYCODE_N + SDL_SCANCODE_O, // AKEYCODE_O + SDL_SCANCODE_P, // AKEYCODE_P + SDL_SCANCODE_Q, // AKEYCODE_Q + SDL_SCANCODE_R, // AKEYCODE_R + SDL_SCANCODE_S, // AKEYCODE_S + SDL_SCANCODE_T, // AKEYCODE_T + SDL_SCANCODE_U, // AKEYCODE_U + SDL_SCANCODE_V, // AKEYCODE_V + SDL_SCANCODE_W, // AKEYCODE_W + SDL_SCANCODE_X, // AKEYCODE_X + SDL_SCANCODE_Y, // AKEYCODE_Y + SDL_SCANCODE_Z, // AKEYCODE_Z + SDL_SCANCODE_COMMA, // AKEYCODE_COMMA + SDL_SCANCODE_PERIOD, // AKEYCODE_PERIOD + SDL_SCANCODE_LALT, // AKEYCODE_ALT_LEFT + SDL_SCANCODE_RALT, // AKEYCODE_ALT_RIGHT + SDL_SCANCODE_LSHIFT, // AKEYCODE_SHIFT_LEFT + SDL_SCANCODE_RSHIFT, // AKEYCODE_SHIFT_RIGHT + SDL_SCANCODE_TAB, // AKEYCODE_TAB + SDL_SCANCODE_SPACE, // AKEYCODE_SPACE + SDL_SCANCODE_UNKNOWN, // AKEYCODE_SYM + SDL_SCANCODE_UNKNOWN, // AKEYCODE_EXPLORER + SDL_SCANCODE_UNKNOWN, // AKEYCODE_ENVELOPE + SDL_SCANCODE_RETURN, // AKEYCODE_ENTER + SDL_SCANCODE_BACKSPACE, // AKEYCODE_DEL + SDL_SCANCODE_GRAVE, // AKEYCODE_GRAVE + SDL_SCANCODE_MINUS, // AKEYCODE_MINUS + SDL_SCANCODE_EQUALS, // AKEYCODE_EQUALS + SDL_SCANCODE_LEFTBRACKET, // AKEYCODE_LEFT_BRACKET + SDL_SCANCODE_RIGHTBRACKET, // AKEYCODE_RIGHT_BRACKET + SDL_SCANCODE_BACKSLASH, // AKEYCODE_BACKSLASH + SDL_SCANCODE_SEMICOLON, // AKEYCODE_SEMICOLON + SDL_SCANCODE_APOSTROPHE, // AKEYCODE_APOSTROPHE + SDL_SCANCODE_SLASH, // AKEYCODE_SLASH + SDL_SCANCODE_UNKNOWN, // AKEYCODE_AT + SDL_SCANCODE_UNKNOWN, // AKEYCODE_NUM + SDL_SCANCODE_UNKNOWN, // AKEYCODE_HEADSETHOOK + SDL_SCANCODE_UNKNOWN, // AKEYCODE_FOCUS + SDL_SCANCODE_UNKNOWN, // AKEYCODE_PLUS + SDL_SCANCODE_MENU, // AKEYCODE_MENU + SDL_SCANCODE_UNKNOWN, // AKEYCODE_NOTIFICATION + SDL_SCANCODE_AC_SEARCH, // AKEYCODE_SEARCH + SDL_SCANCODE_MEDIA_PLAY_PAUSE, // AKEYCODE_MEDIA_PLAY_PAUSE + SDL_SCANCODE_MEDIA_STOP, // AKEYCODE_MEDIA_STOP + SDL_SCANCODE_MEDIA_NEXT_TRACK, // AKEYCODE_MEDIA_NEXT + SDL_SCANCODE_MEDIA_PREVIOUS_TRACK, // AKEYCODE_MEDIA_PREVIOUS + SDL_SCANCODE_MEDIA_REWIND, // AKEYCODE_MEDIA_REWIND + SDL_SCANCODE_MEDIA_FAST_FORWARD, // AKEYCODE_MEDIA_FAST_FORWARD + SDL_SCANCODE_MUTE, // AKEYCODE_MUTE + SDL_SCANCODE_PAGEUP, // AKEYCODE_PAGE_UP + SDL_SCANCODE_PAGEDOWN, // AKEYCODE_PAGE_DOWN + SDL_SCANCODE_UNKNOWN, // AKEYCODE_PICTSYMBOLS + SDL_SCANCODE_UNKNOWN, // AKEYCODE_SWITCH_CHARSET + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_A + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_B + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_C + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_X + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_Y + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_Z + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_L1 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_R1 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_L2 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_R2 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_THUMBL + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_THUMBR + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_START + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_SELECT + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_MODE + SDL_SCANCODE_ESCAPE, // AKEYCODE_ESCAPE + SDL_SCANCODE_DELETE, // AKEYCODE_FORWARD_DEL + SDL_SCANCODE_LCTRL, // AKEYCODE_CTRL_LEFT + SDL_SCANCODE_RCTRL, // AKEYCODE_CTRL_RIGHT + SDL_SCANCODE_CAPSLOCK, // AKEYCODE_CAPS_LOCK + SDL_SCANCODE_SCROLLLOCK, // AKEYCODE_SCROLL_LOCK + SDL_SCANCODE_LGUI, // AKEYCODE_META_LEFT + SDL_SCANCODE_RGUI, // AKEYCODE_META_RIGHT + SDL_SCANCODE_UNKNOWN, // AKEYCODE_FUNCTION + SDL_SCANCODE_PRINTSCREEN, // AKEYCODE_SYSRQ + SDL_SCANCODE_PAUSE, // AKEYCODE_BREAK + SDL_SCANCODE_HOME, // AKEYCODE_MOVE_HOME + SDL_SCANCODE_END, // AKEYCODE_MOVE_END + SDL_SCANCODE_INSERT, // AKEYCODE_INSERT + SDL_SCANCODE_AC_FORWARD, // AKEYCODE_FORWARD + SDL_SCANCODE_MEDIA_PLAY, // AKEYCODE_MEDIA_PLAY + SDL_SCANCODE_MEDIA_PAUSE, // AKEYCODE_MEDIA_PAUSE + SDL_SCANCODE_UNKNOWN, // AKEYCODE_MEDIA_CLOSE + SDL_SCANCODE_MEDIA_EJECT, // AKEYCODE_MEDIA_EJECT + SDL_SCANCODE_MEDIA_RECORD, // AKEYCODE_MEDIA_RECORD + SDL_SCANCODE_F1, // AKEYCODE_F1 + SDL_SCANCODE_F2, // AKEYCODE_F2 + SDL_SCANCODE_F3, // AKEYCODE_F3 + SDL_SCANCODE_F4, // AKEYCODE_F4 + SDL_SCANCODE_F5, // AKEYCODE_F5 + SDL_SCANCODE_F6, // AKEYCODE_F6 + SDL_SCANCODE_F7, // AKEYCODE_F7 + SDL_SCANCODE_F8, // AKEYCODE_F8 + SDL_SCANCODE_F9, // AKEYCODE_F9 + SDL_SCANCODE_F10, // AKEYCODE_F10 + SDL_SCANCODE_F11, // AKEYCODE_F11 + SDL_SCANCODE_F12, // AKEYCODE_F12 + SDL_SCANCODE_NUMLOCKCLEAR, // AKEYCODE_NUM_LOCK + SDL_SCANCODE_KP_0, // AKEYCODE_NUMPAD_0 + SDL_SCANCODE_KP_1, // AKEYCODE_NUMPAD_1 + SDL_SCANCODE_KP_2, // AKEYCODE_NUMPAD_2 + SDL_SCANCODE_KP_3, // AKEYCODE_NUMPAD_3 + SDL_SCANCODE_KP_4, // AKEYCODE_NUMPAD_4 + SDL_SCANCODE_KP_5, // AKEYCODE_NUMPAD_5 + SDL_SCANCODE_KP_6, // AKEYCODE_NUMPAD_6 + SDL_SCANCODE_KP_7, // AKEYCODE_NUMPAD_7 + SDL_SCANCODE_KP_8, // AKEYCODE_NUMPAD_8 + SDL_SCANCODE_KP_9, // AKEYCODE_NUMPAD_9 + SDL_SCANCODE_KP_DIVIDE, // AKEYCODE_NUMPAD_DIVIDE + SDL_SCANCODE_KP_MULTIPLY, // AKEYCODE_NUMPAD_MULTIPLY + SDL_SCANCODE_KP_MINUS, // AKEYCODE_NUMPAD_SUBTRACT + SDL_SCANCODE_KP_PLUS, // AKEYCODE_NUMPAD_ADD + SDL_SCANCODE_KP_PERIOD, // AKEYCODE_NUMPAD_DOT + SDL_SCANCODE_KP_COMMA, // AKEYCODE_NUMPAD_COMMA + SDL_SCANCODE_KP_ENTER, // AKEYCODE_NUMPAD_ENTER + SDL_SCANCODE_KP_EQUALS, // AKEYCODE_NUMPAD_EQUALS + SDL_SCANCODE_KP_LEFTPAREN, // AKEYCODE_NUMPAD_LEFT_PAREN + SDL_SCANCODE_KP_RIGHTPAREN, // AKEYCODE_NUMPAD_RIGHT_PAREN + SDL_SCANCODE_UNKNOWN, // AKEYCODE_VOLUME_MUTE + SDL_SCANCODE_UNKNOWN, // AKEYCODE_INFO + SDL_SCANCODE_CHANNEL_INCREMENT, // AKEYCODE_CHANNEL_UP + SDL_SCANCODE_CHANNEL_INCREMENT, // AKEYCODE_CHANNEL_DOWN + SDL_SCANCODE_UNKNOWN, // AKEYCODE_ZOOM_IN + SDL_SCANCODE_UNKNOWN, // AKEYCODE_ZOOM_OUT + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV + SDL_SCANCODE_UNKNOWN, // AKEYCODE_WINDOW + SDL_SCANCODE_UNKNOWN, // AKEYCODE_GUIDE + SDL_SCANCODE_UNKNOWN, // AKEYCODE_DVR + SDL_SCANCODE_AC_BOOKMARKS, // AKEYCODE_BOOKMARK + SDL_SCANCODE_UNKNOWN, // AKEYCODE_CAPTIONS + SDL_SCANCODE_UNKNOWN, // AKEYCODE_SETTINGS + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_POWER + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_INPUT + SDL_SCANCODE_UNKNOWN, // AKEYCODE_STB_POWER + SDL_SCANCODE_UNKNOWN, // AKEYCODE_STB_INPUT + SDL_SCANCODE_UNKNOWN, // AKEYCODE_AVR_POWER + SDL_SCANCODE_UNKNOWN, // AKEYCODE_AVR_INPUT + SDL_SCANCODE_UNKNOWN, // AKEYCODE_PROG_RED + SDL_SCANCODE_UNKNOWN, // AKEYCODE_PROG_GREEN + SDL_SCANCODE_UNKNOWN, // AKEYCODE_PROG_YELLOW + SDL_SCANCODE_UNKNOWN, // AKEYCODE_PROG_BLUE + SDL_SCANCODE_UNKNOWN, // AKEYCODE_APP_SWITCH + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_1 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_2 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_3 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_4 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_5 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_6 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_7 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_8 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_9 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_10 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_11 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_12 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_13 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_14 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_15 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BUTTON_16 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_LANGUAGE_SWITCH + SDL_SCANCODE_UNKNOWN, // AKEYCODE_MANNER_MODE + SDL_SCANCODE_UNKNOWN, // AKEYCODE_3D_MODE + SDL_SCANCODE_UNKNOWN, // AKEYCODE_CONTACTS + SDL_SCANCODE_UNKNOWN, // AKEYCODE_CALENDAR + SDL_SCANCODE_UNKNOWN, // AKEYCODE_MUSIC + SDL_SCANCODE_UNKNOWN, // AKEYCODE_CALCULATOR + SDL_SCANCODE_LANG5, // AKEYCODE_ZENKAKU_HANKAKU + SDL_SCANCODE_UNKNOWN, // AKEYCODE_EISU + SDL_SCANCODE_INTERNATIONAL5, // AKEYCODE_MUHENKAN + SDL_SCANCODE_INTERNATIONAL4, // AKEYCODE_HENKAN + SDL_SCANCODE_LANG3, // AKEYCODE_KATAKANA_HIRAGANA + SDL_SCANCODE_INTERNATIONAL3, // AKEYCODE_YEN + SDL_SCANCODE_UNKNOWN, // AKEYCODE_RO + SDL_SCANCODE_UNKNOWN, // AKEYCODE_KANA + SDL_SCANCODE_UNKNOWN, // AKEYCODE_ASSIST + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BRIGHTNESS_DOWN + SDL_SCANCODE_UNKNOWN, // AKEYCODE_BRIGHTNESS_UP + SDL_SCANCODE_UNKNOWN, // AKEYCODE_MEDIA_AUDIO_TRACK + SDL_SCANCODE_SLEEP, // AKEYCODE_SLEEP + SDL_SCANCODE_UNKNOWN, // AKEYCODE_WAKEUP + SDL_SCANCODE_UNKNOWN, // AKEYCODE_PAIRING + SDL_SCANCODE_UNKNOWN, // AKEYCODE_MEDIA_TOP_MENU + SDL_SCANCODE_UNKNOWN, // AKEYCODE_11 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_12 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_LAST_CHANNEL + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_DATA_SERVICE + SDL_SCANCODE_UNKNOWN, // AKEYCODE_VOICE_ASSIST + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_RADIO_SERVICE + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_TELETEXT + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_NUMBER_ENTRY + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_TERRESTRIAL_ANALOG + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_TERRESTRIAL_DIGITAL + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_SATELLITE + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_SATELLITE_BS + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_SATELLITE_CS + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_SATELLITE_SERVICE + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_NETWORK + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_ANTENNA_CABLE + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_INPUT_HDMI_1 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_INPUT_HDMI_2 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_INPUT_HDMI_3 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_INPUT_HDMI_4 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_INPUT_COMPOSITE_1 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_INPUT_COMPOSITE_2 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_INPUT_COMPONENT_1 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_INPUT_COMPONENT_2 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_INPUT_VGA_1 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_AUDIO_DESCRIPTION + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_ZOOM_MODE + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_CONTENTS_MENU + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_MEDIA_CONTEXT_MENU + SDL_SCANCODE_UNKNOWN, // AKEYCODE_TV_TIMER_PROGRAMMING + SDL_SCANCODE_HELP, // AKEYCODE_HELP + SDL_SCANCODE_UNKNOWN, // AKEYCODE_NAVIGATE_PREVIOUS + SDL_SCANCODE_UNKNOWN, // AKEYCODE_NAVIGATE_NEXT + SDL_SCANCODE_UNKNOWN, // AKEYCODE_NAVIGATE_IN + SDL_SCANCODE_UNKNOWN, // AKEYCODE_NAVIGATE_OUT + SDL_SCANCODE_UNKNOWN, // AKEYCODE_STEM_PRIMARY + SDL_SCANCODE_UNKNOWN, // AKEYCODE_STEM_1 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_STEM_2 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_STEM_3 + SDL_SCANCODE_UNKNOWN, // AKEYCODE_DPAD_UP_LEFT + SDL_SCANCODE_UNKNOWN, // AKEYCODE_DPAD_DOWN_LEFT + SDL_SCANCODE_UNKNOWN, // AKEYCODE_DPAD_UP_RIGHT + SDL_SCANCODE_UNKNOWN, // AKEYCODE_DPAD_DOWN_RIGHT + SDL_SCANCODE_UNKNOWN, // AKEYCODE_MEDIA_SKIP_FORWARD + SDL_SCANCODE_UNKNOWN, // AKEYCODE_MEDIA_SKIP_BACKWARD + SDL_SCANCODE_UNKNOWN, // AKEYCODE_MEDIA_STEP_FORWARD + SDL_SCANCODE_UNKNOWN, // AKEYCODE_MEDIA_STEP_BACKWARD + SDL_SCANCODE_UNKNOWN, // AKEYCODE_SOFT_SLEEP + SDL_SCANCODE_CUT, // AKEYCODE_CUT + SDL_SCANCODE_COPY, // AKEYCODE_COPY + SDL_SCANCODE_PASTE, // AKEYCODE_PASTE +}; + +static bool SDL_screen_keyboard_shown; + +static SDL_Scancode TranslateKeycode(int keycode) +{ + SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN; + + if (keycode < SDL_arraysize(Android_Keycodes)) { + scancode = Android_Keycodes[keycode]; + } + if (scancode == SDL_SCANCODE_UNKNOWN) { + __android_log_print(ANDROID_LOG_INFO, "SDL", "Unknown keycode %d", keycode); + } + return scancode; +} + +void Android_OnKeyDown(int keycode) +{ + SDL_SendKeyboardKey(0, SDL_DEFAULT_KEYBOARD_ID, keycode, TranslateKeycode(keycode), true); +} + +void Android_OnKeyUp(int keycode) +{ + SDL_SendKeyboardKey(0, SDL_DEFAULT_KEYBOARD_ID, keycode, TranslateKeycode(keycode), false); +} + +bool Android_HasScreenKeyboardSupport(SDL_VideoDevice *_this) +{ + return true; +} + +void Android_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props) +{ + int input_type = 0; + if (SDL_HasProperty(props, SDL_PROP_TEXTINPUT_ANDROID_INPUTTYPE_NUMBER)) { + input_type = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTINPUT_ANDROID_INPUTTYPE_NUMBER, 0); + } else { + switch (SDL_GetTextInputType(props)) { + default: + case SDL_TEXTINPUT_TYPE_TEXT: + input_type = (TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_NORMAL); + break; + case SDL_TEXTINPUT_TYPE_TEXT_NAME: + input_type = (TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PERSON_NAME); + break; + case SDL_TEXTINPUT_TYPE_TEXT_EMAIL: + input_type = (TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_EMAIL_ADDRESS); + break; + case SDL_TEXTINPUT_TYPE_TEXT_USERNAME: + input_type = (TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_NORMAL); + break; + case SDL_TEXTINPUT_TYPE_TEXT_PASSWORD_HIDDEN: + input_type = (TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD); + break; + case SDL_TEXTINPUT_TYPE_TEXT_PASSWORD_VISIBLE: + input_type = (TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_VISIBLE_PASSWORD); + break; + case SDL_TEXTINPUT_TYPE_NUMBER: + input_type = (TYPE_CLASS_NUMBER | TYPE_NUMBER_VARIATION_NORMAL); + break; + case SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_HIDDEN: + input_type = (TYPE_CLASS_NUMBER | TYPE_NUMBER_VARIATION_PASSWORD); + break; + case SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_VISIBLE: + input_type = (TYPE_CLASS_NUMBER | TYPE_NUMBER_VARIATION_NORMAL); + break; + } + + switch (SDL_GetTextInputCapitalization(props)) { + default: + case SDL_CAPITALIZE_NONE: + break; + case SDL_CAPITALIZE_LETTERS: + input_type |= TYPE_TEXT_FLAG_CAP_CHARACTERS; + break; + case SDL_CAPITALIZE_WORDS: + input_type |= TYPE_TEXT_FLAG_CAP_WORDS; + break; + case SDL_CAPITALIZE_SENTENCES: + input_type |= TYPE_TEXT_FLAG_CAP_SENTENCES; + break; + } + + if (SDL_GetTextInputAutocorrect(props)) { + input_type |= (TYPE_TEXT_FLAG_AUTO_CORRECT | TYPE_TEXT_FLAG_AUTO_COMPLETE); + } + + if (SDL_GetTextInputMultiline(props)) { + input_type |= TYPE_TEXT_FLAG_MULTI_LINE; + } + } + Android_JNI_ShowScreenKeyboard(input_type, &window->text_input_rect); + SDL_screen_keyboard_shown = true; +} + +void Android_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window) +{ + Android_JNI_HideScreenKeyboard(); + SDL_screen_keyboard_shown = false; +} + +void Android_RestoreScreenKeyboardOnResume(SDL_VideoDevice *_this, SDL_Window *window) +{ + if (SDL_screen_keyboard_shown) { + Android_ShowScreenKeyboard(_this, window, window->text_input_props); + } +} + +bool Android_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window) +{ + return Android_JNI_IsScreenKeyboardShown(); +} + +#endif // SDL_VIDEO_DRIVER_ANDROID diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidkeyboard.h b/contrib/SDL-3.2.8/src/video/android/SDL_androidkeyboard.h new file mode 100644 index 0000000..c192991 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidkeyboard.h @@ -0,0 +1,32 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#include "SDL_androidvideo.h" + +extern void Android_OnKeyDown(int keycode); +extern void Android_OnKeyUp(int keycode); + +extern bool Android_HasScreenKeyboardSupport(SDL_VideoDevice *_this); +extern void Android_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props); +extern void Android_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window); +extern void Android_RestoreScreenKeyboardOnResume(SDL_VideoDevice *_this, SDL_Window *window); +extern bool Android_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidmessagebox.c b/contrib/SDL-3.2.8/src/video/android/SDL_androidmessagebox.c new file mode 100644 index 0000000..9387082 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidmessagebox.c @@ -0,0 +1,33 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_ANDROID + +#include "SDL_androidmessagebox.h" +#include "../../core/android/SDL_android.h" + +bool Android_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID) +{ + return Android_JNI_ShowMessageBox(messageboxdata, buttonID); +} + +#endif // SDL_VIDEO_DRIVER_ANDROID diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidmessagebox.h b/contrib/SDL-3.2.8/src/video/android/SDL_androidmessagebox.h new file mode 100644 index 0000000..6cd5d7c --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidmessagebox.h @@ -0,0 +1,27 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_ANDROID + +extern bool Android_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID); + +#endif // SDL_VIDEO_DRIVER_ANDROID diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidmouse.c b/contrib/SDL-3.2.8/src/video/android/SDL_androidmouse.c new file mode 100644 index 0000000..2facf0d --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidmouse.c @@ -0,0 +1,250 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_ANDROID + +#include "SDL_androidmouse.h" + +#include "../../events/SDL_mouse_c.h" + +#include "../../core/android/SDL_android.h" + +// See Android's MotionEvent class for constants +#define ACTION_DOWN 0 +#define ACTION_UP 1 +#define ACTION_MOVE 2 +#define ACTION_HOVER_MOVE 7 +#define ACTION_SCROLL 8 +#define BUTTON_PRIMARY 1 +#define BUTTON_SECONDARY 2 +#define BUTTON_TERTIARY 4 +#define BUTTON_BACK 8 +#define BUTTON_FORWARD 16 + +struct SDL_CursorData +{ + int custom_cursor; + int system_cursor; +}; + +// Last known Android mouse button state (includes all buttons) +static int last_state; + +// Blank cursor +static SDL_Cursor *empty_cursor; + +static SDL_Cursor *Android_WrapCursor(int custom_cursor, int system_cursor) +{ + SDL_Cursor *cursor; + + cursor = SDL_calloc(1, sizeof(*cursor)); + if (cursor) { + SDL_CursorData *data = (SDL_CursorData *)SDL_calloc(1, sizeof(*data)); + if (data) { + data->custom_cursor = custom_cursor; + data->system_cursor = system_cursor; + cursor->internal = data; + } else { + SDL_free(cursor); + cursor = NULL; + } + } + + return cursor; +} + +static SDL_Cursor *Android_CreateDefaultCursor(void) +{ + SDL_SystemCursor id = SDL_GetDefaultSystemCursor(); + return Android_WrapCursor(0, id); +} + +static SDL_Cursor *Android_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) +{ + int custom_cursor; + SDL_Surface *converted; + + converted = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ARGB8888); + if (!converted) { + return NULL; + } + custom_cursor = Android_JNI_CreateCustomCursor(converted, hot_x, hot_y); + SDL_DestroySurface(converted); + if (!custom_cursor) { + SDL_Unsupported(); + return NULL; + } + return Android_WrapCursor(custom_cursor, 0); +} + +static SDL_Cursor *Android_CreateSystemCursor(SDL_SystemCursor id) +{ + return Android_WrapCursor(0, id); +} + +static void Android_FreeCursor(SDL_Cursor *cursor) +{ + SDL_CursorData *data = cursor->internal; + if (data->custom_cursor != 0) { + Android_JNI_DestroyCustomCursor(data->custom_cursor); + } + SDL_free(cursor->internal); + SDL_free(cursor); +} + +static SDL_Cursor *Android_CreateEmptyCursor(void) +{ + if (!empty_cursor) { + SDL_Surface *empty_surface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_ARGB8888); + if (empty_surface) { + SDL_memset(empty_surface->pixels, 0, (size_t)empty_surface->h * empty_surface->pitch); + empty_cursor = Android_CreateCursor(empty_surface, 0, 0); + SDL_DestroySurface(empty_surface); + } + } + return empty_cursor; +} + +static void Android_DestroyEmptyCursor(void) +{ + if (empty_cursor) { + Android_FreeCursor(empty_cursor); + empty_cursor = NULL; + } +} + +static bool Android_ShowCursor(SDL_Cursor *cursor) +{ + if (!cursor) { + cursor = Android_CreateEmptyCursor(); + } + if (cursor) { + SDL_CursorData *data = cursor->internal; + if (data->custom_cursor) { + if (!Android_JNI_SetCustomCursor(data->custom_cursor)) { + return SDL_Unsupported(); + } + } else { + if (!Android_JNI_SetSystemCursor(data->system_cursor)) { + return SDL_Unsupported(); + } + } + return true; + } else { + // SDL error set inside Android_CreateEmptyCursor() + return false; + } +} + +static bool Android_SetRelativeMouseMode(bool enabled) +{ + if (!Android_JNI_SupportsRelativeMouse()) { + return SDL_Unsupported(); + } + + if (!Android_JNI_SetRelativeMouseEnabled(enabled)) { + return SDL_Unsupported(); + } + + return true; +} + +void Android_InitMouse(void) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + + mouse->CreateCursor = Android_CreateCursor; + mouse->CreateSystemCursor = Android_CreateSystemCursor; + mouse->ShowCursor = Android_ShowCursor; + mouse->FreeCursor = Android_FreeCursor; + mouse->SetRelativeMouseMode = Android_SetRelativeMouseMode; + + SDL_SetDefaultCursor(Android_CreateDefaultCursor()); + + last_state = 0; +} + +void Android_QuitMouse(void) +{ + Android_DestroyEmptyCursor(); +} + +// Translate Android mouse button state to SDL mouse button +static Uint8 TranslateButton(int state) +{ + if (state & BUTTON_PRIMARY) { + return SDL_BUTTON_LEFT; + } else if (state & BUTTON_SECONDARY) { + return SDL_BUTTON_RIGHT; + } else if (state & BUTTON_TERTIARY) { + return SDL_BUTTON_MIDDLE; + } else if (state & BUTTON_FORWARD) { + return SDL_BUTTON_X1; + } else if (state & BUTTON_BACK) { + return SDL_BUTTON_X2; + } else { + return 0; + } +} + +void Android_OnMouse(SDL_Window *window, int state, int action, float x, float y, bool relative) +{ + int changes; + Uint8 button; + + if (!window) { + return; + } + + switch (action) { + case ACTION_DOWN: + changes = state & ~last_state; + button = TranslateButton(changes); + last_state = state; + SDL_SendMouseMotion(0, window, SDL_DEFAULT_MOUSE_ID, relative, x, y); + SDL_SendMouseButton(0, window, SDL_DEFAULT_MOUSE_ID, button, true); + break; + + case ACTION_UP: + changes = last_state & ~state; + button = TranslateButton(changes); + last_state = state; + SDL_SendMouseMotion(0, window, SDL_DEFAULT_MOUSE_ID, relative, x, y); + SDL_SendMouseButton(0, window, SDL_DEFAULT_MOUSE_ID, button, false); + break; + + case ACTION_MOVE: + case ACTION_HOVER_MOVE: + SDL_SendMouseMotion(0, window, SDL_DEFAULT_MOUSE_ID, relative, x, y); + break; + + case ACTION_SCROLL: + SDL_SendMouseWheel(0, window, SDL_DEFAULT_MOUSE_ID, x, y, SDL_MOUSEWHEEL_NORMAL); + break; + + default: + break; + } +} + +#endif // SDL_VIDEO_DRIVER_ANDROID diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidmouse.h b/contrib/SDL-3.2.8/src/video/android/SDL_androidmouse.h new file mode 100644 index 0000000..3a5d01a --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidmouse.h @@ -0,0 +1,31 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_androidmouse_h_ +#define SDL_androidmouse_h_ + +#include "SDL_androidvideo.h" + +extern void Android_InitMouse(void); +extern void Android_OnMouse(SDL_Window *window, int button, int action, float x, float y, bool relative); +extern void Android_QuitMouse(void); + +#endif // SDL_androidmouse_h_ diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidpen.c b/contrib/SDL-3.2.8/src/video/android/SDL_androidpen.c new file mode 100644 index 0000000..e287cab --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidpen.c @@ -0,0 +1,98 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_ANDROID + +#include "SDL_androidpen.h" +#include "../../events/SDL_pen_c.h" +#include "../../core/android/SDL_android.h" + +#define ACTION_DOWN 0 +#define ACTION_UP 1 +#define ACTION_CANCEL 3 +#define ACTION_POINTER_DOWN 5 +#define ACTION_POINTER_UP 6 +#define ACTION_HOVER_EXIT 10 + +void Android_OnPen(SDL_Window *window, int pen_id_in, int button, int action, float x, float y, float p) +{ + if (!window) { + return; + } + + // pointer index starts from zero. + pen_id_in++; + + SDL_PenID pen = SDL_FindPenByHandle((void *) (size_t) pen_id_in); + if (!pen) { + // TODO: Query JNI for pen device info + SDL_PenInfo peninfo; + SDL_zero(peninfo); + peninfo.capabilities = SDL_PEN_CAPABILITY_PRESSURE | SDL_PEN_CAPABILITY_ERASER; + peninfo.num_buttons = 2; + peninfo.subtype = SDL_PEN_TYPE_PEN; + pen = SDL_AddPenDevice(0, NULL, &peninfo, (void *) (size_t) pen_id_in); + if (!pen) { + SDL_Log("error: can't add a pen device %d", pen_id_in); + return; + } + } + + SDL_SendPenMotion(0, pen, window, x, y); + SDL_SendPenAxis(0, pen, window, SDL_PEN_AXIS_PRESSURE, p); + // TODO: add more axis + + SDL_PenInputFlags current = SDL_GetPenStatus(pen, NULL, 0); + int diff = current ^ button; + if (diff != 0) { + // Android only exposes BUTTON_STYLUS_PRIMARY and BUTTON_STYLUS_SECONDARY + if (diff & SDL_PEN_INPUT_BUTTON_1) + SDL_SendPenButton(0, pen, window, 1, (button & SDL_PEN_INPUT_BUTTON_1) != 0); + + if (diff & SDL_PEN_INPUT_BUTTON_2) + SDL_SendPenButton(0, pen, window, 2, (button & SDL_PEN_INPUT_BUTTON_2) != 0); + } + + // button contains DOWN/ERASER_TIP on DOWN/UP regardless of pressed state, use action to distinguish + // we don't compare tip flags above because MotionEvent.getButtonState doesn't return stylus tip/eraser state. + switch (action) { + case ACTION_CANCEL: + case ACTION_HOVER_EXIT: + SDL_RemovePenDevice(0, pen); + break; + + case ACTION_DOWN: + case ACTION_POINTER_DOWN: + SDL_SendPenTouch(0, pen, window, (button & SDL_PEN_INPUT_ERASER_TIP) != 0, true); + break; + + case ACTION_UP: + case ACTION_POINTER_UP: + SDL_SendPenTouch(0, pen, window, (button & SDL_PEN_INPUT_ERASER_TIP) != 0, false); + break; + + default: + break; + } +} + +#endif // SDL_VIDEO_DRIVER_ANDROID diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidpen.h b/contrib/SDL-3.2.8/src/video/android/SDL_androidpen.h new file mode 100644 index 0000000..99a5aee --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidpen.h @@ -0,0 +1,25 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#include "SDL_androidvideo.h" + +extern void Android_OnPen(SDL_Window *window, int pen_id_in, int button, int action, float x, float y, float p); diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidtouch.c b/contrib/SDL-3.2.8/src/video/android/SDL_androidtouch.c new file mode 100644 index 0000000..661c9a1 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidtouch.c @@ -0,0 +1,96 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_ANDROID + +#include + +#include "SDL_androidtouch.h" +#include "../../events/SDL_mouse_c.h" +#include "../../events/SDL_touch_c.h" +#include "../../core/android/SDL_android.h" + +#define ACTION_DOWN 0 +#define ACTION_UP 1 +#define ACTION_MOVE 2 +#define ACTION_CANCEL 3 +// #define ACTION_OUTSIDE 4 +#define ACTION_POINTER_DOWN 5 +#define ACTION_POINTER_UP 6 + +void Android_InitTouch(void) +{ + // Add all touch devices + Android_JNI_InitTouch(); +} + +void Android_QuitTouch(void) +{ +} + +void Android_OnTouch(SDL_Window *window, int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p) +{ + SDL_TouchID touchDeviceId = 0; + SDL_FingerID fingerId = 0; + + if (!window) { + return; + } + + /* Touch device -1 appears when using Android emulator, eg: + * adb shell input mouse tap 100 100 + * adb shell input touchscreen tap 100 100 + */ + touchDeviceId = (SDL_TouchID)(touch_device_id_in + 2); + + // Finger ID should be greater than 0 + fingerId = (SDL_FingerID)(pointer_finger_id_in + 1); + + if (SDL_AddTouch(touchDeviceId, SDL_TOUCH_DEVICE_DIRECT, "") < 0) { + SDL_Log("error: can't add touch %s, %d", __FILE__, __LINE__); + } + + switch (action) { + case ACTION_DOWN: + case ACTION_POINTER_DOWN: + SDL_SendTouch(0, touchDeviceId, fingerId, window, SDL_EVENT_FINGER_DOWN, x, y, p); + break; + + case ACTION_MOVE: + SDL_SendTouchMotion(0, touchDeviceId, fingerId, window, x, y, p); + break; + + case ACTION_UP: + case ACTION_POINTER_UP: + SDL_SendTouch(0, touchDeviceId, fingerId, window, SDL_EVENT_FINGER_UP, x, y, p); + break; + + case ACTION_CANCEL: + SDL_SendTouch(0, touchDeviceId, fingerId, window, SDL_EVENT_FINGER_CANCELED, x, y, p); + break; + + default: + break; + } +} + +#endif // SDL_VIDEO_DRIVER_ANDROID diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidtouch.h b/contrib/SDL-3.2.8/src/video/android/SDL_androidtouch.h new file mode 100644 index 0000000..2aef822 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidtouch.h @@ -0,0 +1,27 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#include "SDL_androidvideo.h" + +extern void Android_InitTouch(void); +extern void Android_QuitTouch(void); +extern void Android_OnTouch(SDL_Window *window, int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p); diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidvideo.c b/contrib/SDL-3.2.8/src/video/android/SDL_androidvideo.c new file mode 100644 index 0000000..b154ff7 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidvideo.c @@ -0,0 +1,331 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_ANDROID + +// Android SDL video driver implementation + +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "../../events/SDL_windowevents_c.h" + +#include "SDL_androidvideo.h" +#include "SDL_androidgl.h" +#include "SDL_androidclipboard.h" +#include "SDL_androidevents.h" +#include "SDL_androidkeyboard.h" +#include "SDL_androidmouse.h" +#include "SDL_androidtouch.h" +#include "SDL_androidwindow.h" +#include "SDL_androidvulkan.h" +#include "SDL_androidmessagebox.h" + +#define ANDROID_VID_DRIVER_NAME "android" + +// Initialization/Query functions +static bool Android_VideoInit(SDL_VideoDevice *_this); +static void Android_VideoQuit(SDL_VideoDevice *_this); + +#include "../SDL_egl_c.h" +#define Android_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal +#define Android_GLES_UnloadLibrary SDL_EGL_UnloadLibrary +#define Android_GLES_SetSwapInterval SDL_EGL_SetSwapInterval +#define Android_GLES_GetSwapInterval SDL_EGL_GetSwapInterval +#define Android_GLES_DestroyContext SDL_EGL_DestroyContext + +// Android driver bootstrap functions + +// These are filled in with real values in Android_SetScreenResolution on init (before SDL_main()) +int Android_SurfaceWidth = 0; +int Android_SurfaceHeight = 0; +static int Android_DeviceWidth = 0; +static int Android_DeviceHeight = 0; +static Uint32 Android_ScreenFormat = SDL_PIXELFORMAT_RGB565; // Default SurfaceView format, in case this is queried before being filled +float Android_ScreenDensity = 1.0f; +static float Android_ScreenRate = 0.0f; +static SDL_DisplayOrientation Android_ScreenOrientation = SDL_ORIENTATION_UNKNOWN; +int Android_SafeInsetLeft = 0; +int Android_SafeInsetRight = 0; +int Android_SafeInsetTop = 0; +int Android_SafeInsetBottom = 0; +static SDL_SystemTheme Android_SystemTheme; + +static bool Android_SuspendScreenSaver(SDL_VideoDevice *_this) +{ + return Android_JNI_SuspendScreenSaver(_this->suspend_screensaver); +} + +static void Android_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->internal); + SDL_free(device); +} + +static SDL_VideoDevice *Android_CreateDevice(void) +{ + SDL_VideoDevice *device; + SDL_VideoData *data; + + // Initialize all variables that we clean on shutdown + device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); + if (!device) { + return NULL; + } + + data = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); + if (!data) { + SDL_free(device); + return NULL; + } + + device->internal = data; + device->system_theme = Android_SystemTheme; + + // Set the function pointers + device->VideoInit = Android_VideoInit; + device->VideoQuit = Android_VideoQuit; + + device->CreateSDLWindow = Android_CreateWindow; + device->SetWindowTitle = Android_SetWindowTitle; + device->SetWindowFullscreen = Android_SetWindowFullscreen; + device->MinimizeWindow = Android_MinimizeWindow; + device->SetWindowResizable = Android_SetWindowResizable; + device->DestroyWindow = Android_DestroyWindow; + + device->free = Android_DeleteDevice; + + // GL pointers +#ifdef SDL_VIDEO_OPENGL_EGL + device->GL_LoadLibrary = Android_GLES_LoadLibrary; + device->GL_GetProcAddress = Android_GLES_GetProcAddress; + device->GL_UnloadLibrary = Android_GLES_UnloadLibrary; + device->GL_CreateContext = Android_GLES_CreateContext; + device->GL_MakeCurrent = Android_GLES_MakeCurrent; + device->GL_SetSwapInterval = Android_GLES_SetSwapInterval; + device->GL_GetSwapInterval = Android_GLES_GetSwapInterval; + device->GL_SwapWindow = Android_GLES_SwapWindow; + device->GL_DestroyContext = Android_GLES_DestroyContext; +#endif + +#ifdef SDL_VIDEO_VULKAN + device->Vulkan_LoadLibrary = Android_Vulkan_LoadLibrary; + device->Vulkan_UnloadLibrary = Android_Vulkan_UnloadLibrary; + device->Vulkan_GetInstanceExtensions = Android_Vulkan_GetInstanceExtensions; + device->Vulkan_CreateSurface = Android_Vulkan_CreateSurface; + device->Vulkan_DestroySurface = Android_Vulkan_DestroySurface; +#endif + + // Screensaver + device->SuspendScreenSaver = Android_SuspendScreenSaver; + + // Screen keyboard + device->HasScreenKeyboardSupport = Android_HasScreenKeyboardSupport; + device->ShowScreenKeyboard = Android_ShowScreenKeyboard; + device->HideScreenKeyboard = Android_HideScreenKeyboard; + device->IsScreenKeyboardShown = Android_IsScreenKeyboardShown; + + // Clipboard + device->SetClipboardText = Android_SetClipboardText; + device->GetClipboardText = Android_GetClipboardText; + device->HasClipboardText = Android_HasClipboardText; + + device->device_caps = VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS; + + return device; +} + +VideoBootStrap Android_bootstrap = { + ANDROID_VID_DRIVER_NAME, "SDL Android video driver", + Android_CreateDevice, + Android_ShowMessageBox, + false +}; + +bool Android_VideoInit(SDL_VideoDevice *_this) +{ + SDL_VideoData *videodata = _this->internal; + SDL_DisplayID displayID; + SDL_VideoDisplay *display; + SDL_DisplayMode mode; + + videodata->isPaused = false; + videodata->isPausing = false; + + SDL_zero(mode); + mode.format = Android_ScreenFormat; + mode.w = Android_DeviceWidth; + mode.h = Android_DeviceHeight; + mode.refresh_rate = Android_ScreenRate; + + displayID = SDL_AddBasicVideoDisplay(&mode); + if (displayID == 0) { + return false; + } + display = SDL_GetVideoDisplay(displayID); + display->natural_orientation = Android_JNI_GetDisplayNaturalOrientation(); + display->current_orientation = Android_JNI_GetDisplayCurrentOrientation(); + display->content_scale = Android_ScreenDensity; + + Android_InitTouch(); + + Android_InitMouse(); + + // We're done! + return true; +} + +void Android_VideoQuit(SDL_VideoDevice *_this) +{ + Android_QuitMouse(); + Android_QuitTouch(); +} + +void Android_SetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, float density, float rate) +{ + Android_SurfaceWidth = surfaceWidth; + Android_SurfaceHeight = surfaceHeight; + Android_DeviceWidth = deviceWidth; + Android_DeviceHeight = deviceHeight; + Android_ScreenDensity = (density > 0.0f) ? density : 1.0f; + Android_ScreenRate = rate; +} + +static Uint32 format_to_pixelFormat(int format) +{ + Uint32 pf; + if (format == AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM) { // 1 + pf = SDL_PIXELFORMAT_RGBA8888; + } else if (format == AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM) { // 2 + pf = SDL_PIXELFORMAT_RGBX8888; + } else if (format == AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM) { // 3 + pf = SDL_PIXELFORMAT_RGB24; + } else if (format == AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM) { // 4 + pf = SDL_PIXELFORMAT_RGB565; + } else if (format == 5) { + pf = SDL_PIXELFORMAT_BGRA8888; + } else if (format == 6) { + pf = SDL_PIXELFORMAT_RGBA5551; + } else if (format == 7) { + pf = SDL_PIXELFORMAT_RGBA4444; + } else if (format == 0x115) { + // HAL_PIXEL_FORMAT_BGR_565 + pf = SDL_PIXELFORMAT_RGB565; + } else { + pf = SDL_PIXELFORMAT_UNKNOWN; + } + return pf; +} + +void Android_SetFormat(int format_wanted, int format_got) +{ + Uint32 pf_wanted; + Uint32 pf_got; + + pf_wanted = format_to_pixelFormat(format_wanted); + pf_got = format_to_pixelFormat(format_got); + + Android_ScreenFormat = pf_got; + + SDL_Log("pixel format wanted %s (%d), got %s (%d)", + SDL_GetPixelFormatName(pf_wanted), format_wanted, + SDL_GetPixelFormatName(pf_got), format_got); +} + +static void Android_SendOrientationUpdate(void) +{ + /* If we've received a compatible resize event, update the + * orientation immediately, otherwise wait for the display + * resize event. + */ + SDL_VideoDevice *device = SDL_GetVideoDevice(); + if (device && device->num_displays > 0) { + SDL_VideoDisplay *display = device->displays[0]; + bool mode_landscape = (display->desktop_mode.w > display->desktop_mode.h); + bool sensor_landscape = (Android_ScreenOrientation == SDL_ORIENTATION_LANDSCAPE || Android_ScreenOrientation == SDL_ORIENTATION_LANDSCAPE_FLIPPED); + if (sensor_landscape == mode_landscape) { + SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_ORIENTATION, Android_ScreenOrientation, 0); + } + } +} + +void Android_SetOrientation(SDL_DisplayOrientation orientation) +{ + Android_ScreenOrientation = orientation; + Android_SendOrientationUpdate(); +} + +void Android_SendResize(SDL_Window *window) +{ + /* + Update the resolution of the desktop mode, so that the window + can be properly resized. The screen resolution change can for + example happen when the Activity enters or exits immersive mode, + which can happen after VideoInit(). + */ + SDL_VideoDevice *device = SDL_GetVideoDevice(); + if (device && device->num_displays > 0) { + SDL_VideoDisplay *display = device->displays[0]; + SDL_DisplayMode desktop_mode; + + SDL_zero(desktop_mode); + desktop_mode.format = Android_ScreenFormat; + desktop_mode.w = Android_DeviceWidth; + desktop_mode.h = Android_DeviceHeight; + desktop_mode.refresh_rate = Android_ScreenRate; + SDL_SetDesktopDisplayMode(display, &desktop_mode); + Android_SendOrientationUpdate(); + } + + if (window) { + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, Android_SurfaceWidth, Android_SurfaceHeight); + } +} + +void Android_SetWindowSafeAreaInsets(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); + } +} + +void Android_SetDarkMode(bool enabled) +{ + SDL_VideoDevice *device = SDL_GetVideoDevice(); + + if (enabled) { + Android_SystemTheme = SDL_SYSTEM_THEME_DARK; + } else { + Android_SystemTheme = SDL_SYSTEM_THEME_LIGHT; + } + + if (device) { + SDL_SetSystemTheme(Android_SystemTheme); + } +} + +#endif // SDL_VIDEO_DRIVER_ANDROID diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidvideo.h b/contrib/SDL-3.2.8/src/video/android/SDL_androidvideo.h new file mode 100644 index 0000000..c561637 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidvideo.h @@ -0,0 +1,52 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifndef SDL_androidvideo_h_ +#define SDL_androidvideo_h_ + +#include "../SDL_sysvideo.h" + +// Called by the JNI layer when the screen changes size or format +extern void Android_SetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, float density, float rate); +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_SetDarkMode(bool enabled); + +// Private display data + +struct SDL_VideoData +{ + int isPaused; + int isPausing; +}; + +extern int Android_SurfaceWidth; +extern int Android_SurfaceHeight; +extern float Android_ScreenDensity; +extern int Android_SafeInsetLeft; +extern int Android_SafeInsetRight; +extern int Android_SafeInsetTop; +extern int Android_SafeInsetBottom; + +#endif // SDL_androidvideo_h_ diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidvulkan.c b/contrib/SDL-3.2.8/src/video/android/SDL_androidvulkan.c new file mode 100644 index 0000000..4d38388 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidvulkan.c @@ -0,0 +1,171 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* + * @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's + * SDL_x11vulkan.c. + */ + +#include "SDL_internal.h" + +#if defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_ANDROID) + +#include "../SDL_vulkan_internal.h" + +#include "SDL_androidvideo.h" +#include "SDL_androidwindow.h" + +#include "SDL_androidvulkan.h" + + +bool Android_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) +{ + VkExtensionProperties *extensions = NULL; + Uint32 i, extensionCount = 0; + bool hasSurfaceExtension = false; + bool hasAndroidSurfaceExtension = false; + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL; + if (_this->vulkan_config.loader_handle) { + return SDL_SetError("Vulkan already loaded"); + } + + // Load the Vulkan loader library + if (!path) { + path = SDL_GetHint(SDL_HINT_VULKAN_LIBRARY); + } + if (!path) { + path = "libvulkan.so"; + } + _this->vulkan_config.loader_handle = SDL_LoadObject(path); + if (!_this->vulkan_config.loader_handle) { + return false; + } + SDL_strlcpy(_this->vulkan_config.loader_path, path, + SDL_arraysize(_this->vulkan_config.loader_path)); + vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction( + _this->vulkan_config.loader_handle, "vkGetInstanceProcAddr"); + if (!vkGetInstanceProcAddr) { + goto fail; + } + _this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr; + _this->vulkan_config.vkEnumerateInstanceExtensionProperties = + (void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)( + VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties"); + if (!_this->vulkan_config.vkEnumerateInstanceExtensionProperties) { + goto fail; + } + extensions = SDL_Vulkan_CreateInstanceExtensionsList( + (PFN_vkEnumerateInstanceExtensionProperties) + _this->vulkan_config.vkEnumerateInstanceExtensionProperties, + &extensionCount); + if (!extensions) { + goto fail; + } + for (i = 0; i < extensionCount; i++) { + if (SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) { + hasSurfaceExtension = true; + } else if (SDL_strcmp(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) { + hasAndroidSurfaceExtension = true; + } + } + SDL_free(extensions); + if (!hasSurfaceExtension) { + SDL_SetError("Installed Vulkan doesn't implement the " VK_KHR_SURFACE_EXTENSION_NAME " extension"); + goto fail; + } else if (!hasAndroidSurfaceExtension) { + SDL_SetError("Installed Vulkan doesn't implement the " VK_KHR_ANDROID_SURFACE_EXTENSION_NAME "extension"); + goto fail; + } + return true; + +fail: + SDL_UnloadObject(_this->vulkan_config.loader_handle); + _this->vulkan_config.loader_handle = NULL; + return false; +} + +void Android_Vulkan_UnloadLibrary(SDL_VideoDevice *_this) +{ + if (_this->vulkan_config.loader_handle) { + SDL_UnloadObject(_this->vulkan_config.loader_handle); + _this->vulkan_config.loader_handle = NULL; + } +} + +char const* const* Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, + Uint32 *count) +{ + static const char *const extensionsForAndroid[] = { + VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME + }; + if (count) { + *count = SDL_arraysize(extensionsForAndroid); + } + return extensionsForAndroid; +} + +bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this, + SDL_Window *window, + VkInstance instance, + const struct VkAllocationCallbacks *allocator, + VkSurfaceKHR *surface) +{ + SDL_WindowData *windowData = window->internal; + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = + (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr; + PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR = + (PFN_vkCreateAndroidSurfaceKHR)vkGetInstanceProcAddr( + instance, + "vkCreateAndroidSurfaceKHR"); + VkAndroidSurfaceCreateInfoKHR createInfo; + VkResult result; + + if (!_this->vulkan_config.loader_handle) { + return SDL_SetError("Vulkan is not loaded"); + } + + if (!vkCreateAndroidSurfaceKHR) { + return SDL_SetError(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME + " extension is not enabled in the Vulkan instance."); + } + SDL_zero(createInfo); + createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; + createInfo.pNext = NULL; + createInfo.flags = 0; + createInfo.window = windowData->native_window; + result = vkCreateAndroidSurfaceKHR(instance, &createInfo, allocator, surface); + if (result != VK_SUCCESS) { + return SDL_SetError("vkCreateAndroidSurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result)); + } + return true; +} + +void Android_Vulkan_DestroySurface(SDL_VideoDevice *_this, + VkInstance instance, + VkSurfaceKHR surface, + const struct VkAllocationCallbacks *allocator) +{ + if (_this->vulkan_config.loader_handle) { + SDL_Vulkan_DestroySurface_Internal(_this->vulkan_config.vkGetInstanceProcAddr, instance, surface, allocator); + } +} + +#endif diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidvulkan.h b/contrib/SDL-3.2.8/src/video/android/SDL_androidvulkan.h new file mode 100644 index 0000000..4f7cd51 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidvulkan.h @@ -0,0 +1,52 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* + * @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's + * SDL_x11vulkan.h. + */ + +#include "SDL_internal.h" + +#ifndef SDL_androidvulkan_h_ +#define SDL_androidvulkan_h_ + +#include "../SDL_vulkan_internal.h" +#include "../SDL_sysvideo.h" + +#if defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_ANDROID) + +extern bool Android_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path); +extern void Android_Vulkan_UnloadLibrary(SDL_VideoDevice *_this); +extern char const* const* Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count); +extern bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this, + SDL_Window *window, + VkInstance instance, + const struct VkAllocationCallbacks *allocator, + VkSurfaceKHR *surface); +extern void Android_Vulkan_DestroySurface(SDL_VideoDevice *_this, + VkInstance instance, + VkSurfaceKHR surface, + const struct VkAllocationCallbacks *allocator); + +#endif + +#endif // SDL_androidvulkan_h_ diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidwindow.c b/contrib/SDL-3.2.8/src/video/android/SDL_androidwindow.c new file mode 100644 index 0000000..af840b2 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidwindow.c @@ -0,0 +1,204 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_ANDROID + +#include "../SDL_sysvideo.h" +#include "../../events/SDL_keyboard_c.h" +#include "../../events/SDL_mouse_c.h" +#include "../../events/SDL_windowevents_c.h" +#include "../../core/android/SDL_android.h" + +#include "SDL_androidvideo.h" +#include "SDL_androidevents.h" +#include "SDL_androidwindow.h" + + +// Currently only one window +SDL_Window *Android_Window = NULL; + +bool Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) +{ + SDL_WindowData *data; + bool result = true; + + if (!Android_WaitActiveAndLockActivity()) { + return false; + } + + if (Android_Window) { + result = SDL_SetError("Android only supports one window"); + goto endfunction; + } + + // Set orientation + Android_JNI_SetOrientation(window->w, window->h, window->flags & SDL_WINDOW_RESIZABLE, SDL_GetHint(SDL_HINT_ORIENTATIONS)); + + // Adjust the window data to match the screen + window->x = 0; + window->y = 0; + window->w = Android_SurfaceWidth; + window->h = Android_SurfaceHeight; + + // One window, it always has focus + SDL_SetMouseFocus(window); + SDL_SetKeyboardFocus(window); + + data = (SDL_WindowData *)SDL_calloc(1, sizeof(*data)); + if (!data) { + 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"); + 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; + +endfunction: + + Android_UnlockActivityMutex(); + + return result; +} + +void Android_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window) +{ + Android_JNI_SetActivityTitle(window->title); +} + +SDL_FullscreenResult Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_FullscreenOp fullscreen) +{ + Android_LockActivityMutex(); + + 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); + } + + /* 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 environemtns, 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; + } + + old_w = window->w; + old_h = window->h; + + 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); + } + } + +endfunction: + + Android_UnlockActivityMutex(); + + return SDL_FULLSCREEN_SUCCEEDED; +} + +void Android_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) +{ + Android_JNI_MinizeWindow(); +} + +void Android_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, bool resizable) +{ + // Set orientation + Android_JNI_SetOrientation(window->w, window->h, window->flags & SDL_WINDOW_RESIZABLE, SDL_GetHint(SDL_HINT_ORIENTATIONS)); +} + +void Android_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) +{ + Android_LockActivityMutex(); + + if (window == Android_Window) { + Android_Window = NULL; + + if (window->internal) { + SDL_WindowData *data = window->internal; + +#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; + } + } + + Android_UnlockActivityMutex(); +} + +#endif // SDL_VIDEO_DRIVER_ANDROID diff --git a/contrib/SDL-3.2.8/src/video/android/SDL_androidwindow.h b/contrib/SDL-3.2.8/src/video/android/SDL_androidwindow.h new file mode 100644 index 0000000..5590b59 --- /dev/null +++ b/contrib/SDL-3.2.8/src/video/android/SDL_androidwindow.h @@ -0,0 +1,51 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifndef SDL_androidwindow_h_ +#define SDL_androidwindow_h_ + +#include "../../core/android/SDL_android.h" +#include "../SDL_egl_c.h" + +extern bool Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); +extern void Android_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); +extern SDL_FullscreenResult Android_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_FullscreenOp fullscreen); +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 +{ +#ifdef SDL_VIDEO_OPENGL_EGL + EGLSurface egl_surface; + EGLContext egl_context; // We use this to preserve the context when losing focus + int has_swap_interval; // Save/Restore the swap interval / vsync + int swap_interval; +#endif + bool backup_done; + ANativeWindow *native_window; + +}; + +#endif // SDL_androidwindow_h_ -- cgit v1.2.3