From 6e6e105f01726208d60c060c4de653cd15470db3 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 3 Jan 2025 21:20:38 +0200 Subject: #3317 Fix full screen issue with Windows 11 24H2 --- indra/llwindow/llwindowwin32.cpp | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 1cac6ffe08..5d42258068 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -695,8 +695,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, } if (dev_mode.dmPelsWidth == width && - dev_mode.dmPelsHeight == height && - dev_mode.dmBitsPerPel == BITS_PER_PIXEL) + dev_mode.dmPelsHeight == height) { success = true; if ((dev_mode.dmDisplayFrequency - current_refresh) @@ -736,7 +735,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, // If we found a good resolution, use it. if (success) { - success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh); + success = setDisplayResolution(width, height, closest_refresh); } // Keep a copy of the actual current device mode in case we minimize @@ -749,7 +748,6 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, mFullscreen = true; mFullscreenWidth = dev_mode.dmPelsWidth; mFullscreenHeight = dev_mode.dmPelsHeight; - mFullscreenBits = dev_mode.dmBitsPerPel; mFullscreenRefresh = dev_mode.dmDisplayFrequency; LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth @@ -763,7 +761,6 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, mFullscreen = false; mFullscreenWidth = -1; mFullscreenHeight = -1; - mFullscreenBits = -1; mFullscreenRefresh = -1; std::map args; @@ -1185,7 +1182,7 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo // If we found a good resolution, use it. if (success) { - success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh); + success = setDisplayResolution(width, height, closest_refresh); } // Keep a copy of the actual current device mode in case we minimize @@ -1197,7 +1194,6 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo mFullscreen = true; mFullscreenWidth = dev_mode.dmPelsWidth; mFullscreenHeight = dev_mode.dmPelsHeight; - mFullscreenBits = dev_mode.dmBitsPerPel; mFullscreenRefresh = dev_mode.dmDisplayFrequency; LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth @@ -1223,7 +1219,6 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo mFullscreen = false; mFullscreenWidth = -1; mFullscreenHeight = -1; - mFullscreenBits = -1; mFullscreenRefresh = -1; LL_INFOS("Window") << "Unable to run fullscreen at " << width << "x" << height << LL_ENDL; @@ -3517,7 +3512,7 @@ F32 LLWindowWin32::getPixelAspectRatio() // Change display resolution. Returns true if successful. // protected -bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh) +bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 refresh) { DEVMODE dev_mode; ::ZeroMemory(&dev_mode, sizeof(DEVMODE)); @@ -3529,7 +3524,6 @@ bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 re { if (dev_mode.dmPelsWidth == width && dev_mode.dmPelsHeight == height && - dev_mode.dmBitsPerPel == bits && dev_mode.dmDisplayFrequency == refresh ) { // ...display mode identical, do nothing @@ -3541,9 +3535,8 @@ bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 re dev_mode.dmSize = sizeof(dev_mode); dev_mode.dmPelsWidth = width; dev_mode.dmPelsHeight = height; - dev_mode.dmBitsPerPel = bits; dev_mode.dmDisplayFrequency = refresh; - dev_mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; + dev_mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; // CDS_FULLSCREEN indicates that this is a temporary change to the device mode. LONG cds_result = ChangeDisplaySettings(&dev_mode, CDS_FULLSCREEN); @@ -3553,7 +3546,7 @@ bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 re if (!success) { LL_WARNS("Window") << "setDisplayResolution failed, " - << width << "x" << height << "x" << bits << " @ " << refresh << LL_ENDL; + << width << "x" << height << " @ " << refresh << LL_ENDL; } return success; @@ -3564,7 +3557,7 @@ bool LLWindowWin32::setFullscreenResolution() { if (mFullscreen) { - return setDisplayResolution( mFullscreenWidth, mFullscreenHeight, mFullscreenBits, mFullscreenRefresh); + return setDisplayResolution( mFullscreenWidth, mFullscreenHeight, mFullscreenRefresh); } else { -- cgit v1.2.3 From 0c89d06ec2441f035c8de4abc9c6545f9fe9ee66 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 23 Jul 2025 12:11:14 +0300 Subject: #4374 add support for the system theme (light and dark) --- indra/llwindow/llwindowwin32.cpp | 82 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index af53b6fb3f..d97d6e0bb2 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -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 +#include // 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; +} -- cgit v1.2.3 From 9df3b30479e35f0a301d8871582b95e4e2caab7c Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 24 Jul 2025 00:44:16 +0300 Subject: #4424 don't try to update theme too early --- indra/llwindow/llwindowwin32.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index d97d6e0bb2..76d72fe725 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -859,6 +859,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, // Initialize (boot strap) the Language text input management, // based on the system's (or user's) default settings. allowLanguageTextInput(NULL, false); + updateWindowTheme(); } @@ -1829,8 +1830,6 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw mhDC = pair.second; sWindowHandleForMessageBox = mWindowHandle; - - updateWindowTheme(); } void* LLWindowWin32::createSharedContext() -- cgit v1.2.3 From 5291fc252aba354e129ec85076348059cae01f3a Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Sat, 26 Jul 2025 01:20:22 +0300 Subject: #4374 update icon for title bar --- indra/llwindow/llwindowwin32.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'indra/llwindow/llwindowwin32.cpp') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 76d72fe725..68b6de197a 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -113,6 +113,7 @@ static std::thread::id sMainThreadId; LPWSTR gIconResource = IDI_APPLICATION; +LPWSTR gIconSmallResource = IDI_APPLICATION; LPDIRECTINPUT8 gDirectInput8; LLW32MsgCallback gAsyncMsgCallback = NULL; @@ -527,6 +528,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, mFSAASamples = fsaa_samples; mIconResource = gIconResource; + mIconSmallResource = gIconSmallResource; mOverrideAspectRatio = 0.f; mNativeAspectRatio = 0.f; mInputProcessingPaused = false; @@ -860,6 +862,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, // based on the system's (or user's) default settings. allowLanguageTextInput(NULL, false); updateWindowTheme(); + setCustomIcon(); } @@ -5043,3 +5046,20 @@ void LLWindowWin32::updateWindowTheme() LL_INFOS("Window") << "Viewer window theme is set to " << (use_dark_mode ? "dark" : "light") << " mode" << LL_ENDL; } + +void LLWindowWin32::setCustomIcon() +{ + if (mWindowHandle) + { + HICON hDefaultIcon = LoadIcon(mhInstance, mIconResource); + HICON hSmallIcon = LoadIcon(mhInstance, mIconSmallResource); + mWindowThread->post([=]() + { + SendMessage(mWindowHandle, WM_SETICON, ICON_BIG, (LPARAM)hDefaultIcon); + SendMessage(mWindowHandle, WM_SETICON, ICON_SMALL, (LPARAM)hSmallIcon); + + SetClassLongPtr(mWindowHandle, GCLP_HICON, (LONG_PTR)hDefaultIcon); + SetClassLongPtr(mWindowHandle, GCLP_HICONSM, (LONG_PTR)hSmallIcon); + }); + } +} -- cgit v1.2.3