#4374 add support for the system theme (light and dark)

meow-7.2.2
Maxim Nikolenko 2025-07-23 12:11:14 +03:00 committed by GitHub
parent 08971cd9ac
commit 0c89d06ec2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 86 additions and 0 deletions

View File

@ -76,6 +76,11 @@
#pragma comment(lib, "dxguid.lib") // needed for llurlentry test to build on some systems
#pragma comment(lib, "dinput8")
#pragma comment(lib, "UxTheme.lib")
#pragma comment(lib, "Dwmapi.lib")
#include <Uxtheme.h>
#include <dwmapi.h> // needed for DwmSetWindowAttribute to set window theme
const S32 MAX_MESSAGE_PER_UPDATE = 20;
const S32 BITS_PER_PIXEL = 32;
const S32 MAX_NUM_RESOLUTIONS = 32;
@ -85,6 +90,10 @@ const F32 ICON_FLASH_TIME = 0.5f;
#define USER_DEFAULT_SCREEN_DPI 96 // Win7
#endif
#ifndef WM_DWMCOLORIZATIONCOLORCHANGED
#define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320
#endif
// Claim a couple unused GetMessage() message IDs
const UINT WM_DUMMY_(WM_USER + 0x0017);
const UINT WM_POST_FUNCTION_(WM_USER + 0x0018);
@ -137,6 +146,17 @@ typedef HRESULT(STDAPICALLTYPE *GetDpiForMonitorType)(
_Out_ UINT *dpiX,
_Out_ UINT *dpiY);
typedef enum PREFERRED_APP_MODE
{
DEFAULT,
ALLOW_DARK,
FORCE_DARK,
FORCE_LIGHT,
MAX
} PREFERRED_APP_MODE;
typedef PREFERRED_APP_MODE(WINAPI* fnSetPreferredAppMode)(PREFERRED_APP_MODE mode);
//
// LLWindowWin32
//
@ -1809,6 +1829,8 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw
mhDC = pair.second;
sWindowHandleForMessageBox = mWindowHandle;
updateWindowTheme();
}
void* LLWindowWin32::createSharedContext()
@ -3007,6 +3029,17 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
WINDOW_IMP_POST(window_imp->mMouseVanish = true);
}
}
// Check if theme-related settings changed
else if (l_param && (wcscmp((LPCWSTR)l_param, L"ImmersiveColorSet") == 0))
{
WINDOW_IMP_POST(window_imp->updateWindowTheme());
}
}
break;
case WM_DWMCOLORIZATIONCOLORCHANGED:
{
WINDOW_IMP_POST(window_imp->updateWindowTheme());
}
break;
@ -4962,3 +4995,52 @@ void LLWindowWin32::updateWindowRect()
});
}
}
bool LLWindowWin32::isSystemAppDarkMode()
{
HKEY hKey;
DWORD dwValue = 1; // Default to light theme
DWORD dwSize = sizeof(DWORD);
// Check registry for system theme preference
LSTATUS ret_code =
RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_READ, &hKey);
if (ERROR_SUCCESS == ret_code)
{
if (RegQueryValueExW(hKey, L"AppsUseLightTheme", NULL, NULL, (LPBYTE)&dwValue, &dwSize) != ERROR_SUCCESS)
{
// If AppsUseLightTheme is not found, check SystemUsesLightTheme
dwSize = sizeof(DWORD);
RegQueryValueExW(hKey, L"SystemUsesLightTheme", NULL, NULL, (LPBYTE)&dwValue, &dwSize);
}
RegCloseKey(hKey);
}
// Return true if dark mode
return dwValue == 0;
}
void LLWindowWin32::updateWindowTheme()
{
bool use_dark_mode = isSystemAppDarkMode();
if (use_dark_mode == mCurrentDarkMode)
{
return;
}
mCurrentDarkMode = use_dark_mode;
HMODULE hUxTheme = LoadLibraryExW(L"uxtheme.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (hUxTheme)
{
auto SetPreferredAppMode = (fnSetPreferredAppMode)GetProcAddress(hUxTheme, "SetPreferredAppMode");
if (SetPreferredAppMode)
{
SetPreferredAppMode(use_dark_mode ? ALLOW_DARK : FORCE_LIGHT);
}
FreeLibrary(hUxTheme);
}
BOOL dark_mode(use_dark_mode);
DwmSetWindowAttribute(mWindowHandle, DWMWA_USE_IMMERSIVE_DARK_MODE, &dark_mode, sizeof(dark_mode));
LL_INFOS("Window") << "Viewer window theme is set to " << (use_dark_mode ? "dark" : "light") << " mode" << LL_ENDL;
}

View File

@ -246,6 +246,10 @@ protected:
RECT mRect;
RECT mClientRect;
void updateWindowTheme();
bool isSystemAppDarkMode();
bool mCurrentDarkMode { false };
struct LLWindowWin32Thread;
LLWindowWin32Thread* mWindowThread = nullptr;
LLThreadSafeQueue<std::function<void()>> mFunctionQueue;