mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-01-06 21:37:47 +00:00
Allow building the tray subsystem without the video subsystem
Fixes https://github.com/libsdl-org/SDL/issues/13235
This commit is contained in:
@@ -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 $<LINK_LIBRARY:feature,library-list>
|
||||
|
||||
@@ -889,7 +889,6 @@
|
||||
<ClCompile Include="..\..\src\video\SDL_video_unsupported.c" />
|
||||
<ClCompile Include="..\..\src\video\SDL_vulkan_utils.c" />
|
||||
<ClCompile Include="..\..\src\video\SDL_yuv.c" />
|
||||
<ClCompile Include="..\..\src\video\windows\SDL_surface_utils.c" />
|
||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsclipboard.c" />
|
||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsevents.c" />
|
||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsframebuffer.c" />
|
||||
|
||||
@@ -191,7 +191,6 @@
|
||||
<ClCompile Include="..\..\src\video\SDL_video_unsupported.c" />
|
||||
<ClCompile Include="..\..\src\video\SDL_vulkan_utils.c" />
|
||||
<ClCompile Include="..\..\src\video\SDL_yuv.c" />
|
||||
<ClCompile Include="..\..\src\video\windows\SDL_surface_utils.c" />
|
||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsclipboard.c" />
|
||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsevents.c" />
|
||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsframebuffer.c" />
|
||||
|
||||
@@ -744,7 +744,6 @@
|
||||
<ClCompile Include="..\..\src\video\SDL_video_unsupported.c" />
|
||||
<ClCompile Include="..\..\src\video\SDL_vulkan_utils.c" />
|
||||
<ClCompile Include="..\..\src\video\SDL_yuv.c" />
|
||||
<ClCompile Include="..\..\src\video\windows\SDL_surface_utils.c" />
|
||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsclipboard.c" />
|
||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsevents.c" />
|
||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsframebuffer.c" />
|
||||
@@ -775,4 +774,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1356,9 +1356,6 @@
|
||||
<ClCompile Include="..\..\src\video\dummy\SDL_nullvideo.c">
|
||||
<Filter>video\dummy</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\video\windows\SDL_surface_utils.c">
|
||||
<Filter>video\windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\video\windows\SDL_windowsclipboard.c">
|
||||
<Filter>video\windows</Filter>
|
||||
</ClCompile>
|
||||
@@ -1618,4 +1615,4 @@
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\..\src\core\windows\version.rc" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
#include "SDL_windows.h"
|
||||
|
||||
#include "../../video/SDL_surface_c.h"
|
||||
|
||||
#include <objbase.h> // for CoInitialize/CoUninitialize (Win32 only)
|
||||
#ifdef HAVE_ROAPI_H
|
||||
#include <roapi.h> // 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 } };
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -23,13 +23,10 @@
|
||||
|
||||
#include "../SDL_tray_utils.h"
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include "../../video/windows/SDL_windowswindow.h"
|
||||
|
||||
#include <windowsx.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#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();
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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
|
||||
@@ -43,44 +43,6 @@
|
||||
#include <shobjidl.h>
|
||||
#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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user