فهرست منبع

Added support for inset handling on Android 15

Sam Lantinga 6 ماه پیش
والد
کامیت
e91c37f4dd

+ 2 - 2
android-project/app/build.gradle

@@ -6,10 +6,10 @@ def buildWithCMake = project.hasProperty('BUILD_WITH_CMAKE');
 
 
 android {
 android {
     namespace "org.libsdl.app"
     namespace "org.libsdl.app"
-    compileSdkVersion 34
+    compileSdkVersion 35
     defaultConfig {
     defaultConfig {
         minSdkVersion 19
         minSdkVersion 19
-        targetSdkVersion 34
+        targetSdkVersion 35
         versionCode 1
         versionCode 1
         versionName "1.0"
         versionName "1.0"
         externalNativeBuild {
         externalNativeBuild {

+ 4 - 0
android-project/app/src/main/java/org/libsdl/app/SDLActivity.java

@@ -928,6 +928,10 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
                             if (Build.VERSION.SDK_INT >= 28 /* Android 9 (Pie) */) {
                             if (Build.VERSION.SDK_INT >= 28 /* Android 9 (Pie) */) {
                                 window.getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
                                 window.getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
                             }
                             }
+                            if (Build.VERSION.SDK_INT >= 30 /* Android 11 (R) */ &&
+                                Build.VERSION.SDK_INT < 35 /* Android 15 */) {
+                                SDLActivity.onNativeInsetsChanged(0, 0, 0, 0);
+                            }
                         }
                         }
                     } else {
                     } else {
                         Log.e(TAG, "error handling message, getContext() returned no Activity");
                         Log.e(TAG, "error handling message, getContext() returned no Activity");

+ 18 - 17
docs/README-android.md

@@ -10,7 +10,7 @@ The rest of this README covers the Android gradle style build process.
 Requirements
 Requirements
 ================================================================================
 ================================================================================
 
 
-Android SDK (version 34 or later)
+Android SDK (version 35 or later)
 https://developer.android.com/sdk/index.html
 https://developer.android.com/sdk/index.html
 
 
 Android NDK r15c or later
 Android NDK r15c or later
@@ -316,6 +316,17 @@ You can control activity re-creation (eg. onCreate()) behaviour. This allows you
 to choose whether to keep or re-initialize java and native static datas, see
 to choose whether to keep or re-initialize java and native static datas, see
 SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY in SDL_hints.h.
 SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY in SDL_hints.h.
 
 
+
+Insets and Safe Areas
+================================================================================
+
+As of Android 15, SDL windows cover the entire screen, extending under notches
+and system bars. The OS expects you to take those into account when displaying
+content and SDL provides the function SDL_GetWindowSafeArea() so you know what
+area is available for interaction. Outside of the safe area can be potentially
+covered by system bars or used by OS gestures.
+
+
 Mouse / Touch events
 Mouse / Touch events
 ================================================================================
 ================================================================================
 
 
@@ -325,6 +336,7 @@ To enable/disable this behavior, see SDL_hints.h:
 - SDL_HINT_TOUCH_MOUSE_EVENTS
 - SDL_HINT_TOUCH_MOUSE_EVENTS
 - SDL_HINT_MOUSE_TOUCH_EVENTS
 - SDL_HINT_MOUSE_TOUCH_EVENTS
 
 
+
 Misc
 Misc
 ================================================================================
 ================================================================================
 
 
@@ -334,6 +346,7 @@ before creating a window:
   SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
   SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
   SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
   SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
 
 
+
 Threads and the Java VM
 Threads and the Java VM
 ================================================================================
 ================================================================================
 
 
@@ -359,6 +372,7 @@ in your native thread.
 see:
 see:
 https://developer.android.com/training/articles/perf-jni#faq:-why-didnt-findclass-find-my-class
 https://developer.android.com/training/articles/perf-jni#faq:-why-didnt-findclass-find-my-class
 
 
+
 Using STL
 Using STL
 ================================================================================
 ================================================================================
 
 
@@ -526,15 +540,6 @@ The Tegra Graphics Debugger is available from NVidia here:
 https://developer.nvidia.com/tegra-graphics-debugger
 https://developer.nvidia.com/tegra-graphics-debugger
 
 
 
 
-Why is API level 19 the minimum required?
-================================================================================
-
-The latest NDK toolchain doesn't support targeting earlier than API level 19.
-As of this writing, according to https://www.composables.com/tools/distribution-chart
-about 99.7% of the Android devices accessing Google Play support API level 19 or
-higher (August 2023).
-
-
 A note regarding the use of the "dirty rectangles" rendering technique
 A note regarding the use of the "dirty rectangles" rendering technique
 ================================================================================
 ================================================================================
 
 
@@ -545,12 +550,6 @@ This is caused by SDL's use of EGL as the support system to handle OpenGL ES/ES2
 contexts, in particular the use of the eglSwapBuffers function. As stated in the
 contexts, in particular the use of the eglSwapBuffers function. As stated in the
 documentation for the function "The contents of ancillary buffers are always
 documentation for the function "The contents of ancillary buffers are always
 undefined after calling eglSwapBuffers".
 undefined after calling eglSwapBuffers".
-Setting the EGL_SWAP_BEHAVIOR attribute of the surface to EGL_BUFFER_PRESERVED
-is not possible for SDL as it requires EGL 1.4, available only on the API level
-17+, so the only workaround available on this platform is to redraw the entire
-screen each frame.
-
-Reference: http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html
 
 
 
 
 Ending your application
 Ending your application
@@ -570,12 +569,14 @@ Don't call exit() as it stops the activity badly.
 NB: "Back button" can be handled as a SDL_EVENT_KEY_DOWN/UP events, with Keycode
 NB: "Back button" can be handled as a SDL_EVENT_KEY_DOWN/UP events, with Keycode
 SDLK_AC_BACK, for any purpose.
 SDLK_AC_BACK, for any purpose.
 
 
+
 Known issues
 Known issues
 ================================================================================
 ================================================================================
 
 
 - The number of buttons reported for each joystick is hardcoded to be 36, which
 - The number of buttons reported for each joystick is hardcoded to be 36, which
 is the current maximum number of buttons Android can report.
 is the current maximum number of buttons Android can report.
 
 
+
 Building the SDL tests
 Building the SDL tests
 ================================================================================
 ================================================================================
 
 
@@ -651,4 +652,4 @@ There is also a convenience target which will build, install and start a test:
 cmake --build . --target build-install-start-testsprite
 cmake --build . --target build-install-start-testsprite
 ```
 ```
 
 
-Not all tests provide a GUI. For those, you can use `adb logcat` to read the output of stdout.
+Not all tests provide a GUI. For those, you can use `adb logcat` to read the output.

+ 1 - 3
src/core/android/SDL_android.c

@@ -1077,9 +1077,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeInsetsChanged)(
 {
 {
     SDL_LockMutex(Android_ActivityMutex);
     SDL_LockMutex(Android_ActivityMutex);
 
 
-    if (Android_Window) {
-        SDL_SetWindowSafeAreaInsets(Android_Window, left, right, top, bottom);
-    }
+    Android_SetWindowSafeAreaInsets(left, right, top, bottom);
 
 
     SDL_UnlockMutex(Android_ActivityMutex);
     SDL_UnlockMutex(Android_ActivityMutex);
 }
 }

+ 16 - 0
src/video/android/SDL_androidvideo.c

@@ -63,6 +63,10 @@ static int Android_DeviceHeight = 0;
 static Uint32 Android_ScreenFormat = SDL_PIXELFORMAT_RGB565; // Default SurfaceView format, in case this is queried before being filled
 static Uint32 Android_ScreenFormat = SDL_PIXELFORMAT_RGB565; // Default SurfaceView format, in case this is queried before being filled
 float Android_ScreenDensity = 1.0f;
 float Android_ScreenDensity = 1.0f;
 static float Android_ScreenRate = 0.0f;
 static float Android_ScreenRate = 0.0f;
+int Android_SafeInsetLeft = 0;
+int Android_SafeInsetRight = 0;
+int Android_SafeInsetTop = 0;
+int Android_SafeInsetBottom = 0;
 static SDL_SystemTheme Android_SystemTheme;
 static SDL_SystemTheme Android_SystemTheme;
 
 
 static bool Android_SuspendScreenSaver(SDL_VideoDevice *_this)
 static bool Android_SuspendScreenSaver(SDL_VideoDevice *_this)
@@ -271,6 +275,18 @@ void Android_SendResize(SDL_Window *window)
     }
     }
 }
 }
 
 
+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)
 void Android_SetDarkMode(bool enabled)
 {
 {
     SDL_VideoDevice *device = SDL_GetVideoDevice();
     SDL_VideoDevice *device = SDL_GetVideoDevice();

+ 5 - 0
src/video/android/SDL_androidvideo.h

@@ -29,6 +29,7 @@
 extern void Android_SetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, float density, float rate);
 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_SetFormat(int format_wanted, int format_got);
 extern void Android_SendResize(SDL_Window *window);
 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);
 extern void Android_SetDarkMode(bool enabled);
 
 
 // Private display data
 // Private display data
@@ -42,5 +43,9 @@ struct SDL_VideoData
 extern int Android_SurfaceWidth;
 extern int Android_SurfaceWidth;
 extern int Android_SurfaceHeight;
 extern int Android_SurfaceHeight;
 extern float Android_ScreenDensity;
 extern float Android_ScreenDensity;
+extern int Android_SafeInsetLeft;
+extern int Android_SafeInsetRight;
+extern int Android_SafeInsetTop;
+extern int Android_SafeInsetBottom;
 
 
 #endif // SDL_androidvideo_h_
 #endif // SDL_androidvideo_h_

+ 2 - 0
src/video/android/SDL_androidwindow.c

@@ -93,6 +93,8 @@ bool Android_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Proper
     SDL_SetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_ANDROID_SURFACE_POINTER, data->egl_surface);
     SDL_SetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_ANDROID_SURFACE_POINTER, data->egl_surface);
 #endif
 #endif
 
 
+    SDL_SetWindowSafeAreaInsets(window, Android_SafeInsetLeft, Android_SafeInsetRight, Android_SafeInsetTop, Android_SafeInsetBottom);
+
     window->internal = data;
     window->internal = data;
     Android_Window = window;
     Android_Window = window;