diff --git a/engine/src/flutter/shell/platform/windows/flutter_window.cc b/engine/src/flutter/shell/platform/windows/flutter_window.cc index 710a966fc32..93369740943 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_window.cc +++ b/engine/src/flutter/shell/platform/windows/flutter_window.cc @@ -119,7 +119,7 @@ static uint64_t ConvertWinButtonToFlutterButton(UINT button) { FlutterWindow::FlutterWindow( int width, int height, - std::unique_ptr windows_proc_table, + std::shared_ptr windows_proc_table, std::unique_ptr text_input_manager) : binding_handler_delegate_(nullptr), touch_id_generator_(kMinTouchDeviceId, kMaxTouchDeviceId), @@ -356,12 +356,7 @@ PointerLocation FlutterWindow::GetPrimaryPointerLocation() { } void FlutterWindow::OnThemeChange() { - binding_handler_delegate_->UpdateHighContrastEnabled( - GetHighContrastEnabled()); -} - -void FlutterWindow::SendInitialAccessibilityFeatures() { - OnThemeChange(); + binding_handler_delegate_->OnHighContrastChanged(); } ui::AXFragmentRootDelegateWin* FlutterWindow::GetAxFragmentRootDelegate() { @@ -950,19 +945,6 @@ float FlutterWindow::GetScrollOffsetMultiplier() { return scroll_offset_multiplier_; } -bool FlutterWindow::GetHighContrastEnabled() { - HIGHCONTRAST high_contrast = {.cbSize = sizeof(HIGHCONTRAST)}; - // API call is only supported on Windows 8+ - if (SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(HIGHCONTRAST), - &high_contrast, 0)) { - return high_contrast.dwFlags & HCF_HIGHCONTRASTON; - } else { - FML_LOG(INFO) << "Failed to get status of high contrast feature," - << "support only for Windows 8 + "; - return false; - } -} - LRESULT FlutterWindow::Win32DefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, diff --git a/engine/src/flutter/shell/platform/windows/flutter_window.h b/engine/src/flutter/shell/platform/windows/flutter_window.h index f1347369a35..49eb37284f0 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_window.h +++ b/engine/src/flutter/shell/platform/windows/flutter_window.h @@ -38,7 +38,7 @@ class FlutterWindow : public KeyboardManager::WindowDelegate, // Create flutter Window for use as child window FlutterWindow(int width, int height, - std::unique_ptr windows_proc_table = nullptr, + std::shared_ptr windows_proc_table = nullptr, std::unique_ptr text_input_manager = nullptr); virtual ~FlutterWindow(); @@ -189,9 +189,6 @@ class FlutterWindow : public KeyboardManager::WindowDelegate, // Called when a theme change message is issued. virtual void OnThemeChange(); - // |WindowBindingHandler| - virtual void SendInitialAccessibilityFeatures() override; - // |WindowBindingHandler| virtual AlertPlatformNodeDelegate* GetAlertDelegate() override; @@ -281,9 +278,6 @@ class FlutterWindow : public KeyboardManager::WindowDelegate, // Returns the current pixel per scroll tick value. virtual float GetScrollOffsetMultiplier(); - // Check if the high contrast feature is enabled on the OS - virtual bool GetHighContrastEnabled(); - // Delegate to a alert_node_ used to set the announcement text. std::unique_ptr alert_delegate_; @@ -381,7 +375,7 @@ class FlutterWindow : public KeyboardManager::WindowDelegate, // Abstracts Windows APIs that may not be available on all supported versions // of Windows. - std::unique_ptr windows_proc_table_; + std::shared_ptr windows_proc_table_; // Manages IME state. std::unique_ptr text_input_manager_; diff --git a/engine/src/flutter/shell/platform/windows/flutter_window_unittests.cc b/engine/src/flutter/shell/platform/windows/flutter_window_unittests.cc index 7f8ddccc47b..8059a1ed29e 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_window_unittests.cc +++ b/engine/src/flutter/shell/platform/windows/flutter_window_unittests.cc @@ -64,7 +64,6 @@ class MockFlutterWindow : public FlutterWindow { (override)); MOCK_METHOD(void, OnSetCursor, (), (override)); MOCK_METHOD(float, GetScrollOffsetMultiplier, (), (override)); - MOCK_METHOD(bool, GetHighContrastEnabled, (), (override)); MOCK_METHOD(float, GetDpiScale, (), (override)); MOCK_METHOD(bool, IsVisible, (), (override)); MOCK_METHOD(void, UpdateCursorRect, (const Rect&), (override)); @@ -290,8 +289,7 @@ TEST(FlutterWindowTest, OnThemeChange) { MockWindowBindingHandlerDelegate delegate; win32window.SetView(&delegate); - ON_CALL(win32window, GetHighContrastEnabled()).WillByDefault(Return(true)); - EXPECT_CALL(delegate, UpdateHighContrastEnabled(true)).Times(1); + EXPECT_CALL(delegate, OnHighContrastChanged).Times(1); win32window.InjectWindowMessage(WM_THEMECHANGED, 0, 0); } @@ -305,17 +303,6 @@ TEST(FlutterWindowTest, AccessibilityNodeWithoutView) { EXPECT_EQ(win32window.GetNativeViewAccessible(), nullptr); } -TEST(FlutterWindowTest, InitialAccessibilityFeatures) { - MockFlutterWindow win32window; - MockWindowBindingHandlerDelegate delegate; - win32window.SetView(&delegate); - - ON_CALL(win32window, GetHighContrastEnabled()).WillByDefault(Return(true)); - EXPECT_CALL(delegate, UpdateHighContrastEnabled(true)).Times(1); - - win32window.SendInitialAccessibilityFeatures(); -} - // Ensure that announcing the alert propagates the message to the alert node. // Different screen readers use different properties for alerts. TEST(FlutterWindowTest, AlertNode) { diff --git a/engine/src/flutter/shell/platform/windows/flutter_windows.cc b/engine/src/flutter/shell/platform/windows/flutter_windows.cc index 54b66bee620..f15e1adebe7 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_windows.cc +++ b/engine/src/flutter/shell/platform/windows/flutter_windows.cc @@ -76,11 +76,12 @@ FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate( int width, int height, FlutterDesktopEngineRef engine_ref) { + flutter::FlutterWindowsEngine* engine_ptr = EngineFromHandle(engine_ref); std::unique_ptr window_wrapper = - std::make_unique(width, height); + std::make_unique( + width, height, engine_ptr->windows_proc_table()); - auto engine = std::unique_ptr( - EngineFromHandle(engine_ref)); + auto engine = std::unique_ptr(engine_ptr); auto view = std::make_unique(std::move(window_wrapper)); auto controller = std::make_unique( @@ -96,7 +97,11 @@ FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate( // Must happen after engine is running. controller->view()->SendInitialBounds(); - controller->view()->SendInitialAccessibilityFeatures(); + + // The Windows embedder listens to accessibility updates using the + // view's HWND. The embedder's accessibility features may be stale if + // the app was in headless mode. + controller->engine()->UpdateAccessibilityFeatures(); return HandleForViewController(controller.release()); } diff --git a/engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc b/engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc index 2e04c14f244..348ea7b773e 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc +++ b/engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc @@ -157,10 +157,17 @@ FlutterLocale CovertToFlutterLocale(const LanguageInfo& info) { } // namespace -FlutterWindowsEngine::FlutterWindowsEngine(const FlutterProjectBundle& project) +FlutterWindowsEngine::FlutterWindowsEngine( + const FlutterProjectBundle& project, + std::shared_ptr windows_proc_table) : project_(std::make_unique(project)), + windows_proc_table_(std::move(windows_proc_table)), aot_data_(nullptr, nullptr), lifecycle_manager_(std::make_unique(this)) { + if (windows_proc_table_ == nullptr) { + windows_proc_table_ = std::make_shared(); + } + embedder_api_.struct_size = sizeof(FlutterEngineProcTable); FlutterEngineGetProcAddresses(&embedder_api_); @@ -569,8 +576,7 @@ void FlutterWindowsEngine::HandlePlatformMessage( auto message = ConvertToDesktopMessage(*engine_message); - message_dispatcher_->HandleMessage( - message, [this] {}, [this] {}); + message_dispatcher_->HandleMessage(message, [this] {}, [this] {}); } void FlutterWindowsEngine::ReloadSystemFonts() { @@ -605,7 +611,7 @@ void FlutterWindowsEngine::SetLifecycleState(flutter::AppLifecycleState state) { void FlutterWindowsEngine::SendSystemLocales() { std::vector languages = - GetPreferredLanguageInfo(windows_proc_table_); + GetPreferredLanguageInfo(*windows_proc_table_); std::vector flutter_locales; flutter_locales.reserve(languages.size()); for (const auto& info : languages) { @@ -737,34 +743,27 @@ std::string FlutterWindowsEngine::GetExecutableName() const { return "Flutter"; } -void FlutterWindowsEngine::UpdateAccessibilityFeatures( - FlutterAccessibilityFeature flags) { - embedder_api_.UpdateAccessibilityFeatures(engine_, flags); +void FlutterWindowsEngine::UpdateAccessibilityFeatures() { + UpdateHighContrastMode(); } -void FlutterWindowsEngine::UpdateHighContrastEnabled(bool enabled) { - high_contrast_enabled_ = enabled; - int flags = EnabledAccessibilityFeatures(); - if (enabled) { - flags |= - FlutterAccessibilityFeature::kFlutterAccessibilityFeatureHighContrast; - } else { - flags &= - ~FlutterAccessibilityFeature::kFlutterAccessibilityFeatureHighContrast; - } - UpdateAccessibilityFeatures(static_cast(flags)); - settings_plugin_->UpdateHighContrastMode(enabled); +void FlutterWindowsEngine::UpdateHighContrastMode() { + high_contrast_enabled_ = windows_proc_table_->GetHighContrastEnabled(); + + SendAccessibilityFeatures(); + settings_plugin_->UpdateHighContrastMode(high_contrast_enabled_); } -int FlutterWindowsEngine::EnabledAccessibilityFeatures() const { +void FlutterWindowsEngine::SendAccessibilityFeatures() { int flags = 0; - if (high_contrast_enabled()) { + + if (high_contrast_enabled_) { flags |= FlutterAccessibilityFeature::kFlutterAccessibilityFeatureHighContrast; } - // As more accessibility features are enabled for Windows, - // the corresponding checks and flags should be added here. - return flags; + + embedder_api_.UpdateAccessibilityFeatures( + engine_, static_cast(flags)); } void FlutterWindowsEngine::HandleAccessibilityMessage( diff --git a/engine/src/flutter/shell/platform/windows/flutter_windows_engine.h b/engine/src/flutter/shell/platform/windows/flutter_windows_engine.h index 04d33e7583d..ff7f6e4a33b 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_windows_engine.h +++ b/engine/src/flutter/shell/platform/windows/flutter_windows_engine.h @@ -78,7 +78,9 @@ static void WindowsPlatformThreadPrioritySetter( class FlutterWindowsEngine { public: // Creates a new Flutter engine object configured to run |project|. - explicit FlutterWindowsEngine(const FlutterProjectBundle& project); + FlutterWindowsEngine( + const FlutterProjectBundle& project, + std::shared_ptr windows_proc_table = nullptr); virtual ~FlutterWindowsEngine(); @@ -215,11 +217,11 @@ class FlutterWindowsEngine { // Returns true if the semantics tree is enabled. bool semantics_enabled() const { return semantics_enabled_; } - // Update the high contrast feature state. - void UpdateHighContrastEnabled(bool enabled); + // Refresh accessibility features and send them to the engine. + void UpdateAccessibilityFeatures(); - // Returns the flags for all currently enabled accessibility features - int EnabledAccessibilityFeatures() const; + // Refresh high contrast accessibility mode and notify the engine. + void UpdateHighContrastMode(); // Returns true if the high contrast feature is enabled. bool high_contrast_enabled() const { return high_contrast_enabled_; } @@ -240,9 +242,6 @@ class FlutterWindowsEngine { // Returns the executable name for this process or "Flutter" if unknown. std::string GetExecutableName() const; - // Updates accessibility, e.g. switch to high contrast mode - void UpdateAccessibilityFeatures(FlutterAccessibilityFeature flags); - // Called when the application quits in response to a quit request. void OnQuit(std::optional hwnd, std::optional wparam, @@ -274,6 +273,10 @@ class FlutterWindowsEngine { return lifecycle_manager_.get(); } + std::shared_ptr windows_proc_table() { + return windows_proc_table_; + } + protected: // Creates the keyboard key handler. // @@ -320,6 +323,9 @@ class FlutterWindowsEngine { // Calling this method again resets the keyboard state. void InitializeKeyboard(); + // Send the currently enabled accessibility features to the engine. + void SendAccessibilityFeatures(); + void HandleAccessibilityMessage(FlutterDesktopMessengerRef messenger, const FlutterDesktopMessage* message); @@ -414,7 +420,7 @@ class FlutterWindowsEngine { // Handler for top level window messages. std::unique_ptr lifecycle_manager_; - WindowsProcTable windows_proc_table_; + std::shared_ptr windows_proc_table_; FML_DISALLOW_COPY_AND_ASSIGN(FlutterWindowsEngine); }; diff --git a/engine/src/flutter/shell/platform/windows/flutter_windows_engine_unittests.cc b/engine/src/flutter/shell/platform/windows/flutter_windows_engine_unittests.cc index 6b39816907a..281663415d5 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_windows_engine_unittests.cc +++ b/engine/src/flutter/shell/platform/windows/flutter_windows_engine_unittests.cc @@ -12,6 +12,7 @@ #include "flutter/shell/platform/windows/testing/engine_modifier.h" #include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h" #include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h" +#include "flutter/shell/platform/windows/testing/mock_windows_proc_table.h" #include "flutter/shell/platform/windows/testing/test_keyboard.h" #include "flutter/shell/platform/windows/testing/windows_test.h" #include "flutter/third_party/accessibility/ax/platform/ax_platform_node_win.h" @@ -25,6 +26,8 @@ namespace flutter { namespace testing { +using ::testing::Return; + class FlutterWindowsEngineTest : public WindowsTest {}; TEST_F(FlutterWindowsEngineTest, RunDoesExpectedInitialization) { @@ -558,29 +561,41 @@ TEST_F(FlutterWindowsEngineTest, GetExecutableName) { // Ensure that after setting or resetting the high contrast feature, // the corresponding status flag can be retrieved from the engine. TEST_F(FlutterWindowsEngineTest, UpdateHighContrastFeature) { + auto windows_proc_table = std::make_shared(); + EXPECT_CALL(*windows_proc_table, GetHighContrastEnabled) + .WillOnce(Return(true)) + .WillOnce(Return(false)); + FlutterWindowsEngineBuilder builder{GetContext()}; + builder.SetWindowsProcTable(windows_proc_table); std::unique_ptr engine = builder.Build(); EngineModifier modifier(engine.get()); - bool called = false; + std::optional engine_flags; modifier.embedder_api().UpdateAccessibilityFeatures = MOCK_ENGINE_PROC( - UpdateAccessibilityFeatures, ([&called](auto engine, auto flags) { - called = true; + UpdateAccessibilityFeatures, ([&engine_flags](auto engine, auto flags) { + engine_flags = flags; return kSuccess; })); - engine->UpdateHighContrastEnabled(true); - EXPECT_TRUE( - engine->EnabledAccessibilityFeatures() & - FlutterAccessibilityFeature::kFlutterAccessibilityFeatureHighContrast); - EXPECT_TRUE(engine->high_contrast_enabled()); - EXPECT_TRUE(called); + // 1: High contrast is enabled. + engine->UpdateHighContrastMode(); - engine->UpdateHighContrastEnabled(false); - EXPECT_FALSE( - engine->EnabledAccessibilityFeatures() & + EXPECT_TRUE(engine->high_contrast_enabled()); + EXPECT_TRUE(engine_flags.has_value()); + EXPECT_TRUE( + engine_flags.value() & FlutterAccessibilityFeature::kFlutterAccessibilityFeatureHighContrast); + + // 2: High contrast is disabled. + engine_flags.reset(); + engine->UpdateHighContrastMode(); + EXPECT_FALSE(engine->high_contrast_enabled()); + EXPECT_TRUE(engine_flags.has_value()); + EXPECT_FALSE( + engine_flags.value() & + FlutterAccessibilityFeature::kFlutterAccessibilityFeatureHighContrast); } TEST_F(FlutterWindowsEngineTest, PostRasterThreadTask) { diff --git a/engine/src/flutter/shell/platform/windows/flutter_windows_unittests.cc b/engine/src/flutter/shell/platform/windows/flutter_windows_unittests.cc index 23f2abb8964..38d613301bc 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_windows_unittests.cc +++ b/engine/src/flutter/shell/platform/windows/flutter_windows_unittests.cc @@ -10,6 +10,8 @@ #include "flutter/fml/synchronization/count_down_latch.h" #include "flutter/fml/synchronization/waitable_event.h" +#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h" +#include "flutter/shell/platform/windows/testing/engine_modifier.h" #include "flutter/shell/platform/windows/testing/windows_test.h" #include "flutter/shell/platform/windows/testing/windows_test_config_builder.h" #include "flutter/shell/platform/windows/testing/windows_test_context.h" @@ -99,6 +101,27 @@ TEST_F(WindowsTest, LaunchHeadlessEngine) { ASSERT_TRUE(FlutterDesktopEngineRun(engine.get(), nullptr)); } +// Verify that accessibility features are initialized when a view is created. +TEST_F(WindowsTest, LaunchRefreshesAccessibility) { + auto& context = GetContext(); + WindowsConfigBuilder builder(context); + EnginePtr engine{builder.InitializeEngine()}; + EngineModifier modifier{ + reinterpret_cast(engine.get())}; + + auto called = false; + modifier.embedder_api().UpdateAccessibilityFeatures = MOCK_ENGINE_PROC( + UpdateAccessibilityFeatures, ([&called](auto engine, auto flags) { + called = true; + return kSuccess; + })); + + ViewControllerPtr controller{ + FlutterDesktopViewControllerCreate(0, 0, engine.release())}; + + ASSERT_TRUE(called); +} + // Verify that engine fails to launch when a conflicting entrypoint in // FlutterDesktopEngineProperties.dart_entrypoint and the // FlutterDesktopEngineRun parameter. diff --git a/engine/src/flutter/shell/platform/windows/flutter_windows_view.cc b/engine/src/flutter/shell/platform/windows/flutter_windows_view.cc index d5afd6903d7..dc5488122e5 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_windows_view.cc +++ b/engine/src/flutter/shell/platform/windows/flutter_windows_view.cc @@ -613,12 +613,8 @@ void FlutterWindowsView::DestroyRenderSurface() { } } -void FlutterWindowsView::SendInitialAccessibilityFeatures() { - binding_handler_->SendInitialAccessibilityFeatures(); -} - -void FlutterWindowsView::UpdateHighContrastEnabled(bool enabled) { - engine_->UpdateHighContrastEnabled(enabled); +void FlutterWindowsView::OnHighContrastChanged() { + engine_->UpdateHighContrastMode(); } WindowsRenderTarget* FlutterWindowsView::GetRenderTarget() const { diff --git a/engine/src/flutter/shell/platform/windows/flutter_windows_view.h b/engine/src/flutter/shell/platform/windows/flutter_windows_view.h index b11e86f7282..a8871c9f5a1 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_windows_view.h +++ b/engine/src/flutter/shell/platform/windows/flutter_windows_view.h @@ -82,14 +82,11 @@ class FlutterWindowsView : public WindowBindingHandlerDelegate, // Send initial bounds to embedder. Must occur after engine has initialized. void SendInitialBounds(); - // Send the initial accessibility features to the window - void SendInitialAccessibilityFeatures(); - // Set the text of the alert, and create it if it does not yet exist. void AnnounceAlert(const std::wstring& text); // |WindowBindingHandlerDelegate| - void UpdateHighContrastEnabled(bool enabled) override; + void OnHighContrastChanged() override; // Returns the frame buffer id for the engine to render to. uint32_t GetFrameBufferId(size_t width, size_t height); diff --git a/engine/src/flutter/shell/platform/windows/testing/flutter_windows_engine_builder.cc b/engine/src/flutter/shell/platform/windows/testing/flutter_windows_engine_builder.cc index 9b8f6e4053d..9e122b35d4e 100644 --- a/engine/src/flutter/shell/platform/windows/testing/flutter_windows_engine_builder.cc +++ b/engine/src/flutter/shell/platform/windows/testing/flutter_windows_engine_builder.cc @@ -5,6 +5,7 @@ #include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h" #include "flutter/fml/macros.h" +#include "flutter/shell/platform/windows/windows_proc_table.h" namespace flutter { namespace testing { @@ -14,8 +15,9 @@ class TestFlutterWindowsEngine : public FlutterWindowsEngine { TestFlutterWindowsEngine( const FlutterProjectBundle& project, KeyboardKeyEmbedderHandler::GetKeyStateHandler get_key_state, - KeyboardKeyEmbedderHandler::MapVirtualKeyToScanCode map_vk_to_scan) - : FlutterWindowsEngine(project), + KeyboardKeyEmbedderHandler::MapVirtualKeyToScanCode map_vk_to_scan, + std::shared_ptr windows_proc_table = nullptr) + : FlutterWindowsEngine(project, std::move(windows_proc_table)), get_key_state_(std::move(get_key_state)), map_vk_to_scan_(std::move(map_vk_to_scan)) {} @@ -74,6 +76,11 @@ void FlutterWindowsEngineBuilder::SetCreateKeyboardHandlerCallbacks( map_vk_to_scan_ = std::move(map_vk_to_scan); } +void FlutterWindowsEngineBuilder::SetWindowsProcTable( + std::shared_ptr windows_proc_table) { + windows_proc_table_ = std::move(windows_proc_table); +} + std::unique_ptr FlutterWindowsEngineBuilder::Build() { std::vector dart_args; dart_args.reserve(dart_entrypoint_arguments_.size()); @@ -93,8 +100,8 @@ std::unique_ptr FlutterWindowsEngineBuilder::Build() { FlutterProjectBundle project(properties_); project.SetSwitches(switches_); - return std::make_unique(project, get_key_state_, - map_vk_to_scan_); + return std::make_unique( + project, get_key_state_, map_vk_to_scan_, std::move(windows_proc_table_)); } } // namespace testing diff --git a/engine/src/flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h b/engine/src/flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h index e17d3c79422..da7f3fb27f0 100644 --- a/engine/src/flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h +++ b/engine/src/flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h @@ -31,6 +31,9 @@ class FlutterWindowsEngineBuilder { void SetSwitches(std::vector switches); + void SetWindowsProcTable( + std::shared_ptr windows_proc_table); + std::unique_ptr Build(); private: @@ -41,6 +44,7 @@ class FlutterWindowsEngineBuilder { std::vector switches_; KeyboardKeyEmbedderHandler::GetKeyStateHandler get_key_state_; KeyboardKeyEmbedderHandler::MapVirtualKeyToScanCode map_vk_to_scan_; + std::shared_ptr windows_proc_table_; FML_DISALLOW_COPY_AND_ASSIGN(FlutterWindowsEngineBuilder); }; diff --git a/engine/src/flutter/shell/platform/windows/testing/mock_window_binding_handler.h b/engine/src/flutter/shell/platform/windows/testing/mock_window_binding_handler.h index bcecbd8b4e4..cea349ab692 100644 --- a/engine/src/flutter/shell/platform/windows/testing/mock_window_binding_handler.h +++ b/engine/src/flutter/shell/platform/windows/testing/mock_window_binding_handler.h @@ -38,7 +38,6 @@ class MockWindowBindingHandler : public WindowBindingHandler { (const void* allocation, size_t row_bytes, size_t height), (override)); MOCK_METHOD(PointerLocation, GetPrimaryPointerLocation, (), (override)); - MOCK_METHOD(void, SendInitialAccessibilityFeatures, (), (override)); MOCK_METHOD(AlertPlatformNodeDelegate*, GetAlertDelegate, (), (override)); MOCK_METHOD(ui::AXPlatformNodeWin*, GetAlert, (), (override)); MOCK_METHOD(bool, NeedsVSync, (), (override)); diff --git a/engine/src/flutter/shell/platform/windows/testing/mock_window_binding_handler_delegate.h b/engine/src/flutter/shell/platform/windows/testing/mock_window_binding_handler_delegate.h index 2e1ed22c203..81c58abceba 100644 --- a/engine/src/flutter/shell/platform/windows/testing/mock_window_binding_handler_delegate.h +++ b/engine/src/flutter/shell/platform/windows/testing/mock_window_binding_handler_delegate.h @@ -68,7 +68,7 @@ class MockWindowBindingHandlerDelegate : public WindowBindingHandlerDelegate { (double, double, double, double, int, FlutterPointerDeviceKind, int32_t), (override)); MOCK_METHOD(void, OnScrollInertiaCancel, (int32_t), (override)); - MOCK_METHOD(void, UpdateHighContrastEnabled, (bool enabled), (override)); + MOCK_METHOD(void, OnHighContrastChanged, (), (override)); MOCK_METHOD(ui::AXFragmentRootDelegateWin*, GetAxFragmentRootDelegate, diff --git a/engine/src/flutter/shell/platform/windows/testing/mock_windows_proc_table.h b/engine/src/flutter/shell/platform/windows/testing/mock_windows_proc_table.h index ec09a6f7bc4..64caf1d504e 100644 --- a/engine/src/flutter/shell/platform/windows/testing/mock_windows_proc_table.h +++ b/engine/src/flutter/shell/platform/windows/testing/mock_windows_proc_table.h @@ -28,6 +28,8 @@ class MockWindowsProcTable : public WindowsProcTable { (DWORD, PULONG, PZZWSTR, PULONG), (const, override)); + MOCK_METHOD(bool, GetHighContrastEnabled, (), (override)); + private: FML_DISALLOW_COPY_AND_ASSIGN(MockWindowsProcTable); }; diff --git a/engine/src/flutter/shell/platform/windows/window_binding_handler.h b/engine/src/flutter/shell/platform/windows/window_binding_handler.h index 2bc28fe2844..698a2c58b97 100644 --- a/engine/src/flutter/shell/platform/windows/window_binding_handler.h +++ b/engine/src/flutter/shell/platform/windows/window_binding_handler.h @@ -98,9 +98,6 @@ class WindowBindingHandler { // coordinates. virtual PointerLocation GetPrimaryPointerLocation() = 0; - // Called to set the initial state of accessibility features - virtual void SendInitialAccessibilityFeatures() = 0; - // Retrieve the delegate for the alert. virtual AlertPlatformNodeDelegate* GetAlertDelegate() = 0; diff --git a/engine/src/flutter/shell/platform/windows/window_binding_handler_delegate.h b/engine/src/flutter/shell/platform/windows/window_binding_handler_delegate.h index 27c5687adf1..a5647662dcb 100644 --- a/engine/src/flutter/shell/platform/windows/window_binding_handler_delegate.h +++ b/engine/src/flutter/shell/platform/windows/window_binding_handler_delegate.h @@ -136,8 +136,8 @@ class WindowBindingHandlerDelegate { // Returns the root view accessibility node, or nullptr if none. virtual gfx::NativeViewAccessible GetNativeViewAccessible() = 0; - // Update the status of the high contrast feature - virtual void UpdateHighContrastEnabled(bool enabled) = 0; + // Update the status of the high contrast feature. + virtual void OnHighContrastChanged() = 0; // Obtain a pointer to the fragment root delegate. // This is required by UIA in order to obtain the fragment root that diff --git a/engine/src/flutter/shell/platform/windows/windows_proc_table.cc b/engine/src/flutter/shell/platform/windows/windows_proc_table.cc index cc8319bb068..2a058460afd 100644 --- a/engine/src/flutter/shell/platform/windows/windows_proc_table.cc +++ b/engine/src/flutter/shell/platform/windows/windows_proc_table.cc @@ -32,4 +32,14 @@ LRESULT WindowsProcTable::GetThreadPreferredUILanguages(DWORD flags, return ::GetThreadPreferredUILanguages(flags, count, languages, length); } +bool WindowsProcTable::GetHighContrastEnabled() { + HIGHCONTRAST high_contrast = {.cbSize = sizeof(HIGHCONTRAST)}; + if (!::SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(HIGHCONTRAST), + &high_contrast, 0)) { + return false; + } + + return high_contrast.dwFlags & HCF_HIGHCONTRASTON; +} + } // namespace flutter diff --git a/engine/src/flutter/shell/platform/windows/windows_proc_table.h b/engine/src/flutter/shell/platform/windows/windows_proc_table.h index f8f6a0c7c53..584d92823ea 100644 --- a/engine/src/flutter/shell/platform/windows/windows_proc_table.h +++ b/engine/src/flutter/shell/platform/windows/windows_proc_table.h @@ -22,7 +22,7 @@ class WindowsProcTable { // Retrieves the pointer type for a specified pointer. // // Used to react differently to touch or pen inputs. Returns false on failure. - // Available in Windows 8 and newer, otherwise returns false. + // Available on Windows 8 and newer, otherwise returns false. virtual BOOL GetPointerType(UINT32 pointer_id, POINTER_INPUT_TYPE* pointer_type); @@ -35,6 +35,13 @@ class WindowsProcTable { PZZWSTR languages, PULONG length) const; + // Get whether high contrast is enabled. + // + // Available on Windows 8 and newer, otherwise returns false. + // See + // https://learn.microsoft.com/windows/win32/winauto/high-contrast-parameter + virtual bool GetHighContrastEnabled(); + private: using GetPointerType_ = BOOL __stdcall(UINT32 pointerId, POINTER_INPUT_TYPE* pointerType);