mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 19:57:57 +01:00
[Light Switch] Light Switch should detect changes in Windows Settings and treat as manual override (same as using shortcut) (#42882)
<!-- 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 This PR ensures that Light Switch detects changes to app/system theme from Windows Settings. This PR also introduces new behavior where switching the schedule will cause an instant update to the theme if necessary. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #42878 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **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
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include "ThemeScheduler.h"
|
#include "ThemeScheduler.h"
|
||||||
#include "ThemeHelper.h"
|
#include "ThemeHelper.h"
|
||||||
@@ -11,11 +11,12 @@
|
|||||||
#include <logger/logger_settings.h>
|
#include <logger/logger_settings.h>
|
||||||
#include <logger/logger.h>
|
#include <logger/logger.h>
|
||||||
#include <utils/logger_helper.h>
|
#include <utils/logger_helper.h>
|
||||||
|
#include <LightSwitchServiceObserver.h>
|
||||||
|
|
||||||
SERVICE_STATUS g_ServiceStatus = {};
|
SERVICE_STATUS g_ServiceStatus = {};
|
||||||
SERVICE_STATUS_HANDLE g_StatusHandle = nullptr;
|
SERVICE_STATUS_HANDLE g_StatusHandle = nullptr;
|
||||||
HANDLE g_ServiceStopEvent = nullptr;
|
HANDLE g_ServiceStopEvent = nullptr;
|
||||||
static int g_lastUpdatedDay = -1;
|
extern int g_lastUpdatedDay = -1;
|
||||||
static ScheduleMode prevMode = ScheduleMode::Off;
|
static ScheduleMode prevMode = ScheduleMode::Off;
|
||||||
static std::wstring prevLat, prevLon;
|
static std::wstring prevLat, prevLon;
|
||||||
|
|
||||||
@@ -161,25 +162,18 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
|
|||||||
Logger::info(L"[LightSwitchService] Worker thread starting...");
|
Logger::info(L"[LightSwitchService] Worker thread starting...");
|
||||||
Logger::info(L"[LightSwitchService] Parent PID: {}", parentPid);
|
Logger::info(L"[LightSwitchService] Parent PID: {}", parentPid);
|
||||||
|
|
||||||
// Initialize settings system
|
|
||||||
LightSwitchSettings::instance().InitFileWatcher();
|
LightSwitchSettings::instance().InitFileWatcher();
|
||||||
|
|
||||||
// Open the manual override event created by the module interface
|
LightSwitchServiceObserver observer({ SettingId::LightTime,
|
||||||
|
SettingId::DarkTime,
|
||||||
|
SettingId::ScheduleMode,
|
||||||
|
SettingId::Sunrise_Offset,
|
||||||
|
SettingId::Sunset_Offset });
|
||||||
|
|
||||||
HANDLE hManualOverride = OpenEventW(SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE, L"POWERTOYS_LIGHTSWITCH_MANUAL_OVERRIDE");
|
HANDLE hManualOverride = OpenEventW(SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE, L"POWERTOYS_LIGHTSWITCH_MANUAL_OVERRIDE");
|
||||||
|
|
||||||
auto applyTheme = [](int nowMinutes, int lightMinutes, int darkMinutes, const auto& settings) {
|
auto applyTheme = [](int nowMinutes, int lightMinutes, int darkMinutes, const auto& settings) {
|
||||||
bool isLightActive = false;
|
bool isLightActive = (lightMinutes < darkMinutes) ? (nowMinutes >= lightMinutes && nowMinutes < darkMinutes) : (nowMinutes >= lightMinutes || nowMinutes < darkMinutes);
|
||||||
|
|
||||||
if (lightMinutes < darkMinutes)
|
|
||||||
{
|
|
||||||
// Normal case: sunrise < sunset
|
|
||||||
isLightActive = (nowMinutes >= lightMinutes && nowMinutes < darkMinutes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Wraparound case: e.g. light at 21:00, dark at 06:00
|
|
||||||
isLightActive = (nowMinutes >= lightMinutes || nowMinutes < darkMinutes);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isSystemCurrentlyLight = GetCurrentSystemTheme();
|
bool isSystemCurrentlyLight = GetCurrentSystemTheme();
|
||||||
bool isAppsCurrentlyLight = GetCurrentAppsTheme();
|
bool isAppsCurrentlyLight = GetCurrentAppsTheme();
|
||||||
@@ -212,33 +206,155 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Initial settings load ---
|
|
||||||
LightSwitchSettings::instance().LoadSettings();
|
LightSwitchSettings::instance().LoadSettings();
|
||||||
auto& settings = LightSwitchSettings::instance().settings();
|
auto& settings = LightSwitchSettings::instance().settings();
|
||||||
|
|
||||||
// --- Initial theme application (if schedule enabled) ---
|
|
||||||
if (settings.scheduleMode != ScheduleMode::Off)
|
|
||||||
{
|
|
||||||
SYSTEMTIME st;
|
SYSTEMTIME st;
|
||||||
GetLocalTime(&st);
|
GetLocalTime(&st);
|
||||||
int nowMinutes = st.wHour * 60 + st.wMinute;
|
int nowMinutes = st.wHour * 60 + st.wMinute;
|
||||||
applyTheme(nowMinutes, settings.lightTime + settings.sunrise_offset, settings.darkTime + settings.sunset_offset, settings);
|
|
||||||
|
if (settings.scheduleMode != ScheduleMode::Off)
|
||||||
|
{
|
||||||
|
applyTheme(nowMinutes,
|
||||||
|
settings.lightTime + settings.sunrise_offset,
|
||||||
|
settings.darkTime + settings.sunset_offset,
|
||||||
|
settings);
|
||||||
|
Logger::trace(L"[LightSwitchService] Initialized g_lastUpdatedDay = {}", g_lastUpdatedDay);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logger::info(L"[LightSwitchService] Schedule mode is OFF - ticker suspended, waiting for manual action or mode change.");
|
Logger::info(L"[LightSwitchService] Schedule mode is OFF - ticker suspended, waiting for manual action or mode change.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Main loop ---
|
g_lastUpdatedDay = st.wDay;
|
||||||
|
ULONGLONG lastSettingsReload = 0;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
HANDLE waits[2] = { g_ServiceStopEvent, hParent };
|
HANDLE waits[2] = { g_ServiceStopEvent, hParent };
|
||||||
DWORD count = hParent ? 2 : 1;
|
DWORD count = hParent ? 2 : 1;
|
||||||
|
bool skipRest = false;
|
||||||
|
|
||||||
LightSwitchSettings::instance().LoadSettings();
|
|
||||||
const auto& settings = LightSwitchSettings::instance().settings();
|
const auto& settings = LightSwitchSettings::instance().settings();
|
||||||
|
|
||||||
// Check for changes in schedule mode or coordinates
|
bool scheduleJustEnabled = (prevMode == ScheduleMode::Off && settings.scheduleMode != ScheduleMode::Off);
|
||||||
|
prevMode = settings.scheduleMode;
|
||||||
|
|
||||||
|
// ─── Handle "Schedule Off" Mode ─────────────────────────────────────────────
|
||||||
|
if (settings.scheduleMode == ScheduleMode::Off)
|
||||||
|
{
|
||||||
|
Logger::info(L"[LightSwitchService] Schedule mode OFF - suspending scheduler but keeping service alive.");
|
||||||
|
|
||||||
|
if (!hManualOverride)
|
||||||
|
hManualOverride = OpenEventW(SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE, L"POWERTOYS_LIGHTSWITCH_MANUAL_OVERRIDE");
|
||||||
|
|
||||||
|
HANDLE waitsOff[4];
|
||||||
|
DWORD countOff = 0;
|
||||||
|
waitsOff[countOff++] = g_ServiceStopEvent;
|
||||||
|
if (hParent)
|
||||||
|
waitsOff[countOff++] = hParent;
|
||||||
|
if (hManualOverride)
|
||||||
|
waitsOff[countOff++] = hManualOverride;
|
||||||
|
waitsOff[countOff++] = LightSwitchSettings::instance().GetSettingsChangedEvent();
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
DWORD wait = WaitForMultipleObjects(countOff, waitsOff, FALSE, INFINITE);
|
||||||
|
|
||||||
|
if (wait == WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
Logger::info(L"[LightSwitchService] Stop event triggered - exiting worker loop.");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (hParent && wait == WAIT_OBJECT_0 + 1)
|
||||||
|
{
|
||||||
|
Logger::info(L"[LightSwitchService] Parent exited - stopping service.");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wait == WAIT_OBJECT_0 + (hParent ? 2 : 1))
|
||||||
|
{
|
||||||
|
Logger::info(L"[LightSwitchService] Manual override received while schedule OFF.");
|
||||||
|
ResetEvent(hManualOverride);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wait == WAIT_OBJECT_0 + (hParent ? 3 : 2))
|
||||||
|
{
|
||||||
|
Logger::trace(L"[LightSwitchService] Settings change event triggered, reloading settings...");
|
||||||
|
ResetEvent(LightSwitchSettings::instance().GetSettingsChangedEvent());
|
||||||
|
LightSwitchSettings::instance().LoadSettings();
|
||||||
|
const auto& newSettings = LightSwitchSettings::instance().settings();
|
||||||
|
lastSettingsReload = GetTickCount64();
|
||||||
|
|
||||||
|
if (newSettings.scheduleMode != ScheduleMode::Off)
|
||||||
|
{
|
||||||
|
Logger::info(L"[LightSwitchService] Schedule re-enabled, resuming normal loop.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Normal Schedule Loop ───────────────────────────────────────────────────
|
||||||
|
ULONGLONG nowTick = GetTickCount64();
|
||||||
|
bool recentSettingsReload = (nowTick - lastSettingsReload < 5000);
|
||||||
|
|
||||||
|
if (g_lastUpdatedDay != -1)
|
||||||
|
{
|
||||||
|
bool manualOverrideActive = (hManualOverride && WaitForSingleObject(hManualOverride, 0) == WAIT_OBJECT_0);
|
||||||
|
|
||||||
|
if (settings.scheduleMode != ScheduleMode::Off && !recentSettingsReload && !scheduleJustEnabled)
|
||||||
|
{
|
||||||
|
Logger::debug(L"[LightSwitchService] Checking if manual override is active...");
|
||||||
|
bool manualOverrideActive = (hManualOverride && WaitForSingleObject(hManualOverride, 0) == WAIT_OBJECT_0);
|
||||||
|
Logger::debug(L"[LightSwitchService] Manual override active = {}", manualOverrideActive);
|
||||||
|
|
||||||
|
if (!manualOverrideActive)
|
||||||
|
{
|
||||||
|
bool currentSystemTheme = GetCurrentSystemTheme();
|
||||||
|
bool currentAppsTheme = GetCurrentAppsTheme();
|
||||||
|
|
||||||
|
SYSTEMTIME st;
|
||||||
|
GetLocalTime(&st);
|
||||||
|
int nowMinutes = st.wHour * 60 + st.wMinute;
|
||||||
|
|
||||||
|
bool shouldBeLight = (settings.lightTime < settings.darkTime) ? (nowMinutes >= settings.lightTime && nowMinutes < settings.darkTime) : (nowMinutes >= settings.lightTime || nowMinutes < settings.darkTime);
|
||||||
|
|
||||||
|
Logger::debug(L"[LightSwitchService] shouldBeLight = {}", shouldBeLight);
|
||||||
|
|
||||||
|
if ((settings.changeSystem && (currentSystemTheme != shouldBeLight)) ||
|
||||||
|
(settings.changeApps && (currentAppsTheme != shouldBeLight)))
|
||||||
|
{
|
||||||
|
Logger::debug(L"[LightSwitchService] External theme change detected - enabling manual override");
|
||||||
|
|
||||||
|
if (!hManualOverride)
|
||||||
|
{
|
||||||
|
hManualOverride = OpenEventW(SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE, L"POWERTOYS_LIGHTSWITCH_MANUAL_OVERRIDE");
|
||||||
|
if (!hManualOverride)
|
||||||
|
hManualOverride = CreateEventW(nullptr, TRUE, FALSE, L"POWERTOYS_LIGHTSWITCH_MANUAL_OVERRIDE");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hManualOverride)
|
||||||
|
{
|
||||||
|
SetEvent(hManualOverride);
|
||||||
|
Logger::info(L"[LightSwitchService] Detected manual theme change outside of LightSwitch. Triggering manual override.");
|
||||||
|
skipRest = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger::debug(L"[LightSwitchService] Skipping external-change detection (schedule off, recent reload, or just enabled).");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Apply Schedule Logic ───────────────────────────────────────────────────
|
||||||
|
if (!skipRest)
|
||||||
|
{
|
||||||
bool modeChangedToSunset = (prevMode != settings.scheduleMode &&
|
bool modeChangedToSunset = (prevMode != settings.scheduleMode &&
|
||||||
settings.scheduleMode == ScheduleMode::SunsetToSunrise);
|
settings.scheduleMode == ScheduleMode::SunsetToSunrise);
|
||||||
bool coordsChanged = (prevLat != settings.latitude || prevLon != settings.longitude);
|
bool coordsChanged = (prevLat != settings.latitude || prevLon != settings.longitude);
|
||||||
@@ -255,75 +371,10 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
|
|||||||
prevLon = settings.longitude;
|
prevLon = settings.longitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If schedule is off, idle but keep watching settings and manual override
|
|
||||||
if (settings.scheduleMode == ScheduleMode::Off)
|
|
||||||
{
|
|
||||||
Logger::info(L"[LightSwitchService] Schedule mode OFF - suspending scheduler but keeping service alive.");
|
|
||||||
|
|
||||||
if (!hManualOverride)
|
|
||||||
{
|
|
||||||
hManualOverride = OpenEventW(SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE, L"POWERTOYS_LIGHTSWITCH_MANUAL_OVERRIDE");
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE waits[4];
|
|
||||||
DWORD count = 0;
|
|
||||||
waits[count++] = g_ServiceStopEvent;
|
|
||||||
if (hParent)
|
|
||||||
waits[count++] = hParent;
|
|
||||||
if (hManualOverride)
|
|
||||||
waits[count++] = hManualOverride;
|
|
||||||
waits[count++] = LightSwitchSettings::instance().GetSettingsChangedEvent();
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
DWORD wait = WaitForMultipleObjects(count, waits, FALSE, INFINITE);
|
|
||||||
|
|
||||||
// --- Handle exit signals ---
|
|
||||||
if (wait == WAIT_OBJECT_0) // stop event
|
|
||||||
{
|
|
||||||
Logger::info(L"[LightSwitchService] Stop event triggered - exiting worker loop.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (hParent && wait == WAIT_OBJECT_0 + 1)
|
|
||||||
{
|
|
||||||
Logger::info(L"[LightSwitchService] Parent exited - stopping service.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Manual override triggered ---
|
|
||||||
if (wait == WAIT_OBJECT_0 + (hParent ? 2 : 1))
|
|
||||||
{
|
|
||||||
Logger::info(L"[LightSwitchService] Manual override received while schedule OFF.");
|
|
||||||
ResetEvent(hManualOverride);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Settings file changed ---
|
|
||||||
if (wait == WAIT_OBJECT_0 + (hParent ? 3 : 2))
|
|
||||||
{
|
|
||||||
Logger::trace(L"[LightSwitchService] Settings change event triggered, reloading settings...");
|
|
||||||
|
|
||||||
ResetEvent(LightSwitchSettings::instance().GetSettingsChangedEvent());
|
|
||||||
|
|
||||||
LightSwitchSettings::instance().LoadSettings();
|
|
||||||
const auto& newSettings = LightSwitchSettings::instance().settings();
|
|
||||||
|
|
||||||
if (newSettings.scheduleMode != ScheduleMode::Off)
|
|
||||||
{
|
|
||||||
Logger::info(L"[LightSwitchService] Schedule re-enabled, resuming normal loop.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// --- When schedule is active, run once per minute ---
|
|
||||||
SYSTEMTIME st;
|
SYSTEMTIME st;
|
||||||
GetLocalTime(&st);
|
GetLocalTime(&st);
|
||||||
int nowMinutes = st.wHour * 60 + st.wMinute;
|
int nowMinutes = st.wHour * 60 + st.wMinute;
|
||||||
|
|
||||||
// Refresh suntimes at day boundary
|
|
||||||
if ((g_lastUpdatedDay != st.wDay) && (settings.scheduleMode == ScheduleMode::SunsetToSunrise))
|
if ((g_lastUpdatedDay != st.wDay) && (settings.scheduleMode == ScheduleMode::SunsetToSunrise))
|
||||||
{
|
{
|
||||||
update_sun_times(settings);
|
update_sun_times(settings);
|
||||||
@@ -331,7 +382,6 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
|
|||||||
Logger::info(L"[LightSwitchService] Recalculated sun times at new day boundary.");
|
Logger::info(L"[LightSwitchService] Recalculated sun times at new day boundary.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Have to do this again in case settings got updated in the refresh suntimes chunk
|
|
||||||
LightSwitchSettings::instance().LoadSettings();
|
LightSwitchSettings::instance().LoadSettings();
|
||||||
const auto& currentSettings = LightSwitchSettings::instance().settings();
|
const auto& currentSettings = LightSwitchSettings::instance().settings();
|
||||||
|
|
||||||
@@ -347,12 +397,9 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
|
|||||||
static_cast<int>(currentSettings.scheduleMode));
|
static_cast<int>(currentSettings.scheduleMode));
|
||||||
Logger::info(msg);
|
Logger::info(msg);
|
||||||
|
|
||||||
// --- Manual override check ---
|
|
||||||
bool manualOverrideActive = false;
|
bool manualOverrideActive = false;
|
||||||
if (hManualOverride)
|
if (hManualOverride)
|
||||||
{
|
|
||||||
manualOverrideActive = (WaitForSingleObject(hManualOverride, 0) == WAIT_OBJECT_0);
|
manualOverrideActive = (WaitForSingleObject(hManualOverride, 0) == WAIT_OBJECT_0);
|
||||||
}
|
|
||||||
|
|
||||||
if (manualOverrideActive)
|
if (manualOverrideActive)
|
||||||
{
|
{
|
||||||
@@ -365,13 +412,19 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logger::info(L"[LightSwitchService] Skipping schedule due to manual override");
|
Logger::info(L"[LightSwitchService] Skipping schedule due to manual override");
|
||||||
goto sleep_until_next_minute;
|
skipRest = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applyTheme(nowMinutes, currentSettings.lightTime + currentSettings.sunrise_offset, currentSettings.darkTime + currentSettings.sunset_offset, currentSettings);
|
if (!skipRest)
|
||||||
|
applyTheme(nowMinutes,
|
||||||
|
currentSettings.lightTime + currentSettings.sunrise_offset,
|
||||||
|
currentSettings.darkTime + currentSettings.sunset_offset,
|
||||||
|
currentSettings);
|
||||||
|
}
|
||||||
|
|
||||||
sleep_until_next_minute:
|
// ─── Wait For Next Minute Tick Or Stop Event ────────────────────────────────
|
||||||
|
SYSTEMTIME st;
|
||||||
GetLocalTime(&st);
|
GetLocalTime(&st);
|
||||||
int msToNextMinute = (60 - st.wSecond) * 1000 - st.wMilliseconds;
|
int msToNextMinute = (60 - st.wSecond) * 1000 - st.wMilliseconds;
|
||||||
if (msToNextMinute < 50)
|
if (msToNextMinute < 50)
|
||||||
@@ -390,6 +443,7 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
if (hManualOverride)
|
if (hManualOverride)
|
||||||
CloseHandle(hManualOverride);
|
CloseHandle(hManualOverride);
|
||||||
if (hParent)
|
if (hParent)
|
||||||
@@ -398,6 +452,53 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApplyThemeNow()
|
||||||
|
{
|
||||||
|
LightSwitchSettings::instance().LoadSettings();
|
||||||
|
const auto& settings = LightSwitchSettings::instance().settings();
|
||||||
|
|
||||||
|
SYSTEMTIME st;
|
||||||
|
GetLocalTime(&st);
|
||||||
|
int nowMinutes = st.wHour * 60 + st.wMinute;
|
||||||
|
|
||||||
|
bool shouldBeLight = false;
|
||||||
|
if (settings.lightTime < settings.darkTime)
|
||||||
|
shouldBeLight = (nowMinutes >= settings.lightTime && nowMinutes < settings.darkTime);
|
||||||
|
else
|
||||||
|
shouldBeLight = (nowMinutes >= settings.lightTime || nowMinutes < settings.darkTime);
|
||||||
|
|
||||||
|
bool isSystemCurrentlyLight = GetCurrentSystemTheme();
|
||||||
|
bool isAppsCurrentlyLight = GetCurrentAppsTheme();
|
||||||
|
|
||||||
|
Logger::info(L"[LightSwitchService] Applying (if needed) theme immediately due to schedule change.");
|
||||||
|
|
||||||
|
if (shouldBeLight)
|
||||||
|
{
|
||||||
|
if (settings.changeSystem && !isSystemCurrentlyLight)
|
||||||
|
{
|
||||||
|
SetSystemTheme(true);
|
||||||
|
Logger::info(L"[LightSwitchService] Changing system theme to light mode.");
|
||||||
|
}
|
||||||
|
if (settings.changeApps && !isAppsCurrentlyLight)
|
||||||
|
{
|
||||||
|
SetAppsTheme(true);
|
||||||
|
Logger::info(L"[LightSwitchService] Changing apps theme to light mode.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (settings.changeSystem && isSystemCurrentlyLight)
|
||||||
|
{
|
||||||
|
SetSystemTheme(false);
|
||||||
|
Logger::info(L"[LightSwitchService] Changing system theme to dark mode.");
|
||||||
|
}
|
||||||
|
if (settings.changeApps && isAppsCurrentlyLight)
|
||||||
|
{
|
||||||
|
SetAppsTheme(false);
|
||||||
|
Logger::info(L"[LightSwitchService] Changing apps theme to dark mode.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int APIENTRY wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
|
int APIENTRY wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -74,6 +74,7 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="LightSwitchService.cpp" />
|
<ClCompile Include="LightSwitchService.cpp" />
|
||||||
|
<ClCompile Include="LightSwitchServiceObserver.cpp" />
|
||||||
<ClCompile Include="LightSwitchSettings.cpp" />
|
<ClCompile Include="LightSwitchSettings.cpp" />
|
||||||
<ClCompile Include="SettingsConstants.cpp" />
|
<ClCompile Include="SettingsConstants.cpp" />
|
||||||
<ClCompile Include="ThemeHelper.cpp" />
|
<ClCompile Include="ThemeHelper.cpp" />
|
||||||
@@ -84,6 +85,7 @@
|
|||||||
<ResourceCompile Include="LightSwitchService.rc" />
|
<ResourceCompile Include="LightSwitchService.rc" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="LightSwitchServiceObserver.h" />
|
||||||
<ClInclude Include="LightSwitchSettings.h" />
|
<ClInclude Include="LightSwitchSettings.h" />
|
||||||
<ClInclude Include="SettingsConstants.h" />
|
<ClInclude Include="SettingsConstants.h" />
|
||||||
<ClInclude Include="SettingsObserver.h" />
|
<ClInclude Include="SettingsObserver.h" />
|
||||||
|
|||||||
@@ -33,6 +33,9 @@
|
|||||||
<ClCompile Include="WinHookEventIDs.cpp">
|
<ClCompile Include="WinHookEventIDs.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="LightSwitchServiceObserver.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="ThemeScheduler.h">
|
<ClInclude Include="ThemeScheduler.h">
|
||||||
@@ -53,6 +56,9 @@
|
|||||||
<ClInclude Include="WinHookEventIDs.h">
|
<ClInclude Include="WinHookEventIDs.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="LightSwitchServiceObserver.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
|
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#include "LightSwitchServiceObserver.h"
|
||||||
|
#include <logger.h>
|
||||||
|
#include "LightSwitchSettings.h"
|
||||||
|
|
||||||
|
// These are defined elsewhere in your service module (ServiceWorkerThread.cpp)
|
||||||
|
extern int g_lastUpdatedDay;
|
||||||
|
void ApplyThemeNow();
|
||||||
|
|
||||||
|
void LightSwitchServiceObserver::SettingsUpdate(SettingId id)
|
||||||
|
{
|
||||||
|
Logger::info(L"[LightSwitchService] Setting changed: {}", static_cast<int>(id));
|
||||||
|
g_lastUpdatedDay = -1;
|
||||||
|
ApplyThemeNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LightSwitchServiceObserver::WantsToBeNotified(SettingId id) const noexcept
|
||||||
|
{
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case SettingId::LightTime:
|
||||||
|
case SettingId::DarkTime:
|
||||||
|
case SettingId::ScheduleMode:
|
||||||
|
case SettingId::Sunrise_Offset:
|
||||||
|
case SettingId::Sunset_Offset:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SettingsObserver.h"
|
||||||
|
|
||||||
|
// The LightSwitchServiceObserver reacts when LightSwitchSettings changes.
|
||||||
|
class LightSwitchServiceObserver : public SettingsObserver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit LightSwitchServiceObserver(std::unordered_set<SettingId> observedSettings) :
|
||||||
|
SettingsObserver(std::move(observedSettings))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsUpdate(SettingId id) override;
|
||||||
|
bool WantsToBeNotified(SettingId id) const noexcept override;
|
||||||
|
};
|
||||||
@@ -39,6 +39,7 @@ void LightSwitchSettings::InitFileWatcher()
|
|||||||
GetSettingsFileName(),
|
GetSettingsFileName(),
|
||||||
[this]() {
|
[this]() {
|
||||||
Logger::info(L"[LightSwitchSettings] Settings file changed, signaling event.");
|
Logger::info(L"[LightSwitchSettings] Settings file changed, signaling event.");
|
||||||
|
LoadSettings();
|
||||||
SetEvent(m_settingsChangedEvent);
|
SetEvent(m_settingsChangedEvent);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -65,6 +66,11 @@ void LightSwitchSettings::NotifyObservers(SettingId id) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HANDLE LightSwitchSettings::GetSettingsChangedEvent() const
|
||||||
|
{
|
||||||
|
return m_settingsChangedEvent;
|
||||||
|
}
|
||||||
|
|
||||||
void LightSwitchSettings::LoadSettings()
|
void LightSwitchSettings::LoadSettings()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ public:
|
|||||||
|
|
||||||
void LoadSettings();
|
void LoadSettings();
|
||||||
|
|
||||||
HANDLE GetSettingsChangedEvent() const { return m_settingsChangedEvent; }
|
HANDLE GetSettingsChangedEvent() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LightSwitchSettings();
|
LightSwitchSettings();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include "SettingsConstants.h"
|
#include "SettingsConstants.h"
|
||||||
|
#include "LightSwitchSettings.h"
|
||||||
|
|
||||||
class LightSwitchSettings;
|
class LightSwitchSettings;
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ public:
|
|||||||
// Override this in your class to respond to updates
|
// Override this in your class to respond to updates
|
||||||
virtual void SettingsUpdate(SettingId type) {}
|
virtual void SettingsUpdate(SettingId type) {}
|
||||||
|
|
||||||
bool WantsToBeNotified(SettingId type) const noexcept
|
virtual bool WantsToBeNotified(SettingId type) const noexcept
|
||||||
{
|
{
|
||||||
return m_observedSettings.contains(type);
|
return m_observedSettings.contains(type);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user