SDL: Implemented querying the orientation of displays on Windows

From c0f1109bd0c8041ae71d601ebd43edaea8c576f1 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 10 Nov 2021 06:03:01 -0800
Subject: [PATCH] Implemented querying the orientation of displays on Windows

---
 src/video/windows/SDL_windowsmodes.c | 55 ++++++++++++++++++++++++++--
 1 file changed, 52 insertions(+), 3 deletions(-)

diff --git a/src/video/windows/SDL_windowsmodes.c b/src/video/windows/SDL_windowsmodes.c
index e8b1fc151c..3abb5d42c0 100644
--- a/src/video/windows/SDL_windowsmodes.c
+++ b/src/video/windows/SDL_windowsmodes.c
@@ -108,8 +108,50 @@ WIN_UpdateDisplayMode(_THIS, LPCWSTR deviceName, DWORD index, SDL_DisplayMode *
     }
 }
 
+static SDL_DisplayOrientation
+WIN_GetDisplayOrientation(DEVMODE *mode)
+{
+    int width = mode->dmPelsWidth;
+    int height = mode->dmPelsHeight;
+
+    /* Use unrotated width/height to guess orientation */
+    if (mode->dmDisplayOrientation == DMDO_90 || mode->dmDisplayOrientation == DMDO_270) {
+        int temp = width;
+        width = height;
+        height = temp;
+    }
+
+    if (width >= height) {
+        switch (mode->dmDisplayOrientation) {
+        case DMDO_DEFAULT:
+            return SDL_ORIENTATION_LANDSCAPE;
+        case DMDO_90:
+            return SDL_ORIENTATION_PORTRAIT;
+        case DMDO_180:
+            return SDL_ORIENTATION_LANDSCAPE_FLIPPED;
+        case DMDO_270:
+            return SDL_ORIENTATION_PORTRAIT_FLIPPED;
+        default:
+            return SDL_ORIENTATION_UNKNOWN;
+        }
+    } else {
+        switch (mode->dmDisplayOrientation) {
+        case DMDO_DEFAULT:
+            return SDL_ORIENTATION_PORTRAIT;
+        case DMDO_90:
+            return SDL_ORIENTATION_LANDSCAPE_FLIPPED;
+        case DMDO_180:
+            return SDL_ORIENTATION_PORTRAIT_FLIPPED;
+        case DMDO_270:
+            return SDL_ORIENTATION_LANDSCAPE;
+        default:
+            return SDL_ORIENTATION_UNKNOWN;
+        }
+    }
+}
+
 static SDL_bool
-WIN_GetDisplayMode(_THIS, LPCWSTR deviceName, DWORD index, SDL_DisplayMode * mode)
+WIN_GetDisplayMode(_THIS, LPCWSTR deviceName, DWORD index, SDL_DisplayMode * mode, SDL_DisplayOrientation *orientation)
 {
     SDL_DisplayModeData *data;
     DEVMODE devmode;
@@ -135,6 +177,11 @@ WIN_GetDisplayMode(_THIS, LPCWSTR deviceName, DWORD index, SDL_DisplayMode * mod
 
     /* Fill in the mode information */
     WIN_UpdateDisplayMode(_this, deviceName, index, mode);
+
+    if (orientation) {
+        *orientation = WIN_GetDisplayOrientation(&devmode);
+    }
+
     return SDL_TRUE;
 }
 
@@ -145,13 +192,14 @@ WIN_AddDisplay(_THIS, HMONITOR hMonitor, const MONITORINFOEXW *info, SDL_bool se
     SDL_VideoDisplay display;
     SDL_DisplayData *displaydata;
     SDL_DisplayMode mode;
+    SDL_DisplayOrientation orientation;
     DISPLAY_DEVICEW device;
 
 #ifdef DEBUG_MODES
     SDL_Log("Display: %s\n", WIN_StringToUTF8W(info->szDevice));
 #endif
 
-    if (!WIN_GetDisplayMode(_this, info->szDevice, ENUM_CURRENT_SETTINGS, &mode)) {
+    if (!WIN_GetDisplayMode(_this, info->szDevice, ENUM_CURRENT_SETTINGS, &mode, &orientation)) {
         return SDL_FALSE;
     }
 
@@ -183,6 +231,7 @@ WIN_AddDisplay(_THIS, HMONITOR hMonitor, const MONITORINFOEXW *info, SDL_bool se
     }
     display.desktop_mode = mode;
     display.current_mode = mode;
+    display.orientation = orientation;
     display.driverdata = displaydata;
     SDL_AddVideoDisplay(&display, send_event);
     SDL_free(display.name);
@@ -357,7 +406,7 @@ WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
     SDL_DisplayMode mode;
 
     for (i = 0;; ++i) {
-        if (!WIN_GetDisplayMode(_this, data->DeviceName, i, &mode)) {
+        if (!WIN_GetDisplayMode(_this, data->DeviceName, i, &mode, NULL)) {
             break;
         }
         if (SDL_ISPIXELFORMAT_INDEXED(mode.format)) {