mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-15 03:07:56 +01:00
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request Introduces a new mode that will have Light Switch follow Windows Night Light. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: https://github.com/microsoft/PowerToys/issues/42457 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments Strictly follows the state of Night Light. When NL is on, LS will be switch to dark mode and when NL is off, LS will switch to light mode (with respect to the users system/app selection). <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed Turn on Follow Night Light mode Change night light! ## Notes
139 lines
4.4 KiB
C++
139 lines
4.4 KiB
C++
#include <windows.h>
|
|
#include <logger/logger_settings.h>
|
|
#include <logger/logger.h>
|
|
#include <utils/logger_helper.h>
|
|
#include "ThemeHelper.h"
|
|
#include <SettingsConstants.h>
|
|
|
|
// Controls changing the themes.
|
|
|
|
static void ResetColorPrevalence()
|
|
{
|
|
HKEY hKey;
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER,
|
|
PERSONALIZATION_REGISTRY_PATH,
|
|
0,
|
|
KEY_SET_VALUE,
|
|
&hKey) == ERROR_SUCCESS)
|
|
{
|
|
DWORD value = 0; // back to default value
|
|
RegSetValueEx(hKey, L"ColorPrevalence", 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
|
|
RegCloseKey(hKey);
|
|
|
|
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, reinterpret_cast<LPARAM>(L"ImmersiveColorSet"), SMTO_ABORTIFHUNG, 5000, nullptr);
|
|
|
|
SendMessageTimeout(HWND_BROADCAST, WM_THEMECHANGED, 0, 0, SMTO_ABORTIFHUNG, 5000, nullptr);
|
|
|
|
SendMessageTimeout(HWND_BROADCAST, WM_DWMCOLORIZATIONCOLORCHANGED, 0, 0, SMTO_ABORTIFHUNG, 5000, nullptr);
|
|
}
|
|
}
|
|
|
|
void SetAppsTheme(bool mode)
|
|
{
|
|
HKEY hKey;
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER,
|
|
PERSONALIZATION_REGISTRY_PATH,
|
|
0,
|
|
KEY_SET_VALUE,
|
|
&hKey) == ERROR_SUCCESS)
|
|
{
|
|
DWORD value = mode;
|
|
RegSetValueEx(hKey, L"AppsUseLightTheme", 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
|
|
RegCloseKey(hKey);
|
|
|
|
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, reinterpret_cast<LPARAM>(L"ImmersiveColorSet"), SMTO_ABORTIFHUNG, 5000, nullptr);
|
|
|
|
SendMessageTimeout(HWND_BROADCAST, WM_THEMECHANGED, 0, 0, SMTO_ABORTIFHUNG, 5000, nullptr);
|
|
}
|
|
}
|
|
|
|
void SetSystemTheme(bool mode)
|
|
{
|
|
HKEY hKey;
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER,
|
|
PERSONALIZATION_REGISTRY_PATH,
|
|
0,
|
|
KEY_SET_VALUE,
|
|
&hKey) == ERROR_SUCCESS)
|
|
{
|
|
DWORD value = mode;
|
|
RegSetValueEx(hKey, L"SystemUsesLightTheme", 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
|
|
RegCloseKey(hKey);
|
|
|
|
if (mode) // if are changing to light mode
|
|
{
|
|
ResetColorPrevalence();
|
|
Logger::info(L"[LightSwitchService] Reset ColorPrevalence to default when switching to light mode.");
|
|
}
|
|
|
|
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, reinterpret_cast<LPARAM>(L"ImmersiveColorSet"), SMTO_ABORTIFHUNG, 5000, nullptr);
|
|
|
|
SendMessageTimeout(HWND_BROADCAST, WM_THEMECHANGED, 0, 0, SMTO_ABORTIFHUNG, 5000, nullptr);
|
|
}
|
|
}
|
|
|
|
// Can think of this as "is the current theme light?"
|
|
bool GetCurrentSystemTheme()
|
|
{
|
|
HKEY hKey;
|
|
DWORD value = 1; // default = light
|
|
DWORD size = sizeof(value);
|
|
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER,
|
|
PERSONALIZATION_REGISTRY_PATH,
|
|
0,
|
|
KEY_READ,
|
|
&hKey) == ERROR_SUCCESS)
|
|
{
|
|
RegQueryValueEx(hKey, L"SystemUsesLightTheme", nullptr, nullptr, reinterpret_cast<LPBYTE>(&value), &size);
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return value == 1; // true = light, false = dark
|
|
}
|
|
|
|
bool GetCurrentAppsTheme()
|
|
{
|
|
HKEY hKey;
|
|
DWORD value = 1;
|
|
DWORD size = sizeof(value);
|
|
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER,
|
|
PERSONALIZATION_REGISTRY_PATH,
|
|
0,
|
|
KEY_READ,
|
|
&hKey) == ERROR_SUCCESS)
|
|
{
|
|
RegQueryValueEx(hKey, L"AppsUseLightTheme", nullptr, nullptr, reinterpret_cast<LPBYTE>(&value), &size);
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return value == 1; // true = light, false = dark
|
|
}
|
|
|
|
bool IsNightLightEnabled()
|
|
{
|
|
HKEY hKey;
|
|
const wchar_t* path = NIGHT_LIGHT_REGISTRY_PATH;
|
|
|
|
if (RegOpenKeyExW(HKEY_CURRENT_USER, path, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
|
|
return false;
|
|
|
|
// RegGetValueW will set size to the size of the data and we expect that to be at least 25 bytes (we need to access bytes 23 and 24)
|
|
DWORD size = 0;
|
|
if (RegGetValueW(hKey, nullptr, L"Data", RRF_RT_REG_BINARY, nullptr, nullptr, &size) != ERROR_SUCCESS || size < 25)
|
|
{
|
|
RegCloseKey(hKey);
|
|
return false;
|
|
}
|
|
|
|
std::vector<BYTE> data(size);
|
|
if (RegGetValueW(hKey, nullptr, L"Data", RRF_RT_REG_BINARY, nullptr, data.data(), &size) != ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hKey);
|
|
return false;
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
return data[23] == 0x10 && data[24] == 0x00;
|
|
} |