From 26826d5a5f93136d00a212c88854217ee2fdbcde Mon Sep 17 00:00:00 2001 From: Vortex2Oblivion <73261680+Vortex2Oblivion@users.noreply.github.com> Date: Mon, 6 Apr 2026 19:50:42 -0400 Subject: [PATCH] add isLightTheme function --- src/hxwindowmode/WindowColorMode.hx | 14 +++- src/hxwindowmode/backend/WindowBackend.hx | 3 + src/hxwindowmode/backend/build.xml | 1 + .../backend/src/windowbackend.cpp | 64 +++++++++++++++---- .../backend/src/windowbackend.hpp | 1 + 5 files changed, 69 insertions(+), 14 deletions(-) diff --git a/src/hxwindowmode/WindowColorMode.hx b/src/hxwindowmode/WindowColorMode.hx index 8eacb14..b3d0406 100644 --- a/src/hxwindowmode/WindowColorMode.hx +++ b/src/hxwindowmode/WindowColorMode.hx @@ -36,7 +36,9 @@ class WindowColorMode { * Useful for checking if you need to force redraw the window header. */ public static var isWindows10(get, never):Bool; - public static function get_isWindows10():Bool { + + @:noCompletion + private static inline function get_isWindows10():Bool { #if lime //could use some C++ code but this works too return (lime.system.System.platformLabel.toLowerCase().indexOf("windows 10") != -1); @@ -153,9 +155,19 @@ class WindowColorMode { */ public static inline function redrawWindowHeader() { #if lime + #if !desktop + trace('`redrawWindowHeader` is not available on this platform!'); + #end for (i in 0...2) lime.app.Application.current.window.borderless = !lime.app.Application.current.window.borderless; #end } + + public static inline function isLightTheme() { + #if(!cpp || !windows) + trace('`isLightTheme` is not available on this platform!'); + #end + return WindowBackend.isLightTheme(); + } } enum abstract WindowCornerType(Int) { diff --git a/src/hxwindowmode/backend/WindowBackend.hx b/src/hxwindowmode/backend/WindowBackend.hx index c92f607..a4c02c0 100644 --- a/src/hxwindowmode/backend/WindowBackend.hx +++ b/src/hxwindowmode/backend/WindowBackend.hx @@ -18,4 +18,7 @@ extern class WindowBackend { @:native("nativeWindowColorMode::updateWindow") private static function updateWindow():Void; + + @:native("nativeWindowColorMode::isLightTheme") + private static function isLightTheme():Bool; } diff --git a/src/hxwindowmode/backend/build.xml b/src/hxwindowmode/backend/build.xml index fd16c4a..e0bea89 100644 --- a/src/hxwindowmode/backend/build.xml +++ b/src/hxwindowmode/backend/build.xml @@ -18,5 +18,6 @@ + \ No newline at end of file diff --git a/src/hxwindowmode/backend/src/windowbackend.cpp b/src/hxwindowmode/backend/src/windowbackend.cpp index d5ce4d1..5be5e6d 100644 --- a/src/hxwindowmode/backend/src/windowbackend.cpp +++ b/src/hxwindowmode/backend/src/windowbackend.cpp @@ -3,11 +3,14 @@ #ifdef HX_WINDOWS #include #include +#include +#include +#include #endif bool nativeWindowColorMode::setWindowColorMode(bool isDarkMode) { - #ifdef HX_WINDOWS +#ifdef HX_WINDOWS HWND window = GetActiveWindow(); int isDark = (isDarkMode ? 1 : 0); bool hasChanged = (DwmSetWindowAttribute(window, 19, &isDark, sizeof(isDark)) == S_OK); @@ -19,50 +22,85 @@ bool nativeWindowColorMode::setWindowColorMode(bool isDarkMode) UpdateWindow(window); return hasChanged; - #else +#else return false; - #endif +#endif } void nativeWindowColorMode::setWindowBorderColor(::Array color, bool setHeader, bool setBorder) { - #ifdef HX_WINDOWS +#ifdef HX_WINDOWS HWND window = GetActiveWindow(); auto finalColor = RGB(color[0], color[1], color[2]); - if(setHeader) + if (setHeader) DwmSetWindowAttribute(window, 35, &finalColor, sizeof(COLORREF)); - if(setBorder) + if (setBorder) DwmSetWindowAttribute(window, 34, &finalColor, sizeof(COLORREF)); UpdateWindow(window); - #endif +#endif } void nativeWindowColorMode::setWindowTitleColor(::Array color) { - #ifdef HX_WINDOWS +#ifdef HX_WINDOWS HWND window = GetActiveWindow(); auto finalColor = RGB(color[0], color[1], color[2]); DwmSetWindowAttribute(window, 36, &finalColor, sizeof(COLORREF)); UpdateWindow(window); - #endif +#endif } void nativeWindowColorMode::setWindowCornerType(int cornerType) { - #ifdef HX_WINDOWS +#ifdef HX_WINDOWS HWND window = GetActiveWindow(); DwmSetWindowAttribute(window, 33, &cornerType, sizeof(cornerType)); UpdateWindow(window); - #endif +#endif } void nativeWindowColorMode::updateWindow() { - #ifdef HX_WINDOWS +#ifdef HX_WINDOWS UpdateWindow(GetActiveWindow()); - #endif +#endif +} + +/** + * @see https://stackoverflow.com/questions/51334674/how-to-detect-windows-10-light-dark-mode-in-win32-application + */ +bool nativeWindowColorMode::isLightTheme() +{ +#ifdef HX_WINDOWS + // The value is expected to be a REG_DWORD, which is a signed 32-bit little-endian + auto buffer = std::vector(4); + auto cbData = static_cast(buffer.size() * sizeof(char)); + auto res = RegGetValueW( + HKEY_CURRENT_USER, + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", + L"AppsUseLightTheme", + RRF_RT_REG_DWORD, // expected value type + nullptr, + buffer.data(), + &cbData); + + if (res != ERROR_SUCCESS) + { + throw std::runtime_error("Error: error_code=" + std::to_string(res)); + } + + // convert bytes written to our buffer to an int, assuming little-endian + auto i = int(buffer[3] << 24 | + buffer[2] << 16 | + buffer[1] << 8 | + buffer[0]); + + return i == 1; +#else + return false; +#endif } \ No newline at end of file diff --git a/src/hxwindowmode/backend/src/windowbackend.hpp b/src/hxwindowmode/backend/src/windowbackend.hpp index 52ab1cd..9bd03da 100644 --- a/src/hxwindowmode/backend/src/windowbackend.hpp +++ b/src/hxwindowmode/backend/src/windowbackend.hpp @@ -9,4 +9,5 @@ namespace nativeWindowColorMode void setWindowTitleColor(::Array color); void setWindowCornerType(int cornerType); void updateWindow(); + bool isLightTheme(); } \ No newline at end of file