SDL: Wait for a display resize event before sending orientation changes

From 8704ab84228aca126c906ea42c2dbf4a240909bc Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 30 Dec 2024 15:49:10 -0800
Subject: [PATCH] Wait for a display resize event before sending orientation
 changes

Fixes https://github.com/libsdl-org/SDL/issues/9585
---
 src/core/android/SDL_android.c       |  5 +----
 src/video/android/SDL_androidvideo.c | 25 +++++++++++++++++++++++++
 src/video/android/SDL_androidvideo.h |  1 +
 3 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c
index 419d4c29f146d..c2f94dbd804b0 100644
--- a/src/core/android/SDL_android.c
+++ b/src/core/android/SDL_android.c
@@ -1063,10 +1063,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeRotationChanged)(
         break;
     }
 
-    if (Android_Window) {
-        SDL_VideoDisplay *display = SDL_GetVideoDisplay(SDL_GetPrimaryDisplay());
-        SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_ORIENTATION, displayCurrentOrientation, 0);
-    }
+    Android_SetOrientation(displayCurrentOrientation);
 
     SDL_UnlockMutex(Android_ActivityMutex);
 }
diff --git a/src/video/android/SDL_androidvideo.c b/src/video/android/SDL_androidvideo.c
index ab360a11c44aa..e2e5f3e9255c4 100644
--- a/src/video/android/SDL_androidvideo.c
+++ b/src/video/android/SDL_androidvideo.c
@@ -63,6 +63,7 @@ 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;
@@ -249,6 +250,29 @@ void Android_SetFormat(int format_wanted, int format_got)
             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)
 {
     /*
@@ -268,6 +292,7 @@ void Android_SendResize(SDL_Window *window)
         desktop_mode.h = Android_DeviceHeight;
         desktop_mode.refresh_rate = Android_ScreenRate;
         SDL_SetDesktopDisplayMode(display, &desktop_mode);
+        Android_SendOrientationUpdate();
     }
 
     if (window) {
diff --git a/src/video/android/SDL_androidvideo.h b/src/video/android/SDL_androidvideo.h
index bcc234f5d0af8..cd67890c92e22 100644
--- a/src/video/android/SDL_androidvideo.h
+++ b/src/video/android/SDL_androidvideo.h
@@ -28,6 +28,7 @@
 // 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);