From da6e9bbf7cc982d52dadefbc95316126ddad02d9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 27 Aug 2025 07:34:18 -0700 Subject: [PATCH] Allow building the tray subsystem without the video subsystem Fixes https://github.com/libsdl-org/SDL/issues/13235 --- CMakeLists.txt | 14 +- VisualC-GDK/SDL/SDL.vcxproj | 1 - VisualC-GDK/SDL/SDL.vcxproj.filters | 1 - VisualC/SDL/SDL.vcxproj | 3 +- VisualC/SDL/SDL.vcxproj.filters | 5 +- include/build_config/SDL_build_config.h.cmake | 3 + .../build_config/SDL_build_config_android.h | 3 + include/build_config/SDL_build_config_ios.h | 3 + .../build_config/SDL_build_config_minimal.h | 3 + include/build_config/SDL_build_config_xbox.h | 3 + src/core/windows/SDL_windows.c | 182 ++++++++++++++++++ src/core/windows/SDL_windows.h | 6 +- src/tray/dummy/SDL_tray.c | 4 +- src/tray/windows/SDL_tray.c | 9 +- src/video/windows/SDL_surface_utils.c | 97 ---------- src/video/windows/SDL_surface_utils.h | 38 ---- src/video/windows/SDL_windowswindow.c | 106 ---------- src/video/windows/SDL_windowswindow.h | 1 - 18 files changed, 219 insertions(+), 263 deletions(-) delete mode 100644 src/video/windows/SDL_surface_utils.c delete mode 100644 src/video/windows/SDL_surface_utils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c67d875ab2..f2af75dd85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -253,6 +253,7 @@ define_sdl_subsystem(Hidapi) define_sdl_subsystem(Power) define_sdl_subsystem(Sensor) define_sdl_subsystem(Dialog) +define_sdl_subsystem(Tray) cmake_dependent_option(SDL_FRAMEWORK "Build SDL libraries as Apple Framework" OFF "APPLE" OFF) if(SDL_FRAMEWORK) @@ -410,6 +411,7 @@ if (NGAGE) set(SDL_DUMMYVIDEO OFF) set(SDL_OFFSCREEN OFF) set(SDL_RENDER_GPU OFF) + set(SDL_TRAY OFF) set(SDL_VIRTUAL_JOYSTICK OFF) endif() @@ -1752,7 +1754,9 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) CheckVivante() CheckVulkan() CheckQNXScreen() + endif() + if(SDL_TRAY) sdl_glob_sources( "${SDL3_SOURCE_DIR}/src/tray/unix/*.c" "${SDL3_SOURCE_DIR}/src/tray/unix/*.h" @@ -2330,7 +2334,9 @@ elseif(WINDOWS) set(HAVE_RENDER_VULKAN TRUE) endif() endif() + endif() + if(SDL_TRAY) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/tray/windows/*.c") set(HAVE_SDL_TRAY TRUE) endif() @@ -2646,11 +2652,11 @@ elseif(APPLE) endif() endif() endif() + endif() - if(MACOS) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/tray/cocoa/*.m") - set(HAVE_SDL_TRAY TRUE) - endif() + if(SDL_TRAY AND MACOS) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/tray/cocoa/*.m") + set(HAVE_SDL_TRAY TRUE) endif() # Minimum version for $ diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index a9024fc683..f4ba231954 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -889,7 +889,6 @@ - diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index 9a0ce21537..446b9b6afa 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -191,7 +191,6 @@ - diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index f59c31f9e2..3832fc36a8 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -744,7 +744,6 @@ - @@ -775,4 +774,4 @@ - \ No newline at end of file + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index 4a1b31c884..819b4277d8 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -1356,9 +1356,6 @@ video\dummy - - video\windows - video\windows @@ -1618,4 +1615,4 @@ - \ No newline at end of file + diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index cc491526e5..c274257160 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -540,6 +540,9 @@ /* Enable dialog subsystem */ #cmakedefine SDL_DIALOG_DUMMY 1 +/* Enable tray subsystem */ +#cmakedefine SDL_TRAY_DUMMY 1 + /* Enable assembly routines */ #cmakedefine SDL_ALTIVEC_BLITTERS 1 diff --git a/include/build_config/SDL_build_config_android.h b/include/build_config/SDL_build_config_android.h index a0727f50cd..2ebb459115 100644 --- a/include/build_config/SDL_build_config_android.h +++ b/include/build_config/SDL_build_config_android.h @@ -208,6 +208,9 @@ #define SDL_CAMERA_DRIVER_ANDROID 1 #endif /* SDL_CAMERA_DISABLED */ +/* Enable tray subsystem */ +#define SDL_TRAY_DUMMY 1 + /* Enable nl_langinfo and high-res file times on version 26 and higher. */ #if __ANDROID_API__ >= 26 #define HAVE_NL_LANGINFO 1 diff --git a/include/build_config/SDL_build_config_ios.h b/include/build_config/SDL_build_config_ios.h index be1ec29a18..f278556a5f 100644 --- a/include/build_config/SDL_build_config_ios.h +++ b/include/build_config/SDL_build_config_ios.h @@ -223,4 +223,7 @@ /* Enable dialog subsystem */ #define SDL_DIALOG_DUMMY 1 +/* Enable tray subsystem */ +#define SDL_TRAY_DUMMY 1 + #endif /* SDL_build_config_ios_h_ */ diff --git a/include/build_config/SDL_build_config_minimal.h b/include/build_config/SDL_build_config_minimal.h index d5fe736e9d..e20d9c2ef1 100644 --- a/include/build_config/SDL_build_config_minimal.h +++ b/include/build_config/SDL_build_config_minimal.h @@ -98,4 +98,7 @@ typedef unsigned int uintptr_t; /* Enable dialog subsystem */ #define SDL_DIALOG_DUMMY 1 +/* Enable tray subsystem */ +#define SDL_TRAY_DUMMY 1 + #endif /* SDL_build_config_minimal_h_ */ diff --git a/include/build_config/SDL_build_config_xbox.h b/include/build_config/SDL_build_config_xbox.h index 5a4fde297f..70e9047acf 100644 --- a/include/build_config/SDL_build_config_xbox.h +++ b/include/build_config/SDL_build_config_xbox.h @@ -220,4 +220,7 @@ /* Enable dialog subsystem */ #define SDL_DIALOG_DUMMY 1 +/* Enable tray subsystem */ +#define SDL_TRAY_DUMMY 1 + #endif /* SDL_build_config_wingdk_h_ */ diff --git a/src/core/windows/SDL_windows.c b/src/core/windows/SDL_windows.c index cc8c8327ce..b402a94c1f 100644 --- a/src/core/windows/SDL_windows.c +++ b/src/core/windows/SDL_windows.c @@ -24,6 +24,8 @@ #include "SDL_windows.h" +#include "../../video/SDL_surface_c.h" + #include // for CoInitialize/CoUninitialize (Win32 only) #ifdef HAVE_ROAPI_H #include // For RoInitialize/RoUninitialize (Win32 only) @@ -53,6 +55,44 @@ typedef enum RO_INIT_TYPE #define WC_ERR_INVALID_CHARS 0x00000080 #endif +// Dark mode support +typedef enum { + UXTHEME_APPMODE_DEFAULT, + UXTHEME_APPMODE_ALLOW_DARK, + UXTHEME_APPMODE_FORCE_DARK, + UXTHEME_APPMODE_FORCE_LIGHT, + UXTHEME_APPMODE_MAX +} UxthemePreferredAppMode; + +typedef enum { + WCA_UNDEFINED = 0, + WCA_USEDARKMODECOLORS = 26, + WCA_LAST = 27 +} WINDOWCOMPOSITIONATTRIB; + +typedef struct { + WINDOWCOMPOSITIONATTRIB Attrib; + PVOID pvData; + SIZE_T cbData; +} WINDOWCOMPOSITIONATTRIBDATA; + +typedef struct { + ULONG dwOSVersionInfoSize; + ULONG dwMajorVersion; + ULONG dwMinorVersion; + ULONG dwBuildNumber; + ULONG dwPlatformId; + WCHAR szCSDVersion[128]; +} NT_OSVERSIONINFOW; + +typedef bool (WINAPI *ShouldAppsUseDarkMode_t)(void); +typedef void (WINAPI *AllowDarkModeForWindow_t)(HWND, bool); +typedef void (WINAPI *AllowDarkModeForApp_t)(bool); +typedef void (WINAPI *RefreshImmersiveColorPolicyState_t)(void); +typedef UxthemePreferredAppMode (WINAPI *SetPreferredAppMode_t)(UxthemePreferredAppMode); +typedef BOOL (WINAPI *SetWindowCompositionAttribute_t)(HWND, const WINDOWCOMPOSITIONATTRIBDATA *); +typedef void (NTAPI *RtlGetVersion_t)(NT_OSVERSIONINFOW *); + // Fake window to help with DirectInput events. HWND SDL_HelperWindow = NULL; static const TCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher"); @@ -408,6 +448,148 @@ bool WIN_WindowRectValid(const RECT *rect) return (rect->right > 0); } +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) { + // Too old to support dark mode + return; + } + HMODULE uxtheme = LoadLibrary(TEXT("uxtheme.dll")); + if (!uxtheme) { + return; + } + 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) { + AllowDarkModeForApp_t AllowDarkModeForAppFunc = (AllowDarkModeForApp_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(135)); + if (AllowDarkModeForAppFunc) { + AllowDarkModeForAppFunc(true); + } + } else { + SetPreferredAppMode_t SetPreferredAppModeFunc = (SetPreferredAppMode_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(135)); + if (SetPreferredAppModeFunc) { + SetPreferredAppModeFunc(UXTHEME_APPMODE_ALLOW_DARK); + } + } + if (RefreshImmersiveColorPolicyStateFunc) { + RefreshImmersiveColorPolicyStateFunc(); + } + if (AllowDarkModeForWindowFunc) { + AllowDarkModeForWindowFunc(hwnd, true); + } + BOOL value; + // Check dark mode using ShouldAppsUseDarkMode, but use SDL_GetSystemTheme as a fallback + if (ShouldAppsUseDarkModeFunc) { + value = ShouldAppsUseDarkModeFunc() ? TRUE : FALSE; + } else { + value = (SDL_GetSystemTheme() == SDL_SYSTEM_THEME_DARK) ? TRUE : FALSE; + } + FreeLibrary(uxtheme); + if (os_info.dwBuildNumber < 18362) { + SetProp(hwnd, TEXT("UseImmersiveDarkModeColors"), SDL_reinterpret_cast(HANDLE, SDL_static_cast(INT_PTR, value))); + } else { + HMODULE user32 = GetModuleHandle(TEXT("user32.dll")); + if (user32) { + SetWindowCompositionAttribute_t SetWindowCompositionAttributeFunc = (SetWindowCompositionAttribute_t)GetProcAddress(user32, "SetWindowCompositionAttribute"); + if (SetWindowCompositionAttributeFunc) { + WINDOWCOMPOSITIONATTRIBDATA data = { WCA_USEDARKMODECOLORS, &value, sizeof(value) }; + SetWindowCompositionAttributeFunc(hwnd, &data); + } + } + } +#endif +} + +HICON WIN_CreateIconFromSurface(SDL_Surface *surface) +{ +#if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)) + SDL_Surface *s = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ARGB8888); + if (!s) { + return NULL; + } + + /* The dimensions will be needed after s is freed */ + const int width = s->w; + const int height = s->h; + + BITMAPINFO bmpInfo; + SDL_zero(bmpInfo); + bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmpInfo.bmiHeader.biWidth = width; + bmpInfo.bmiHeader.biHeight = -height; /* Top-down bitmap */ + bmpInfo.bmiHeader.biPlanes = 1; + bmpInfo.bmiHeader.biBitCount = 32; + bmpInfo.bmiHeader.biCompression = BI_RGB; + + HDC hdc = GetDC(NULL); + void *pBits = NULL; + HBITMAP hBitmap = CreateDIBSection(hdc, &bmpInfo, DIB_RGB_COLORS, &pBits, NULL, 0); + if (!hBitmap) { + ReleaseDC(NULL, hdc); + SDL_DestroySurface(s); + return NULL; + } + + SDL_memcpy(pBits, s->pixels, width * height * 4); + + SDL_DestroySurface(s); + + HBITMAP hMask = CreateBitmap(width, height, 1, 1, NULL); + if (!hMask) { + DeleteObject(hBitmap); + ReleaseDC(NULL, hdc); + return NULL; + } + + HDC hdcMem = CreateCompatibleDC(hdc); + HGDIOBJ oldBitmap = SelectObject(hdcMem, hMask); + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + BYTE* pixel = (BYTE*)pBits + (y * width + x) * 4; + BYTE alpha = pixel[3]; + COLORREF maskColor = (alpha == 0) ? RGB(0, 0, 0) : RGB(255, 255, 255); + SetPixel(hdcMem, x, y, maskColor); + } + } + + ICONINFO iconInfo; + iconInfo.fIcon = TRUE; + iconInfo.xHotspot = 0; + iconInfo.yHotspot = 0; + iconInfo.hbmMask = hMask; + iconInfo.hbmColor = hBitmap; + + HICON hIcon = CreateIconIndirect(&iconInfo); + + SelectObject(hdcMem, oldBitmap); + DeleteDC(hdcMem); + DeleteObject(hBitmap); + DeleteObject(hMask); + ReleaseDC(NULL, hdc); + + return hIcon; +#else + return NULL; +#endif +} + // Some GUIDs we need to know without linking to libraries that aren't available before Vista. /* *INDENT-OFF* */ // clang-format off static const GUID SDL_KSDATAFORMAT_SUBTYPE_PCM = { 0x00000001, 0x0000, 0x0010,{ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } }; diff --git a/src/core/windows/SDL_windows.h b/src/core/windows/SDL_windows.h index ef54fe379e..1cd1aca334 100644 --- a/src/core/windows/SDL_windows.h +++ b/src/core/windows/SDL_windows.h @@ -157,7 +157,11 @@ extern void WIN_RECTToRect(const RECT *winrect, SDL_Rect *sdlrect); extern void WIN_RectToRECT(const SDL_Rect *sdlrect, RECT *winrect); // Returns false if a window client rect is not valid -bool WIN_WindowRectValid(const RECT *rect); +extern bool WIN_WindowRectValid(const RECT *rect); + +extern void WIN_UpdateDarkModeForHWND(HWND hwnd); + +extern HICON WIN_CreateIconFromSurface(SDL_Surface *surface); extern SDL_AudioFormat SDL_WaveFormatExToSDLFormat(WAVEFORMATEX *waveformat); diff --git a/src/tray/dummy/SDL_tray.c b/src/tray/dummy/SDL_tray.c index 766fb92584..0847e34357 100644 --- a/src/tray/dummy/SDL_tray.c +++ b/src/tray/dummy/SDL_tray.c @@ -21,7 +21,7 @@ #include "SDL_internal.h" -#ifndef SDL_PLATFORM_MACOS +#ifdef SDL_TRAY_DUMMY #include "../SDL_tray_utils.h" @@ -140,4 +140,4 @@ void SDL_DestroyTray(SDL_Tray *tray) { } -#endif // !SDL_PLATFORM_MACOS +#endif // SDL_TRAY_DUMMY diff --git a/src/tray/windows/SDL_tray.c b/src/tray/windows/SDL_tray.c index 15021ac798..31da4d2ff7 100644 --- a/src/tray/windows/SDL_tray.c +++ b/src/tray/windows/SDL_tray.c @@ -23,13 +23,10 @@ #include "../SDL_tray_utils.h" #include "../../core/windows/SDL_windows.h" -#include "../../video/windows/SDL_windowswindow.h" #include #include -#include "../../video/windows/SDL_surface_utils.h" - #ifndef NOTIFYICON_VERSION_4 #define NOTIFYICON_VERSION_4 4 #endif @@ -115,7 +112,7 @@ LRESULT CALLBACK TrayWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lPar case WM_TRAYICON: if (LOWORD(lParam) == WM_CONTEXTMENU || LOWORD(lParam) == WM_LBUTTONUP) { SetForegroundWindow(hwnd); - + if (tray->menu) { TrackPopupMenu(tray->menu->hMenu, TPM_BOTTOMALIGN | TPM_RIGHTALIGN, GET_X_LPARAM(wParam), GET_Y_LPARAM(wParam), 0, hwnd, NULL); } @@ -247,7 +244,7 @@ SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip) SDL_free(tooltipw); if (icon) { - tray->nid.hIcon = CreateIconFromSurface(icon); + tray->nid.hIcon = WIN_CreateIconFromSurface(icon); if (!tray->nid.hIcon) { tray->nid.hIcon = load_default_icon(); @@ -280,7 +277,7 @@ void SDL_SetTrayIcon(SDL_Tray *tray, SDL_Surface *icon) } if (icon) { - tray->nid.hIcon = CreateIconFromSurface(icon); + tray->nid.hIcon = WIN_CreateIconFromSurface(icon); if (!tray->nid.hIcon) { tray->nid.hIcon = load_default_icon(); diff --git a/src/video/windows/SDL_surface_utils.c b/src/video/windows/SDL_surface_utils.c deleted file mode 100644 index 3e80438104..0000000000 --- a/src/video/windows/SDL_surface_utils.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - 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_surface_utils.h" - -#include "../SDL_surface_c.h" - -#if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)) -HICON CreateIconFromSurface(SDL_Surface *surface) -{ - SDL_Surface *s = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ARGB8888); - if (!s) { - return NULL; - } - - /* The dimensions will be needed after s is freed */ - const int width = s->w; - const int height = s->h; - - BITMAPINFO bmpInfo; - SDL_zero(bmpInfo); - bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmpInfo.bmiHeader.biWidth = width; - bmpInfo.bmiHeader.biHeight = -height; /* Top-down bitmap */ - bmpInfo.bmiHeader.biPlanes = 1; - bmpInfo.bmiHeader.biBitCount = 32; - bmpInfo.bmiHeader.biCompression = BI_RGB; - - HDC hdc = GetDC(NULL); - void *pBits = NULL; - HBITMAP hBitmap = CreateDIBSection(hdc, &bmpInfo, DIB_RGB_COLORS, &pBits, NULL, 0); - if (!hBitmap) { - ReleaseDC(NULL, hdc); - SDL_DestroySurface(s); - return NULL; - } - - SDL_memcpy(pBits, s->pixels, width * height * 4); - - SDL_DestroySurface(s); - - HBITMAP hMask = CreateBitmap(width, height, 1, 1, NULL); - if (!hMask) { - DeleteObject(hBitmap); - ReleaseDC(NULL, hdc); - return NULL; - } - - HDC hdcMem = CreateCompatibleDC(hdc); - HGDIOBJ oldBitmap = SelectObject(hdcMem, hMask); - - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - BYTE* pixel = (BYTE*)pBits + (y * width + x) * 4; - BYTE alpha = pixel[3]; - COLORREF maskColor = (alpha == 0) ? RGB(0, 0, 0) : RGB(255, 255, 255); - SetPixel(hdcMem, x, y, maskColor); - } - } - - ICONINFO iconInfo; - iconInfo.fIcon = TRUE; - iconInfo.xHotspot = 0; - iconInfo.yHotspot = 0; - iconInfo.hbmMask = hMask; - iconInfo.hbmColor = hBitmap; - - HICON hIcon = CreateIconIndirect(&iconInfo); - - SelectObject(hdcMem, oldBitmap); - DeleteDC(hdcMem); - DeleteObject(hBitmap); - DeleteObject(hMask); - ReleaseDC(NULL, hdc); - - return hIcon; -} -#endif diff --git a/src/video/windows/SDL_surface_utils.h b/src/video/windows/SDL_surface_utils.h deleted file mode 100644 index a793cdcf8c..0000000000 --- a/src/video/windows/SDL_surface_utils.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - 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_surface_utils_h_ -#define SDL_surface_utils_h_ - -#include "../../core/windows/SDL_windows.h" - -#ifdef __cplusplus -extern "C" { -#endif - -extern HICON CreateIconFromSurface(SDL_Surface *surface); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index aadfbd734b..5902f8f9c3 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -43,44 +43,6 @@ #include #endif -// Dark mode support -typedef enum { - UXTHEME_APPMODE_DEFAULT, - UXTHEME_APPMODE_ALLOW_DARK, - UXTHEME_APPMODE_FORCE_DARK, - UXTHEME_APPMODE_FORCE_LIGHT, - UXTHEME_APPMODE_MAX -} UxthemePreferredAppMode; - -typedef enum { - WCA_UNDEFINED = 0, - WCA_USEDARKMODECOLORS = 26, - WCA_LAST = 27 -} WINDOWCOMPOSITIONATTRIB; - -typedef struct { - WINDOWCOMPOSITIONATTRIB Attrib; - PVOID pvData; - SIZE_T cbData; -} WINDOWCOMPOSITIONATTRIBDATA; - -typedef struct { - ULONG dwOSVersionInfoSize; - ULONG dwMajorVersion; - ULONG dwMinorVersion; - ULONG dwBuildNumber; - ULONG dwPlatformId; - WCHAR szCSDVersion[128]; -} NT_OSVERSIONINFOW; - -typedef bool (WINAPI *ShouldAppsUseDarkMode_t)(void); -typedef void (WINAPI *AllowDarkModeForWindow_t)(HWND, bool); -typedef void (WINAPI *AllowDarkModeForApp_t)(bool); -typedef void (WINAPI *RefreshImmersiveColorPolicyState_t)(void); -typedef UxthemePreferredAppMode (WINAPI *SetPreferredAppMode_t)(UxthemePreferredAppMode); -typedef BOOL (WINAPI *SetWindowCompositionAttribute_t)(HWND, const WINDOWCOMPOSITIONATTRIBDATA *); -typedef void (NTAPI *RtlGetVersion_t)(NT_OSVERSIONINFOW *); - // Windows CE compatibility #ifndef SWP_NOCOPYBITS #define SWP_NOCOPYBITS 0 @@ -2298,74 +2260,6 @@ bool WIN_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, bool foc } #endif // !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) -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) { - // Too old to support dark mode - return; - } - HMODULE uxtheme = LoadLibrary(TEXT("uxtheme.dll")); - if (!uxtheme) { - return; - } - 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) { - AllowDarkModeForApp_t AllowDarkModeForAppFunc = (AllowDarkModeForApp_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(135)); - if (AllowDarkModeForAppFunc) { - AllowDarkModeForAppFunc(true); - } - } else { - SetPreferredAppMode_t SetPreferredAppModeFunc = (SetPreferredAppMode_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(135)); - if (SetPreferredAppModeFunc) { - SetPreferredAppModeFunc(UXTHEME_APPMODE_ALLOW_DARK); - } - } - if (RefreshImmersiveColorPolicyStateFunc) { - RefreshImmersiveColorPolicyStateFunc(); - } - if (AllowDarkModeForWindowFunc) { - AllowDarkModeForWindowFunc(hwnd, true); - } - BOOL value; - // Check dark mode using ShouldAppsUseDarkMode, but use SDL_GetSystemTheme as a fallback - if (ShouldAppsUseDarkModeFunc) { - value = ShouldAppsUseDarkModeFunc() ? TRUE : FALSE; - } else { - value = (SDL_GetSystemTheme() == SDL_SYSTEM_THEME_DARK) ? TRUE : FALSE; - } - FreeLibrary(uxtheme); - if (os_info.dwBuildNumber < 18362) { - SetProp(hwnd, TEXT("UseImmersiveDarkModeColors"), SDL_reinterpret_cast(HANDLE, SDL_static_cast(INT_PTR, value))); - } else { - HMODULE user32 = GetModuleHandle(TEXT("user32.dll")); - if (user32) { - SetWindowCompositionAttribute_t SetWindowCompositionAttributeFunc = (SetWindowCompositionAttribute_t)GetProcAddress(user32, "SetWindowCompositionAttribute"); - if (SetWindowCompositionAttributeFunc) { - WINDOWCOMPOSITIONATTRIBDATA data = { WCA_USEDARKMODECOLORS, &value, sizeof(value) }; - SetWindowCompositionAttributeFunc(hwnd, &data); - } - } - } -#endif -} - bool WIN_SetWindowParent(SDL_VideoDevice *_this, SDL_Window *window, SDL_Window *parent) { #if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index 8401ab65a3..9ee8d748a5 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -136,7 +136,6 @@ extern bool WIN_SetWindowHitTest(SDL_Window *window, bool enabled); extern void WIN_AcceptDragAndDrop(SDL_Window *window, bool accept); extern bool WIN_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation); extern bool WIN_ApplyWindowProgress(SDL_VideoDevice *_this, SDL_Window *window); -extern void WIN_UpdateDarkModeForHWND(HWND hwnd); extern bool WIN_SetWindowPositionInternal(SDL_Window *window, UINT flags, SDL_WindowRect rect_type); extern void WIN_ShowWindowSystemMenu(SDL_Window *window, int x, int y); extern bool WIN_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, bool focusable);