/ src / modules / LightSwitch / LightSwitchLib / ThemeHelper.cpp
ThemeHelper.cpp
  1  #include "pch.h"
  2  #include "ThemeHelper.h"
  3  #include <logger/logger.h>
  4  
  5  // Controls changing the themes.
  6  
  7  static void ResetColorPrevalence()
  8  {
  9      HKEY hKey;
 10      if (RegOpenKeyEx(HKEY_CURRENT_USER,
 11                       PERSONALIZATION_REGISTRY_PATH,
 12                       0,
 13                       KEY_SET_VALUE,
 14                       &hKey) == ERROR_SUCCESS)
 15      {
 16          DWORD value = 0; // back to default value
 17          RegSetValueEx(hKey, L"ColorPrevalence", 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
 18          RegCloseKey(hKey);
 19  
 20          SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, reinterpret_cast<LPARAM>(L"ImmersiveColorSet"), SMTO_ABORTIFHUNG, 5000, nullptr);
 21  
 22          SendMessageTimeout(HWND_BROADCAST, WM_THEMECHANGED, 0, 0, SMTO_ABORTIFHUNG, 5000, nullptr);
 23  
 24          SendMessageTimeout(HWND_BROADCAST, WM_DWMCOLORIZATIONCOLORCHANGED, 0, 0, SMTO_ABORTIFHUNG, 5000, nullptr);
 25      }
 26  }
 27  
 28  void SetAppsTheme(bool mode)
 29  {
 30      HKEY hKey;
 31      if (RegOpenKeyEx(HKEY_CURRENT_USER,
 32                       PERSONALIZATION_REGISTRY_PATH,
 33                       0,
 34                       KEY_SET_VALUE,
 35                       &hKey) == ERROR_SUCCESS)
 36      {
 37          DWORD value = mode;
 38          RegSetValueEx(hKey, L"AppsUseLightTheme", 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
 39          RegCloseKey(hKey);
 40  
 41          SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, reinterpret_cast<LPARAM>(L"ImmersiveColorSet"), SMTO_ABORTIFHUNG, 5000, nullptr);
 42  
 43          SendMessageTimeout(HWND_BROADCAST, WM_THEMECHANGED, 0, 0, SMTO_ABORTIFHUNG, 5000, nullptr);
 44      }
 45  }
 46  
 47  void SetSystemTheme(bool mode)
 48  {
 49      HKEY hKey;
 50      if (RegOpenKeyEx(HKEY_CURRENT_USER,
 51                       PERSONALIZATION_REGISTRY_PATH,
 52                       0,
 53                       KEY_SET_VALUE,
 54                       &hKey) == ERROR_SUCCESS)
 55      {
 56          DWORD value = mode;
 57          RegSetValueEx(hKey, L"SystemUsesLightTheme", 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
 58          RegCloseKey(hKey);
 59  
 60          if (mode) // if are changing to light mode 
 61          {
 62              ResetColorPrevalence();
 63              Logger::info(L"[LightSwitchLib] Reset ColorPrevalence to default when switching to light mode.");
 64          }
 65  
 66          SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, reinterpret_cast<LPARAM>(L"ImmersiveColorSet"), SMTO_ABORTIFHUNG, 5000, nullptr);
 67  
 68          SendMessageTimeout(HWND_BROADCAST, WM_THEMECHANGED, 0, 0, SMTO_ABORTIFHUNG, 5000, nullptr);
 69      }
 70  }
 71  
 72  // Can think of this as "is the current theme light?"
 73  bool GetCurrentSystemTheme()
 74  {
 75      HKEY hKey;
 76      DWORD value = 1; // default = light
 77      DWORD size = sizeof(value);
 78  
 79      if (RegOpenKeyEx(HKEY_CURRENT_USER,
 80                       PERSONALIZATION_REGISTRY_PATH,
 81                       0,
 82                       KEY_READ,
 83                       &hKey) == ERROR_SUCCESS)
 84      {
 85          RegQueryValueEx(hKey, L"SystemUsesLightTheme", nullptr, nullptr, reinterpret_cast<LPBYTE>(&value), &size);
 86          RegCloseKey(hKey);
 87      }
 88  
 89      return value == 1; // true = light, false = dark
 90  }
 91  
 92  bool GetCurrentAppsTheme()
 93  {
 94      HKEY hKey;
 95      DWORD value = 1;
 96      DWORD size = sizeof(value);
 97  
 98      if (RegOpenKeyEx(HKEY_CURRENT_USER,
 99                       PERSONALIZATION_REGISTRY_PATH,
100                       0,
101                       KEY_READ,
102                       &hKey) == ERROR_SUCCESS)
103      {
104          RegQueryValueEx(hKey, L"AppsUseLightTheme", nullptr, nullptr, reinterpret_cast<LPBYTE>(&value), &size);
105          RegCloseKey(hKey);
106      }
107  
108      return value == 1; // true = light, false = dark
109  }
110  
111  bool IsNightLightEnabled()
112  {
113      HKEY hKey;
114      const wchar_t* path = NIGHT_LIGHT_REGISTRY_PATH;
115  
116      if (RegOpenKeyExW(HKEY_CURRENT_USER, path, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
117          return false;
118  
119      // 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)
120      DWORD size = 0;
121      if (RegGetValueW(hKey, nullptr, L"Data", RRF_RT_REG_BINARY, nullptr, nullptr, &size) != ERROR_SUCCESS || size < 25)
122      {
123          RegCloseKey(hKey);
124          return false;
125      }
126  
127      std::vector<BYTE> data(size);
128      if (RegGetValueW(hKey, nullptr, L"Data", RRF_RT_REG_BINARY, nullptr, data.data(), &size) != ERROR_SUCCESS)
129      {
130          RegCloseKey(hKey);
131          return false;
132      }
133  
134      RegCloseKey(hKey);
135      return data[23] == 0x10 && data[24] == 0x00;
136  }