Browse Source

feat: detect high contrast color mode (#15493)

* feat: add event and method to detect high contrast color mode

* docs: add docs for isHighContrastColorScheme and high-contrast-color-scheme-changed

* refactor: correct type of contrast
Heilig Benedek 6 years ago
parent
commit
6d2a088be9

+ 8 - 0
atom/browser/api/atom_api_system_preferences.cc

@@ -37,6 +37,12 @@ bool SystemPreferences::IsInvertedColorScheme() {
   return color_utils::IsInvertedColorScheme();
 }
 
+#if !defined(OS_WIN)
+bool SystemPreferences::IsHighContrastColorScheme() {
+  return false;
+}
+#endif  // !defined(OS_WIN)
+
 // static
 mate::Handle<SystemPreferences> SystemPreferences::Create(
     v8::Isolate* isolate) {
@@ -86,6 +92,8 @@ void SystemPreferences::BuildPrototype(
 #endif
       .SetMethod("isInvertedColorScheme",
                  &SystemPreferences::IsInvertedColorScheme)
+      .SetMethod("isHighContrastColorScheme",
+                 &SystemPreferences::IsHighContrastColorScheme)
       .SetMethod("isDarkMode", &SystemPreferences::IsDarkMode);
 }
 

+ 3 - 0
atom/browser/api/atom_api_system_preferences.h

@@ -98,6 +98,7 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences>
 #endif
   bool IsDarkMode();
   bool IsInvertedColorScheme();
+  bool IsHighContrastColorScheme();
 
  protected:
   explicit SystemPreferences(v8::Isolate* isolate);
@@ -139,6 +140,8 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences>
 
   bool invertered_color_scheme_;
 
+  bool high_contrast_color_scheme_;
+
   std::unique_ptr<gfx::ScopedSysColorChangeListener> color_change_listener_;
 #endif
   DISALLOW_COPY_AND_ASSIGN(SystemPreferences);

+ 29 - 0
atom/browser/api/atom_api_system_preferences_win.cc

@@ -20,6 +20,18 @@ namespace {
 const wchar_t kSystemPreferencesWindowClass[] =
     L"Electron_SystemPreferencesHostWindow";
 
+bool g_is_high_contract_color_scheme = false;
+bool g_is_high_contract_color_scheme_initialized = false;
+
+void UpdateHighContrastColorScheme() {
+  HIGHCONTRAST high_contrast = {0};
+  high_contrast.cbSize = sizeof(HIGHCONTRAST);
+  g_is_high_contract_color_scheme =
+      SystemParametersInfo(SPI_GETHIGHCONTRAST, 0, &high_contrast, 0) &&
+      ((high_contrast.dwFlags & HCF_HIGHCONTRASTON) != 0);
+  g_is_high_contract_color_scheme_initialized = true;
+}
+
 }  // namespace
 
 namespace api {
@@ -28,6 +40,12 @@ bool SystemPreferences::IsAeroGlassEnabled() {
   return ui::win::IsAeroGlassEnabled();
 }
 
+bool SystemPreferences::IsHighContrastColorScheme() {
+  if (!g_is_high_contract_color_scheme_initialized)
+    UpdateHighContrastColorScheme();
+  return g_is_high_contract_color_scheme;
+}
+
 std::string hexColorDWORDToRGBA(DWORD color) {
   DWORD rgba = color << 8 | color >> 24;
   std::ostringstream stream;
@@ -119,6 +137,7 @@ std::string SystemPreferences::GetColor(const std::string& color,
 
 void SystemPreferences::InitializeWindow() {
   invertered_color_scheme_ = IsInvertedColorScheme();
+  high_contrast_color_scheme_ = IsHighContrastColorScheme();
 
   // Wait until app is ready before creating sys color listener
   // Creating this listener before the app is ready causes global shortcuts
@@ -169,6 +188,9 @@ LRESULT CALLBACK SystemPreferences::WndProc(HWND hwnd,
       Emit("accent-color-changed", hexColorDWORDToRGBA(new_color));
       current_color_ = new_color_string;
     }
+  } else if (message == WM_SYSCOLORCHANGE ||
+             (message == WM_SETTINGCHANGE && wparam == SPI_SETHIGHCONTRAST)) {
+    UpdateHighContrastColorScheme();
   }
   return ::DefWindowProc(hwnd, message, wparam, lparam);
 }
@@ -179,6 +201,13 @@ void SystemPreferences::OnSysColorChange() {
     invertered_color_scheme_ = new_invertered_color_scheme;
     Emit("inverted-color-scheme-changed", new_invertered_color_scheme);
   }
+
+  bool new_high_contrast_color_scheme = IsHighContrastColorScheme();
+  if (new_high_contrast_color_scheme != high_contrast_color_scheme_) {
+    high_contrast_color_scheme_ = new_high_contrast_color_scheme;
+    Emit("high-contrast-color-scheme-changed", new_high_contrast_color_scheme);
+  }
+
   Emit("color-changed");
 }
 

+ 14 - 5
docs/api/system-preferences.md

@@ -32,8 +32,14 @@ Returns:
 Returns:
 
 * `event` Event
-* `invertedColorScheme` Boolean - `true` if an inverted color scheme, such as
-  a high contrast theme, is being used, `false` otherwise.
+* `invertedColorScheme` Boolean - `true` if an inverted color scheme (a high contrast color scheme with light text and dark backgrounds) is being used, `false` otherwise.
+
+### Event: 'high-contrast-color-scheme-changed' _Windows_
+
+Returns:
+
+* `event` Event
+* `highContrastColorScheme` Boolean - `true` if a high contrast theme is being used, `false` otherwise.
 
 ### Event: 'appearance-changed' _macOS_
 
@@ -276,12 +282,15 @@ const alpha = color.substr(6, 2) // "dd"
 Returns `String` - The system color setting in RGB hexadecimal form (`#ABCDEF`).
 See the [Windows docs][windows-colors] for more details.
 
+[windows-colors]:https://msdn.microsoft.com/en-us/library/windows/desktop/ms724371(v=vs.85).aspx
+
 ### `systemPreferences.isInvertedColorScheme()` _Windows_
 
-Returns `Boolean` - `true` if an inverted color scheme, such as a high contrast
-theme, is active, `false` otherwise.
+Returns `Boolean` - `true` if an inverted color scheme (a high contrast color scheme with light text and dark backgrounds) is active, `false` otherwise.
 
-[windows-colors]:https://msdn.microsoft.com/en-us/library/windows/desktop/ms724371(v=vs.85).aspx
+### `systemPreferences.isHighContrastColorScheme()` _Windows_
+
+Returns `Boolean` - `true` if a high contrast theme is active, `false` otherwise.
 
 ### `systemPreferences.getEffectiveAppearance()` _macOS_