diff --git a/PowerToys.slnx b/PowerToys.slnx
index 1884b2d58b..69db025332 100644
--- a/PowerToys.slnx
+++ b/PowerToys.slnx
@@ -640,6 +640,7 @@
+
diff --git a/src/modules/LightSwitch/LightSwitchLib/LightSwitchLib.vcxproj b/src/modules/LightSwitch/LightSwitchLib/LightSwitchLib.vcxproj
new file mode 100644
index 0000000000..dbc97ab86e
--- /dev/null
+++ b/src/modules/LightSwitch/LightSwitchLib/LightSwitchLib.vcxproj
@@ -0,0 +1,123 @@
+
+
+
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Release
+ ARM64
+
+
+
+ 17.0
+ Win32Proj
+ {79267138-2895-4346-9021-21408d65379f}
+ LightSwitchLib
+ 10.0.26100.0
+ LightSwitchLib
+
+
+
+ StaticLibrary
+ true
+ v143
+ Unicode
+
+
+ StaticLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+ StaticLibrary
+ true
+ v143
+ Unicode
+
+
+ StaticLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\..\..\$(Platform)\$(Configuration)\$(MSBuildProjectName)\
+
+
+
+ Level3
+ true
+ _LIB;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+
+ ./;
+ ..\..\..\common;
+ ..\..\..\common\logger;
+ ..\..\..\common\utils;
+ ..\..\..\..\deps\spdlog\include;
+ %(AdditionalIncludeDirectories)
+
+
+
+ Windows
+ true
+
+
+
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+
+ {d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}
+
+
+
+
+
+
+
+
diff --git a/src/modules/LightSwitch/LightSwitchLib/LightSwitchLib.vcxproj.filters b/src/modules/LightSwitch/LightSwitchLib/LightSwitchLib.vcxproj.filters
new file mode 100644
index 0000000000..0792aad8f7
--- /dev/null
+++ b/src/modules/LightSwitch/LightSwitchLib/LightSwitchLib.vcxproj.filters
@@ -0,0 +1,33 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
diff --git a/src/modules/LightSwitch/LightSwitchService/ThemeHelper.cpp b/src/modules/LightSwitch/LightSwitchLib/ThemeHelper.cpp
similarity index 94%
rename from src/modules/LightSwitch/LightSwitchService/ThemeHelper.cpp
rename to src/modules/LightSwitch/LightSwitchLib/ThemeHelper.cpp
index cfa858c636..ccd8ff244f 100644
--- a/src/modules/LightSwitch/LightSwitchService/ThemeHelper.cpp
+++ b/src/modules/LightSwitch/LightSwitchLib/ThemeHelper.cpp
@@ -1,9 +1,6 @@
-#include
-#include
-#include
-#include
+#include "pch.h"
#include "ThemeHelper.h"
-#include
+#include
// Controls changing the themes.
@@ -63,7 +60,7 @@ void SetSystemTheme(bool mode)
if (mode) // if are changing to light mode
{
ResetColorPrevalence();
- Logger::info(L"[LightSwitchService] Reset ColorPrevalence to default when switching to light mode.");
+ Logger::info(L"[LightSwitchLib] Reset ColorPrevalence to default when switching to light mode.");
}
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, reinterpret_cast(L"ImmersiveColorSet"), SMTO_ABORTIFHUNG, 5000, nullptr);
@@ -136,4 +133,4 @@ bool IsNightLightEnabled()
RegCloseKey(hKey);
return data[23] == 0x10 && data[24] == 0x00;
-}
\ No newline at end of file
+}
diff --git a/src/modules/LightSwitch/LightSwitchLib/ThemeHelper.h b/src/modules/LightSwitch/LightSwitchLib/ThemeHelper.h
new file mode 100644
index 0000000000..8720a3b19d
--- /dev/null
+++ b/src/modules/LightSwitch/LightSwitchLib/ThemeHelper.h
@@ -0,0 +1,10 @@
+#pragma once
+
+inline constexpr wchar_t PERSONALIZATION_REGISTRY_PATH[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
+inline constexpr wchar_t NIGHT_LIGHT_REGISTRY_PATH[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\CloudStore\\Store\\DefaultAccount\\Current\\default$windows.data.bluelightreduction.bluelightreductionstate\\windows.data.bluelightreduction.bluelightreductionstate";
+
+void SetSystemTheme(bool isLight);
+void SetAppsTheme(bool isLight);
+bool GetCurrentSystemTheme();
+bool GetCurrentAppsTheme();
+bool IsNightLightEnabled();
diff --git a/src/modules/LightSwitch/LightSwitchLib/pch.cpp b/src/modules/LightSwitch/LightSwitchLib/pch.cpp
new file mode 100644
index 0000000000..1d9f38c57d
--- /dev/null
+++ b/src/modules/LightSwitch/LightSwitchLib/pch.cpp
@@ -0,0 +1 @@
+#include "pch.h"
diff --git a/src/modules/LightSwitch/LightSwitchLib/pch.h b/src/modules/LightSwitch/LightSwitchLib/pch.h
new file mode 100644
index 0000000000..b8d235d9c5
--- /dev/null
+++ b/src/modules/LightSwitch/LightSwitchLib/pch.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#include
+#include
diff --git a/src/modules/LightSwitch/LightSwitchModuleInterface/ExportedFunctions.cpp b/src/modules/LightSwitch/LightSwitchModuleInterface/ExportedFunctions.cpp
new file mode 100644
index 0000000000..d9046c361e
--- /dev/null
+++ b/src/modules/LightSwitch/LightSwitchModuleInterface/ExportedFunctions.cpp
@@ -0,0 +1,22 @@
+#include "pch.h"
+#include "ThemeHelper.h"
+
+extern "C" __declspec(dllexport) void __cdecl LightSwitch_SetSystemTheme(bool isLight)
+{
+ SetSystemTheme(isLight);
+}
+
+extern "C" __declspec(dllexport) void __cdecl LightSwitch_SetAppsTheme(bool isLight)
+{
+ SetAppsTheme(isLight);
+}
+
+extern "C" __declspec(dllexport) bool __cdecl LightSwitch_GetCurrentSystemTheme()
+{
+ return GetCurrentSystemTheme();
+}
+
+extern "C" __declspec(dllexport) bool __cdecl LightSwitch_GetCurrentAppsTheme()
+{
+ return GetCurrentAppsTheme();
+}
diff --git a/src/modules/LightSwitch/LightSwitchModuleInterface/LightSwitchModuleInterface.vcxproj b/src/modules/LightSwitch/LightSwitchModuleInterface/LightSwitchModuleInterface.vcxproj
index 261cfab1e6..a7ef9f21d7 100644
--- a/src/modules/LightSwitch/LightSwitchModuleInterface/LightSwitchModuleInterface.vcxproj
+++ b/src/modules/LightSwitch/LightSwitchModuleInterface/LightSwitchModuleInterface.vcxproj
@@ -166,7 +166,7 @@
- ..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories)
+ ..\LightSwitchLib;..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories)
$(CoreLibraryDependencies);%(AdditionalDependencies);advapi32.lib
@@ -175,11 +175,11 @@
-
+
Create
Create
@@ -190,7 +190,6 @@
pch.h
pch.h
-
@@ -206,6 +205,9 @@
{6955446d-23f7-4023-9bb3-8657f904af99}
+
+ {79267138-2895-4346-9021-21408d65379f}
+
diff --git a/src/modules/LightSwitch/LightSwitchModuleInterface/ThemeHelper.cpp b/src/modules/LightSwitch/LightSwitchModuleInterface/ThemeHelper.cpp
deleted file mode 100644
index 3593a5bbae..0000000000
--- a/src/modules/LightSwitch/LightSwitchModuleInterface/ThemeHelper.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#include "pch.h"
-#include
-#include "ThemeHelper.h"
-
-// Controls changing the themes.
-static void ResetColorPrevalence()
-{
- HKEY hKey;
- if (RegOpenKeyEx(HKEY_CURRENT_USER,
- L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
- 0,
- KEY_SET_VALUE,
- &hKey) == ERROR_SUCCESS)
- {
- DWORD value = 0; // back to default value
- RegSetValueEx(hKey, L"ColorPrevalence", 0, REG_DWORD, reinterpret_cast(&value), sizeof(value));
- RegCloseKey(hKey);
-
- SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, reinterpret_cast(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,
- L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
- 0,
- KEY_SET_VALUE,
- &hKey) == ERROR_SUCCESS)
- {
- DWORD value = mode;
- RegSetValueEx(hKey, L"AppsUseLightTheme", 0, REG_DWORD, reinterpret_cast(&value), sizeof(value));
- RegCloseKey(hKey);
-
- SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, reinterpret_cast(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,
- L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
- 0,
- KEY_SET_VALUE,
- &hKey) == ERROR_SUCCESS)
- {
- DWORD value = mode;
- RegSetValueEx(hKey, L"SystemUsesLightTheme", 0, REG_DWORD, reinterpret_cast(&value), sizeof(value));
- RegCloseKey(hKey);
-
- if (mode) // if are changing to light mode
- {
- ResetColorPrevalence();
- }
-
- SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, reinterpret_cast(L"ImmersiveColorSet"), SMTO_ABORTIFHUNG, 5000, nullptr);
-
- SendMessageTimeout(HWND_BROADCAST, WM_THEMECHANGED, 0, 0, SMTO_ABORTIFHUNG, 5000, nullptr);
- }
-}
-
-bool GetCurrentSystemTheme()
-{
- HKEY hKey;
- DWORD value = 1; // default = light
- DWORD size = sizeof(value);
-
- if (RegOpenKeyEx(HKEY_CURRENT_USER,
- L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
- 0,
- KEY_READ,
- &hKey) == ERROR_SUCCESS)
- {
- RegQueryValueEx(hKey, L"SystemUsesLightTheme", nullptr, nullptr, reinterpret_cast(&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,
- L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
- 0,
- KEY_READ,
- &hKey) == ERROR_SUCCESS)
- {
- RegQueryValueEx(hKey, L"AppsUseLightTheme", nullptr, nullptr, reinterpret_cast(&value), &size);
- RegCloseKey(hKey);
- }
-
- return value == 1; // true = light, false = dark
-}
diff --git a/src/modules/LightSwitch/LightSwitchModuleInterface/ThemeHelper.h b/src/modules/LightSwitch/LightSwitchModuleInterface/ThemeHelper.h
deleted file mode 100644
index 5985fd95c8..0000000000
--- a/src/modules/LightSwitch/LightSwitchModuleInterface/ThemeHelper.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#pragma once
-void SetSystemTheme(bool dark);
-void SetAppsTheme(bool dark);
-bool GetCurrentSystemTheme();
-bool GetCurrentAppsTheme();
diff --git a/src/modules/LightSwitch/LightSwitchService/LightSwitchService.vcxproj b/src/modules/LightSwitch/LightSwitchService/LightSwitchService.vcxproj
index e1c8052de6..0aff50ccab 100644
--- a/src/modules/LightSwitch/LightSwitchService/LightSwitchService.vcxproj
+++ b/src/modules/LightSwitch/LightSwitchService/LightSwitchService.vcxproj
@@ -55,6 +55,7 @@
%(PreprocessorDefinitions)
./../;
+ ..\LightSwitchLib;
..\..\..\common;
..\..\..\common\logger;
..\..\..\common\utils;
@@ -78,7 +79,6 @@
-
@@ -92,7 +92,6 @@
-
@@ -109,6 +108,9 @@
{8f021b46-362b-485c-bfba-ccf83e820cbd}
+
+ {79267138-2895-4346-9021-21408d65379f}
+
@@ -116,4 +118,4 @@
-
\ No newline at end of file
+
diff --git a/src/modules/LightSwitch/LightSwitchService/SettingsConstants.h b/src/modules/LightSwitch/LightSwitchService/SettingsConstants.h
index 8015c9b3e6..1ec1f36340 100644
--- a/src/modules/LightSwitch/LightSwitchService/SettingsConstants.h
+++ b/src/modules/LightSwitch/LightSwitchService/SettingsConstants.h
@@ -12,6 +12,3 @@ enum class SettingId
ChangeSystem,
ChangeApps
};
-
-constexpr wchar_t PERSONALIZATION_REGISTRY_PATH[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
-constexpr wchar_t NIGHT_LIGHT_REGISTRY_PATH[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\CloudStore\\Store\\DefaultAccount\\Current\\default$windows.data.bluelightreduction.bluelightreductionstate\\windows.data.bluelightreduction.bluelightreductionstate";
diff --git a/src/modules/LightSwitch/LightSwitchService/ThemeHelper.h b/src/modules/LightSwitch/LightSwitchService/ThemeHelper.h
deleted file mode 100644
index e8d45e9c2a..0000000000
--- a/src/modules/LightSwitch/LightSwitchService/ThemeHelper.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#pragma once
-void SetSystemTheme(bool dark);
-void SetAppsTheme(bool dark);
-bool GetCurrentSystemTheme();
-bool GetCurrentAppsTheme();
-bool IsNightLightEnabled();
\ No newline at end of file
diff --git a/src/modules/LightSwitch/Tests/LightSwitch.UITests/LightSwitch.UITests.csproj b/src/modules/LightSwitch/Tests/LightSwitch.UITests/LightSwitch.UITests.csproj
index 9770255af6..f457025c0e 100644
--- a/src/modules/LightSwitch/Tests/LightSwitch.UITests/LightSwitch.UITests.csproj
+++ b/src/modules/LightSwitch/Tests/LightSwitch.UITests/LightSwitch.UITests.csproj
@@ -19,4 +19,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/modules/LightSwitch/Tests/LightSwitch.UITests/TestHelper.cs b/src/modules/LightSwitch/Tests/LightSwitch.UITests/TestHelper.cs
index 37041b4b2d..d7748fc2f5 100644
--- a/src/modules/LightSwitch/Tests/LightSwitch.UITests/TestHelper.cs
+++ b/src/modules/LightSwitch/Tests/LightSwitch.UITests/TestHelper.cs
@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.PowerToys.UITest;
@@ -17,6 +18,20 @@ namespace LightSwitch.UITests
{
private static readonly string[] ShortcutSeparators = { " + ", "+", " " };
+ [DllImport("PowerToys.LightSwitchModuleInterface.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern void LightSwitch_SetSystemTheme(bool isLight);
+
+ [DllImport("PowerToys.LightSwitchModuleInterface.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern void LightSwitch_SetAppsTheme(bool isLight);
+
+ [DllImport("PowerToys.LightSwitchModuleInterface.dll", CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs(UnmanagedType.I1)]
+ private static extern bool LightSwitch_GetCurrentSystemTheme();
+
+ [DllImport("PowerToys.LightSwitchModuleInterface.dll", CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs(UnmanagedType.I1)]
+ private static extern bool LightSwitch_GetCurrentAppsTheme();
+
///
/// Performs common test initialization: navigate to settings, enable toggle, verify shortcut
///
@@ -127,8 +142,7 @@ namespace LightSwitch.UITests
/// The test base instance
public static void CleanupTest(UITestBase testBase)
{
- // TODO: Make sure the task kills?
- // CloseLightSwitch(testBase);
+ CloseLightSwitch(testBase);
// Ensure we're attached to settings after cleanup
try
@@ -141,6 +155,51 @@ namespace LightSwitch.UITests
}
}
+ ///
+ /// Switch to white/light theme for both system and apps
+ ///
+ /// The test base instance
+ public static void CloseLightSwitch(UITestBase testBase)
+ {
+ // Kill LightSwitch process before setting themes
+ KillLightSwitchProcess();
+
+ // Set both themes to light (white)
+ SetSystemTheme(true);
+ SetAppsTheme(true);
+ }
+
+ ///
+ /// Kill the LightSwitch service process if it's running
+ ///
+ private static void KillLightSwitchProcess()
+ {
+ try
+ {
+ var processes = System.Diagnostics.Process.GetProcessesByName("PowerToys.LightSwitchService");
+ foreach (var process in processes)
+ {
+ try
+ {
+ process.Kill();
+ process.WaitForExit(2000);
+ }
+ catch
+ {
+ // Ignore errors killing individual processes
+ }
+ finally
+ {
+ process.Dispose();
+ }
+ }
+ }
+ catch
+ {
+ // Ignore errors enumerating processes
+ }
+ }
+
///
/// Perform a update time test operation
///
@@ -408,24 +467,22 @@ namespace LightSwitch.UITests
/* Helpers */
private static int GetSystemTheme()
{
- using var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize");
- if (key is null)
- {
- return 1;
- }
-
- return (int)key.GetValue("SystemUsesLightTheme", 1);
+ return LightSwitch_GetCurrentSystemTheme() ? 1 : 0;
}
private static int GetAppsTheme()
{
- using var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize");
- if (key is null)
- {
- return 1;
- }
+ return LightSwitch_GetCurrentAppsTheme() ? 1 : 0;
+ }
- return (int)key.GetValue("AppsUseLightTheme", 1);
+ private static void SetSystemTheme(bool isLight)
+ {
+ LightSwitch_SetSystemTheme(isLight);
+ }
+
+ private static void SetAppsTheme(bool isLight)
+ {
+ LightSwitch_SetAppsTheme(isLight);
}
private static string GetHelpTextValue(string helpText, string key)