From b17fb87832a190066782a83455ed451320709eea Mon Sep 17 00:00:00 2001 From: schectman Date: Fri, 27 Jan 2023 14:39:15 -0500 Subject: [PATCH 1/9] Check high contrast themes --- .../windows/flutter_windows_engine.cc | 1 + shell/platform/windows/settings_plugin.cc | 39 +++++++++++++------ shell/platform/windows/settings_plugin.h | 9 ++++- .../windows/settings_plugin_unittests.cc | 17 ++++++++ 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/shell/platform/windows/flutter_windows_engine.cc b/shell/platform/windows/flutter_windows_engine.cc index 8a9f3f760074c..f0aab9220ea43 100644 --- a/shell/platform/windows/flutter_windows_engine.cc +++ b/shell/platform/windows/flutter_windows_engine.cc @@ -668,6 +668,7 @@ void FlutterWindowsEngine::UpdateHighContrastEnabled(bool enabled) { ~FlutterAccessibilityFeature::kFlutterAccessibilityFeatureHighContrast; } UpdateAccessibilityFeatures(static_cast(flags)); + settings_plugin_->UpdateHighContrastMode(enabled); } int FlutterWindowsEngine::EnabledAccessibilityFeatures() const { diff --git a/shell/platform/windows/settings_plugin.cc b/shell/platform/windows/settings_plugin.cc index 2754516e108be..aa6e432ffcb44 100644 --- a/shell/platform/windows/settings_plugin.cc +++ b/shell/platform/windows/settings_plugin.cc @@ -103,19 +103,29 @@ float SettingsPlugin::GetTextScaleFactor() { } SettingsPlugin::PlatformBrightness SettingsPlugin::GetPreferredBrightness() { - DWORD use_light_theme; - DWORD use_light_theme_size = sizeof(use_light_theme); - LONG result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, - kGetPreferredBrightnessRegValue, RRF_RT_REG_DWORD, - nullptr, &use_light_theme, &use_light_theme_size); - - if (result == 0) { - return use_light_theme ? SettingsPlugin::PlatformBrightness::kLight - : SettingsPlugin::PlatformBrightness::kDark; + if (is_high_contrast_) { + DWORD text_color = GetSysColor(COLOR_WINDOW); + int r = GetRValue(text_color); + int g = GetGValue(text_color); + int b = GetBValue(text_color); + int luminance = (r + r + r + b + (g << 2)) >> 3; + return luminance >= 0.5 ? SettingsPlugin::PlatformBrightness::kLight + : SettingsPlugin::PlatformBrightness::kDark; } else { - // The current OS does not support dark mode. (Older Windows 10 or before - // Windows 10) - return SettingsPlugin::PlatformBrightness::kLight; + DWORD use_light_theme; + DWORD use_light_theme_size = sizeof(use_light_theme); + LONG result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, RRF_RT_REG_DWORD, + nullptr, &use_light_theme, &use_light_theme_size); + + if (result == 0) { + return use_light_theme ? SettingsPlugin::PlatformBrightness::kLight + : SettingsPlugin::PlatformBrightness::kDark; + } else { + // The current OS does not support dark mode. (Older Windows 10 or before + // Windows 10) + return SettingsPlugin::PlatformBrightness::kLight; + } } } @@ -146,4 +156,9 @@ void SettingsPlugin::WatchTextScaleFactorChanged() { text_scale_factor_changed_watcher_->GetHandle(), TRUE); } +void SettingsPlugin::UpdateHighContrastMode(bool is_high_contrast) { + is_high_contrast_ = is_high_contrast; + SendSettings(); +} + } // namespace flutter diff --git a/shell/platform/windows/settings_plugin.h b/shell/platform/windows/settings_plugin.h index 2c663fc048212..dbd770fa5bd6f 100644 --- a/shell/platform/windows/settings_plugin.h +++ b/shell/platform/windows/settings_plugin.h @@ -23,6 +23,8 @@ namespace flutter { // These are typically set in the control panel. class SettingsPlugin { public: + enum struct PlatformBrightness { kDark, kLight }; + explicit SettingsPlugin(BinaryMessenger* messenger, TaskRunner* task_runner); virtual ~SettingsPlugin(); @@ -37,9 +39,10 @@ class SettingsPlugin { // this automatically. virtual void StopWatching(); - protected: - enum struct PlatformBrightness { kDark, kLight }; + // Update the high contrast status of the system. + virtual void UpdateHighContrastMode(bool is_high_contrast); + protected: // Returns `true` if the user uses 24 hour time. virtual bool GetAlwaysUse24HourFormat(); @@ -55,6 +58,8 @@ class SettingsPlugin { // Starts watching text scale factor changes. virtual void WatchTextScaleFactorChanged(); + bool is_high_contrast_ = false; + private: std::unique_ptr> channel_; diff --git a/shell/platform/windows/settings_plugin_unittests.cc b/shell/platform/windows/settings_plugin_unittests.cc index 2380f46017014..1450aa7d77250 100644 --- a/shell/platform/windows/settings_plugin_unittests.cc +++ b/shell/platform/windows/settings_plugin_unittests.cc @@ -26,6 +26,10 @@ class MockSettingsPlugin : public SettingsPlugin { MOCK_METHOD0(GetTextScaleFactor, float()); MOCK_METHOD0(GetPreferredBrightness, PlatformBrightness()); + bool is_high_contrast() { + return is_high_contrast_; + } + MOCK_METHOD0(WatchPreferredBrightnessChanged, void()); MOCK_METHOD0(WatchTextScaleFactorChanged, void()); }; @@ -70,5 +74,18 @@ TEST(SettingsPluginTest, StartWatchingStartsWatchingChanges) { settings_plugin.StartWatching(); } +TEST(SettingsPluginTest, HighContrastModeHonored) { + TestBinaryMessenger messenger([](const std::string& channel, + const uint8_t* message, size_t message_size, + BinaryReply reply) {}); + ::testing::NiceMock settings_plugin(&messenger, nullptr); + + settings_plugin.UpdateHighContrastMode(true); + EXPECT_TRUE(settings_plugin.is_high_contrast()); + + settings_plugin.UpdateHighContrastMode(false); + EXPECT_FALSE(settings_plugin.is_high_contrast()); +} + } // namespace testing } // namespace flutter From 6ad04032990dba95ddfa868c45898b5ab226194e Mon Sep 17 00:00:00 2001 From: schectman Date: Fri, 27 Jan 2023 15:00:33 -0500 Subject: [PATCH 2/9] Formatting --- shell/platform/windows/settings_plugin_unittests.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/shell/platform/windows/settings_plugin_unittests.cc b/shell/platform/windows/settings_plugin_unittests.cc index 1450aa7d77250..3170881e7b164 100644 --- a/shell/platform/windows/settings_plugin_unittests.cc +++ b/shell/platform/windows/settings_plugin_unittests.cc @@ -21,15 +21,13 @@ class MockSettingsPlugin : public SettingsPlugin { virtual ~MockSettingsPlugin() = default; + bool is_high_contrast() { return is_high_contrast_; } + // |SettingsPlugin| MOCK_METHOD0(GetAlwaysUse24HourFormat, bool()); MOCK_METHOD0(GetTextScaleFactor, float()); MOCK_METHOD0(GetPreferredBrightness, PlatformBrightness()); - bool is_high_contrast() { - return is_high_contrast_; - } - MOCK_METHOD0(WatchPreferredBrightnessChanged, void()); MOCK_METHOD0(WatchTextScaleFactorChanged, void()); }; From f53aefb498eb40e918d1952baf202bf63f6413dd Mon Sep 17 00:00:00 2001 From: schectman Date: Fri, 27 Jan 2023 15:10:30 -0500 Subject: [PATCH 3/9] Test message sending --- shell/platform/windows/settings_plugin_unittests.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/shell/platform/windows/settings_plugin_unittests.cc b/shell/platform/windows/settings_plugin_unittests.cc index 3170881e7b164..57a2fa277ca17 100644 --- a/shell/platform/windows/settings_plugin_unittests.cc +++ b/shell/platform/windows/settings_plugin_unittests.cc @@ -73,9 +73,10 @@ TEST(SettingsPluginTest, StartWatchingStartsWatchingChanges) { } TEST(SettingsPluginTest, HighContrastModeHonored) { - TestBinaryMessenger messenger([](const std::string& channel, + int times = 0; + TestBinaryMessenger messenger([×](const std::string& channel, const uint8_t* message, size_t message_size, - BinaryReply reply) {}); + BinaryReply reply) { times++; }); ::testing::NiceMock settings_plugin(&messenger, nullptr); settings_plugin.UpdateHighContrastMode(true); @@ -83,6 +84,8 @@ TEST(SettingsPluginTest, HighContrastModeHonored) { settings_plugin.UpdateHighContrastMode(false); EXPECT_FALSE(settings_plugin.is_high_contrast()); + + EXPECT_EQ(times, 2); } } // namespace testing From d6cff50339d4c12df18bfa2abc9600378b9e36ea Mon Sep 17 00:00:00 2001 From: schectman Date: Mon, 30 Jan 2023 16:37:54 -0500 Subject: [PATCH 4/9] Assert channel name --- shell/platform/windows/settings_plugin_unittests.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shell/platform/windows/settings_plugin_unittests.cc b/shell/platform/windows/settings_plugin_unittests.cc index 57a2fa277ca17..9a9e7ef38d74b 100644 --- a/shell/platform/windows/settings_plugin_unittests.cc +++ b/shell/platform/windows/settings_plugin_unittests.cc @@ -76,7 +76,10 @@ TEST(SettingsPluginTest, HighContrastModeHonored) { int times = 0; TestBinaryMessenger messenger([×](const std::string& channel, const uint8_t* message, size_t message_size, - BinaryReply reply) { times++; }); + BinaryReply reply) { + ASSERT_EQ(channel, "flutter/settings"); + times++; + }); ::testing::NiceMock settings_plugin(&messenger, nullptr); settings_plugin.UpdateHighContrastMode(true); From 69c584ac93244466782f0d18ecaf0ab5710424e0 Mon Sep 17 00:00:00 2001 From: schectman Date: Mon, 30 Jan 2023 16:58:46 -0500 Subject: [PATCH 5/9] Formatting --- shell/platform/windows/settings_plugin_unittests.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/shell/platform/windows/settings_plugin_unittests.cc b/shell/platform/windows/settings_plugin_unittests.cc index 9a9e7ef38d74b..2ca1711c8faf4 100644 --- a/shell/platform/windows/settings_plugin_unittests.cc +++ b/shell/platform/windows/settings_plugin_unittests.cc @@ -74,12 +74,12 @@ TEST(SettingsPluginTest, StartWatchingStartsWatchingChanges) { TEST(SettingsPluginTest, HighContrastModeHonored) { int times = 0; - TestBinaryMessenger messenger([×](const std::string& channel, - const uint8_t* message, size_t message_size, - BinaryReply reply) { - ASSERT_EQ(channel, "flutter/settings"); - times++; - }); + TestBinaryMessenger messenger( + [×](const std::string& channel, const uint8_t* message, + size_t message_size, BinaryReply reply) { + ASSERT_EQ(channel, "flutter/settings"); + times++; + }); ::testing::NiceMock settings_plugin(&messenger, nullptr); settings_plugin.UpdateHighContrastMode(true); From 6a2353e36492e047214b5acdabfb7902acc4a2f5 Mon Sep 17 00:00:00 2001 From: schectman Date: Tue, 31 Jan 2023 17:04:53 -0500 Subject: [PATCH 6/9] Calculate luminance --- shell/platform/windows/settings_plugin.cc | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/shell/platform/windows/settings_plugin.cc b/shell/platform/windows/settings_plugin.cc index aa6e432ffcb44..46041a3d0862d 100644 --- a/shell/platform/windows/settings_plugin.cc +++ b/shell/platform/windows/settings_plugin.cc @@ -26,6 +26,14 @@ constexpr wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; constexpr wchar_t kGetTextScaleFactorRegKey[] = L"Software\\Microsoft\\Accessibility"; constexpr wchar_t kGetTextScaleFactorRegValue[] = L"TextScaleFactor"; + +// Return an approximation of the apparent luminance of a given color. +int GetLuminance(DWORD color) { + int r = GetRValue(color); + int g = GetGValue(color); + int b = GetBValue(color); + return (r + r + r + b + (g << 2)) >> 3; +} } // namespace SettingsPlugin::SettingsPlugin(BinaryMessenger* messenger, @@ -104,12 +112,9 @@ float SettingsPlugin::GetTextScaleFactor() { SettingsPlugin::PlatformBrightness SettingsPlugin::GetPreferredBrightness() { if (is_high_contrast_) { - DWORD text_color = GetSysColor(COLOR_WINDOW); - int r = GetRValue(text_color); - int g = GetGValue(text_color); - int b = GetBValue(text_color); - int luminance = (r + r + r + b + (g << 2)) >> 3; - return luminance >= 0.5 ? SettingsPlugin::PlatformBrightness::kLight + DWORD window_color = GetSysColor(COLOR_WINDOW); + int luminance = GetLuminance(window_color); + return luminance >= 127 ? SettingsPlugin::PlatformBrightness::kLight : SettingsPlugin::PlatformBrightness::kDark; } else { DWORD use_light_theme; From e1f57c99e745ce368de6ef68b74955c5665a857c Mon Sep 17 00:00:00 2001 From: schectman Date: Tue, 31 Jan 2023 17:08:42 -0500 Subject: [PATCH 7/9] Refactor brightness check --- shell/platform/windows/settings_plugin.cc | 32 +++++++++++++---------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/shell/platform/windows/settings_plugin.cc b/shell/platform/windows/settings_plugin.cc index 46041a3d0862d..f43b8746b1b9c 100644 --- a/shell/platform/windows/settings_plugin.cc +++ b/shell/platform/windows/settings_plugin.cc @@ -34,6 +34,23 @@ int GetLuminance(DWORD color) { int b = GetBValue(color); return (r + r + r + b + (g << 2)) >> 3; } + +// Return kLight if light mode for apps is selected, otherwise return kDark. +SettingsPlugin::PlatformBrightness GetThemeBrightness() {DWORD use_light_theme; + DWORD use_light_theme_size = sizeof(use_light_theme); + LONG result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, RRF_RT_REG_DWORD, + nullptr, &use_light_theme, &use_light_theme_size); + + if (result == 0) { + return use_light_theme ? SettingsPlugin::PlatformBrightness::kLight + : SettingsPlugin::PlatformBrightness::kDark; + } else { + // The current OS does not support dark mode. (Older Windows 10 or before + // Windows 10) + return SettingsPlugin::PlatformBrightness::kLight; + } +} } // namespace SettingsPlugin::SettingsPlugin(BinaryMessenger* messenger, @@ -117,20 +134,7 @@ SettingsPlugin::PlatformBrightness SettingsPlugin::GetPreferredBrightness() { return luminance >= 127 ? SettingsPlugin::PlatformBrightness::kLight : SettingsPlugin::PlatformBrightness::kDark; } else { - DWORD use_light_theme; - DWORD use_light_theme_size = sizeof(use_light_theme); - LONG result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, - kGetPreferredBrightnessRegValue, RRF_RT_REG_DWORD, - nullptr, &use_light_theme, &use_light_theme_size); - - if (result == 0) { - return use_light_theme ? SettingsPlugin::PlatformBrightness::kLight - : SettingsPlugin::PlatformBrightness::kDark; - } else { - // The current OS does not support dark mode. (Older Windows 10 or before - // Windows 10) - return SettingsPlugin::PlatformBrightness::kLight; - } + return GetThemeBrightness(); } } From 2f34d2b700710c2ddb7c1a2221740b7f25bbe73a Mon Sep 17 00:00:00 2001 From: schectman Date: Tue, 31 Jan 2023 17:17:29 -0500 Subject: [PATCH 8/9] Formatting --- shell/platform/windows/settings_plugin.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/windows/settings_plugin.cc b/shell/platform/windows/settings_plugin.cc index f43b8746b1b9c..a8733d69aefde 100644 --- a/shell/platform/windows/settings_plugin.cc +++ b/shell/platform/windows/settings_plugin.cc @@ -44,7 +44,7 @@ SettingsPlugin::PlatformBrightness GetThemeBrightness() {DWORD use_light_theme; if (result == 0) { return use_light_theme ? SettingsPlugin::PlatformBrightness::kLight - : SettingsPlugin::PlatformBrightness::kDark; + : SettingsPlugin::PlatformBrightness::kDark; } else { // The current OS does not support dark mode. (Older Windows 10 or before // Windows 10) From cb766b92cfc4d8c95cddff2daf9ff72557f12df9 Mon Sep 17 00:00:00 2001 From: schectman Date: Tue, 31 Jan 2023 18:06:04 -0500 Subject: [PATCH 9/9] Formatting --- shell/platform/windows/settings_plugin.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shell/platform/windows/settings_plugin.cc b/shell/platform/windows/settings_plugin.cc index a8733d69aefde..094184703a030 100644 --- a/shell/platform/windows/settings_plugin.cc +++ b/shell/platform/windows/settings_plugin.cc @@ -36,7 +36,8 @@ int GetLuminance(DWORD color) { } // Return kLight if light mode for apps is selected, otherwise return kDark. -SettingsPlugin::PlatformBrightness GetThemeBrightness() {DWORD use_light_theme; +SettingsPlugin::PlatformBrightness GetThemeBrightness() { + DWORD use_light_theme; DWORD use_light_theme_size = sizeof(use_light_theme); LONG result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, kGetPreferredBrightnessRegValue, RRF_RT_REG_DWORD,