diff --git a/src/core/windows/SDL_windows.c b/src/core/windows/SDL_windows.c index 7c433b252c..4621531ca5 100644 --- a/src/core/windows/SDL_windows.c +++ b/src/core/windows/SDL_windows.c @@ -284,6 +284,31 @@ static BOOL IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WO return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE; } + +static DWORD WIN_BuildNumber = 0; +static BOOL IsWindowsBuildVersionAtLeast(DWORD dwBuildNumber) +{ + if (WIN_BuildNumber != 0) { + return (WIN_BuildNumber >= dwBuildNumber); + } + + HMODULE ntdll = LoadLibrary(TEXT("ntdll.dll")); + if (!ntdll) { + return false; + } + // There is no function to get Windows build number, so let's get it here via RtlGetVersion + RtlGetVersion_t RtlGetVersionFunc = (RtlGetVersion_t)GetProcAddress(ntdll, "RtlGetVersion"); + NT_OSVERSIONINFOW os_info; + os_info.dwOSVersionInfoSize = sizeof(NT_OSVERSIONINFOW); + os_info.dwBuildNumber = 0; + if (RtlGetVersionFunc) { + RtlGetVersionFunc(&os_info); + } + FreeLibrary(ntdll); + + WIN_BuildNumber = (os_info.dwBuildNumber & ~0xF0000000); + return (WIN_BuildNumber >= dwBuildNumber); +} #endif // apply some static variables so we only call into the Win32 API once per process for each check. @@ -324,6 +349,11 @@ BOOL WIN_IsWindows8OrGreater(void) CHECKWINVER(TRUE, IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0)); } +BOOL WIN_IsWindows11OrGreater(void) +{ + return IsWindowsBuildVersionAtLeast(22000); +} + #undef CHECKWINVER @@ -441,21 +471,7 @@ bool WIN_WindowRectValid(const RECT *rect) void WIN_UpdateDarkModeForHWND(HWND hwnd) { #if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) - HMODULE ntdll = LoadLibrary(TEXT("ntdll.dll")); - if (!ntdll) { - return; - } - // There is no function to get Windows build number, so let's get it here via RtlGetVersion - RtlGetVersion_t RtlGetVersionFunc = (RtlGetVersion_t)GetProcAddress(ntdll, "RtlGetVersion"); - NT_OSVERSIONINFOW os_info; - os_info.dwOSVersionInfoSize = sizeof(NT_OSVERSIONINFOW); - os_info.dwBuildNumber = 0; - if (RtlGetVersionFunc) { - RtlGetVersionFunc(&os_info); - } - FreeLibrary(ntdll); - os_info.dwBuildNumber &= ~0xF0000000; - if (os_info.dwBuildNumber < 17763) { + if (!IsWindowsBuildVersionAtLeast(17763)) { // Too old to support dark mode return; } @@ -466,7 +482,7 @@ void WIN_UpdateDarkModeForHWND(HWND hwnd) RefreshImmersiveColorPolicyState_t RefreshImmersiveColorPolicyStateFunc = (RefreshImmersiveColorPolicyState_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(104)); ShouldAppsUseDarkMode_t ShouldAppsUseDarkModeFunc = (ShouldAppsUseDarkMode_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(132)); AllowDarkModeForWindow_t AllowDarkModeForWindowFunc = (AllowDarkModeForWindow_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(133)); - if (os_info.dwBuildNumber < 18362) { + if (!IsWindowsBuildVersionAtLeast(18362)) { AllowDarkModeForApp_t AllowDarkModeForAppFunc = (AllowDarkModeForApp_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(135)); if (AllowDarkModeForAppFunc) { AllowDarkModeForAppFunc(true); @@ -491,7 +507,7 @@ void WIN_UpdateDarkModeForHWND(HWND hwnd) value = (SDL_GetSystemTheme() == SDL_SYSTEM_THEME_DARK) ? TRUE : FALSE; } FreeLibrary(uxtheme); - if (os_info.dwBuildNumber < 18362) { + if (!IsWindowsBuildVersionAtLeast(18362)) { SetProp(hwnd, TEXT("UseImmersiveDarkModeColors"), SDL_reinterpret_cast(HANDLE, SDL_static_cast(INT_PTR, value))); } else { HMODULE user32 = GetModuleHandle(TEXT("user32.dll")); diff --git a/src/core/windows/SDL_windows.h b/src/core/windows/SDL_windows.h index 80eb0997e5..f26b653b92 100644 --- a/src/core/windows/SDL_windows.h +++ b/src/core/windows/SDL_windows.h @@ -180,6 +180,9 @@ extern BOOL WIN_IsWindows7OrGreater(void); // Returns true if we're running on Windows 8 and newer extern BOOL WIN_IsWindows8OrGreater(void); +// Returns true if we're running on Windows 11 and newer +extern BOOL WIN_IsWindows11OrGreater(void); + // You need to SDL_free() the result of this call. extern char *WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid);