From 9df37ee2f50c67656c56868bf2e01645cf1a0dfa Mon Sep 17 00:00:00 2001 From: floppyhammer Date: Fri, 16 Dec 2022 14:16:28 +0800 Subject: [PATCH 1/7] Win32: Add dark mode for title bar --- src/win32_init.c | 14 ++++++++++++++ src/win32_platform.h | 20 +++++++++++++++++++- src/win32_window.c | 24 ++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/win32_init.c b/src/win32_init.c index 64393e77..63b77663 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -151,6 +151,8 @@ static GLFWbool loadLibraries(void) _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow"); _glfw.win32.dwmapi.GetColorizationColor = (PFN_DwmGetColorizationColor) _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmGetColorizationColor"); + _glfw.win32.dwmapi.SetWindowAttribute = (PFN_DwmSetWindowAttribute) + _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmSetWindowAttribute"); } _glfw.win32.shcore.instance = _glfwPlatformLoadModule("shcore.dll"); @@ -169,6 +171,18 @@ static GLFWbool loadLibraries(void) _glfwPlatformGetModuleSymbol(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo"); } + _glfw.win32.uxtheme.instance = _glfwPlatformLoadModule("uxtheme.dll"); + if (_glfw.win32.uxtheme.instance) + { + _glfw.win32.uxtheme.ShouldAppsUseDarkMode = (ShouldAppsUseDarkModePtr)_glfwPlatformGetModuleSymbol(_glfw.win32.uxtheme.instance, MAKEINTRESOURCEA(132)); + _glfw.win32.uxtheme.GetImmersiveColorFromColorSetEx = (GetImmersiveColorFromColorSetExPtr)_glfwPlatformGetModuleSymbol(_glfw.win32.uxtheme.instance, MAKEINTRESOURCEA(95)); + _glfw.win32.uxtheme.GetImmersiveColorTypeFromName = (GetImmersiveColorTypeFromNamePtr)_glfwPlatformGetModuleSymbol(_glfw.win32.uxtheme.instance, MAKEINTRESOURCEA(96)); + _glfw.win32.uxtheme.GetImmersiveUserColorSetPreference = (GetImmersiveUserColorSetPreferencePtr)_glfwPlatformGetModuleSymbol(_glfw.win32.uxtheme.instance, MAKEINTRESOURCEA(98)); + + _glfw.win32.uxtheme.uxThemeAvailable = _glfw.win32.uxtheme.ShouldAppsUseDarkMode && _glfw.win32.uxtheme.GetImmersiveColorFromColorSetEx && _glfw.win32.uxtheme.GetImmersiveColorTypeFromName && _glfw.win32.uxtheme.GetImmersiveUserColorSetPreference; + _glfw.win32.uxtheme.darkTitleAvailable = _glfwIsWindows10BuildOrGreaterWin32(22000); + } + return GLFW_TRUE; } diff --git a/src/win32_platform.h b/src/win32_platform.h index 82b34bb9..c572f568 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -299,12 +299,15 @@ typedef int (WINAPI * PFN_GetSystemMetricsForDpi)(int,UINT); // dwmapi.dll function pointer typedefs typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*); typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID); -typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*); +typedef HRESULT (WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*); typedef HRESULT (WINAPI * PFN_DwmGetColorizationColor)(DWORD*,BOOL*); +typedef HRESULT (WINAPI * PFN_DwmSetWindowAttribute)(HWND,DWORD,LPCVOID,DWORD); + #define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled #define DwmFlush _glfw.win32.dwmapi.Flush #define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow #define DwmGetColorizationColor _glfw.win32.dwmapi.GetColorizationColor +#define DwmSetWindowAttribute _glfw.win32.dwmapi.SetWindowAttribute // shcore.dll function pointer typedefs typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); @@ -366,6 +369,10 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)( #define GLFW_WGL_CONTEXT_STATE _GLFWcontextWGL wgl; #define GLFW_WGL_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl; +typedef BOOL (WINAPI * ShouldAppsUseDarkModePtr)(); +typedef DWORD(WINAPI * GetImmersiveColorFromColorSetExPtr)(UINT,UINT,BOOL,UINT); +typedef int (WINAPI * GetImmersiveColorTypeFromNamePtr)(const WCHAR*); +typedef int (WINAPI * GetImmersiveUserColorSetPreferencePtr)(BOOL,BOOL); // WGL-specific per-context data // @@ -487,6 +494,7 @@ typedef struct _GLFWlibraryWin32 PFN_DwmFlush Flush; PFN_DwmEnableBlurBehindWindow EnableBlurBehindWindow; PFN_DwmGetColorizationColor GetColorizationColor; + PFN_DwmSetWindowAttribute SetWindowAttribute; } dwmapi; struct { @@ -499,6 +507,16 @@ typedef struct _GLFWlibraryWin32 HINSTANCE instance; PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_; } ntdll; + + struct { + HINSTANCE instance; + GLFWbool uxThemeAvailable; + GLFWbool darkTitleAvailable; + ShouldAppsUseDarkModePtr ShouldAppsUseDarkMode; + GetImmersiveColorFromColorSetExPtr GetImmersiveColorFromColorSetEx; + GetImmersiveColorTypeFromNamePtr GetImmersiveColorTypeFromName; + GetImmersiveUserColorSetPreferencePtr GetImmersiveUserColorSetPreference; + } uxtheme; } _GLFWlibraryWin32; // Win32-specific per-monitor data diff --git a/src/win32_window.c b/src/win32_window.c index 676640bf..56e3afc0 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -37,6 +37,23 @@ #include #include +// Ref: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +// Update window theme (light/dark) +// +static void updateTheme(HWND hWnd) { + if (_glfw.win32.uxtheme.uxThemeAvailable && _glfw.win32.uxtheme.darkTitleAvailable) { + BOOL value = _glfw.win32.uxtheme.ShouldAppsUseDarkMode() & 0x1; + DwmSetWindowAttribute(hWnd, + DWMWA_USE_IMMERSIVE_DARK_MODE, + &value, + sizeof(value)); + } +} + // Returns the window style for the specified window // static DWORD getWindowStyle(const _GLFWwindow* window) @@ -1146,6 +1163,11 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l return 0; } + case WM_THEMECHANGED: + case WM_SETTINGCHANGE: { + updateTheme(window->win32.handle); + } break; + case WM_GETDPISCALEDSIZE: { if (window->win32.scaleToMonitor) @@ -1436,6 +1458,8 @@ static int createNativeWindow(_GLFWwindow* window, _glfwGetWindowSizeWin32(window, &window->win32.width, &window->win32.height); + updateTheme(window->win32.handle); + return GLFW_TRUE; } From 2adf1134df19580574e3c429f6ed174ba4e9ca6b Mon Sep 17 00:00:00 2001 From: floppyhammer Date: Sun, 19 Feb 2023 22:11:50 +0800 Subject: [PATCH 2/7] Modify CONTRIBUTORS.md & README.md --- CONTRIBUTORS.md | 1 + README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 110ed4cd..3ddef481 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -260,6 +260,7 @@ video tutorials. - Jonas Ådahl - Lasse Öörni - Leonard König + - Haoyun Chen - All the unmentioned and anonymous contributors in the GLFW community, for bug reports, patches, feedback, testing and encouragement diff --git a/README.md b/README.md index 8b4a1546..4277db2d 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,7 @@ information on what to include when reporting a bug. ## Changelog + - [Win32] Added support for dark title bar #2228 - Added `GLFW_PLATFORM` init hint for runtime platform selection (#1958) - Added `GLFW_ANY_PLATFORM`, `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` and `GLFW_PLATFORM_NULL` symbols to From e06507a75c8436a46a46aae9d944eea5d9e4f841 Mon Sep 17 00:00:00 2001 From: floppyhammer Date: Sun, 19 Feb 2023 22:23:35 +0800 Subject: [PATCH 3/7] Free uxtheme properly --- src/win32_init.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/win32_init.c b/src/win32_init.c index 63b77663..e84a4873 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -207,6 +207,9 @@ static void freeLibraries(void) if (_glfw.win32.ntdll.instance) _glfwPlatformFreeModule(_glfw.win32.ntdll.instance); + + if (_glfw.win32.uxtheme.instance) + _glfwPlatformFreeModule(_glfw.win32.uxtheme.instance); } // Create key code translation tables From 1b371ae3c17534bb8d331e1e8770eca5c7a784bd Mon Sep 17 00:00:00 2001 From: floppyhammer Date: Sun, 19 Feb 2023 22:29:53 +0800 Subject: [PATCH 4/7] Code format --- src/win32_platform.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win32_platform.h b/src/win32_platform.h index c572f568..b5f9ee1f 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -370,7 +370,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)( #define GLFW_WGL_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl; typedef BOOL (WINAPI * ShouldAppsUseDarkModePtr)(); -typedef DWORD(WINAPI * GetImmersiveColorFromColorSetExPtr)(UINT,UINT,BOOL,UINT); +typedef DWORD (WINAPI * GetImmersiveColorFromColorSetExPtr)(UINT,UINT,BOOL,UINT); typedef int (WINAPI * GetImmersiveColorTypeFromNamePtr)(const WCHAR*); typedef int (WINAPI * GetImmersiveUserColorSetPreferencePtr)(BOOL,BOOL); From c388b878241bf44ebd8c7fc81233b635447a16df Mon Sep 17 00:00:00 2001 From: floppyhammer Date: Wed, 22 Feb 2023 14:38:56 +0800 Subject: [PATCH 5/7] Code format --- src/win32_window.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/win32_window.c b/src/win32_window.c index 56e3afc0..1235eec6 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -44,8 +44,10 @@ // Update window theme (light/dark) // -static void updateTheme(HWND hWnd) { - if (_glfw.win32.uxtheme.uxThemeAvailable && _glfw.win32.uxtheme.darkTitleAvailable) { +static void updateTheme(HWND hWnd) +{ + if (_glfw.win32.uxtheme.uxThemeAvailable && _glfw.win32.uxtheme.darkTitleAvailable) + { BOOL value = _glfw.win32.uxtheme.ShouldAppsUseDarkMode() & 0x1; DwmSetWindowAttribute(hWnd, DWMWA_USE_IMMERSIVE_DARK_MODE, @@ -1164,9 +1166,11 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l } case WM_THEMECHANGED: - case WM_SETTINGCHANGE: { + case WM_SETTINGCHANGE: + { updateTheme(window->win32.handle); - } break; + break; + } case WM_GETDPISCALEDSIZE: { From b1e12ef4b98f905a6925c8e94824d6303d0faf4d Mon Sep 17 00:00:00 2001 From: floppyhammer Date: Thu, 23 Feb 2023 10:09:05 +0800 Subject: [PATCH 6/7] Modify CONTRIBUTORS.md & README.md --- CONTRIBUTORS.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 3ddef481..79a26278 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -46,6 +46,7 @@ video tutorials. - Bailey Cosier - Noel Cower - CuriouserThing + - Haoyun Chen - Jason Daly - danhambleton - Jarrod Davis @@ -260,7 +261,6 @@ video tutorials. - Jonas Ådahl - Lasse Öörni - Leonard König - - Haoyun Chen - All the unmentioned and anonymous contributors in the GLFW community, for bug reports, patches, feedback, testing and encouragement diff --git a/README.md b/README.md index 4277db2d..ce579c7d 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,6 @@ information on what to include when reporting a bug. ## Changelog - - [Win32] Added support for dark title bar #2228 - Added `GLFW_PLATFORM` init hint for runtime platform selection (#1958) - Added `GLFW_ANY_PLATFORM`, `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` and `GLFW_PLATFORM_NULL` symbols to @@ -184,6 +183,7 @@ information on what to include when reporting a bug. - Bugfix: `glfwMakeContextCurrent` would access TLS slot before initialization - Bugfix: `glfwSetGammaRamp` could emit `GLFW_INVALID_VALUE` before initialization - Bugfix: `glfwGetJoystickUserPointer` returned `NULL` during disconnection (#2092) + - [Win32] Added support for dark title bar (#2228) - [Win32] Added the `GLFW_WIN32_KEYBOARD_MENU` window hint for enabling access to the window menu - [Win32] Added a version info resource to the GLFW DLL From b16284153e0526a4530b79ac74491dd89eb49053 Mon Sep 17 00:00:00 2001 From: floppyhammer Date: Thu, 23 Feb 2023 10:14:12 +0800 Subject: [PATCH 7/7] Modify CONTRIBUTORS.md --- CONTRIBUTORS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 79a26278..333130dd 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -32,6 +32,7 @@ video tutorials. - David Carlier - Arturo Castro - Chi-kwan Chan + - Haoyun Chen - TheChocolateOre - Ali Chraghi - Joseph Chua @@ -46,7 +47,6 @@ video tutorials. - Bailey Cosier - Noel Cower - CuriouserThing - - Haoyun Chen - Jason Daly - danhambleton - Jarrod Davis