Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Move ownership of AccessibilityBridgeWindows to FlutterWindowsView #41308

Merged
merged 9 commits into from
Apr 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions shell/platform/windows/accessibility_bridge_windows.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,8 @@

namespace flutter {

AccessibilityBridgeWindows::AccessibilityBridgeWindows(
FlutterWindowsEngine* engine,
FlutterWindowsView* view)
: engine_(engine), view_(view) {
FML_DCHECK(engine_);
AccessibilityBridgeWindows::AccessibilityBridgeWindows(FlutterWindowsView* view)
: view_(view) {
FML_DCHECK(view_);
}

Expand Down Expand Up @@ -168,7 +165,7 @@ void AccessibilityBridgeWindows::DispatchAccessibilityAction(
AccessibilityNodeId target,
FlutterSemanticsAction action,
fml::MallocMapping data) {
engine_->DispatchSemanticsAction(target, action, std::move(data));
view_->GetEngine()->DispatchSemanticsAction(target, action, std::move(data));
}

std::shared_ptr<FlutterPlatformNodeDelegate>
Expand Down
4 changes: 1 addition & 3 deletions shell/platform/windows/accessibility_bridge_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ class FlutterPlatformNodeDelegateWindows;
class AccessibilityBridgeWindows : public AccessibilityBridge,
public ui::AXFragmentRootDelegateWin {
public:
AccessibilityBridgeWindows(FlutterWindowsEngine* engine,
FlutterWindowsView* view);
AccessibilityBridgeWindows(FlutterWindowsView* view);
virtual ~AccessibilityBridgeWindows() = default;

// |AccessibilityBridge|
Expand Down Expand Up @@ -70,7 +69,6 @@ class AccessibilityBridgeWindows : public AccessibilityBridge,
CreateFlutterPlatformNodeDelegate() override;

private:
FlutterWindowsEngine* engine_;
FlutterWindowsView* view_;

FML_DISALLOW_COPY_AND_ASSIGN(AccessibilityBridgeWindows);
Expand Down
39 changes: 18 additions & 21 deletions shell/platform/windows/accessibility_bridge_windows_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class AccessibilityBridgeWindowsSpy : public AccessibilityBridgeWindows {

explicit AccessibilityBridgeWindowsSpy(FlutterWindowsEngine* engine,
FlutterWindowsView* view)
: AccessibilityBridgeWindows(engine, view) {}
: AccessibilityBridgeWindows(view) {}

void DispatchWinAccessibilityEvent(
std::shared_ptr<FlutterPlatformNodeDelegateWindows> node_delegate,
Expand Down Expand Up @@ -71,34 +71,33 @@ class AccessibilityBridgeWindowsSpy : public AccessibilityBridgeWindows {
FML_DISALLOW_COPY_AND_ASSIGN(AccessibilityBridgeWindowsSpy);
};

// A FlutterWindowsEngine whose accessibility bridge is a
// A FlutterWindowsView whose accessibility bridge is an
// AccessibilityBridgeWindowsSpy.
class FlutterWindowsEngineSpy : public FlutterWindowsEngine {
class FlutterWindowsViewSpy : public FlutterWindowsView {
public:
explicit FlutterWindowsEngineSpy(const FlutterProjectBundle& project)
: FlutterWindowsEngine(project) {}
explicit FlutterWindowsViewSpy(std::unique_ptr<WindowBindingHandler> handler)
: FlutterWindowsView(std::move(handler)) {}

protected:
virtual std::shared_ptr<AccessibilityBridgeWindows> CreateAccessibilityBridge(
FlutterWindowsEngine* engine,
FlutterWindowsView* view) override {
return std::make_shared<AccessibilityBridgeWindowsSpy>(engine, view);
virtual std::shared_ptr<AccessibilityBridgeWindows>
CreateAccessibilityBridge() override {
return std::make_shared<AccessibilityBridgeWindowsSpy>(GetEngine(), this);
}

private:
FML_DISALLOW_COPY_AND_ASSIGN(FlutterWindowsEngineSpy);
FML_DISALLOW_COPY_AND_ASSIGN(FlutterWindowsViewSpy);
};

// Returns an engine instance configured with dummy project path values, and
// overridden methods for sending platform messages, so that the engine can
// respond as if the framework were connected.
std::unique_ptr<FlutterWindowsEngineSpy> GetTestEngine() {
std::unique_ptr<FlutterWindowsEngine> GetTestEngine() {
FlutterDesktopEngineProperties properties = {};
properties.assets_path = L"C:\\foo\\flutter_assets";
properties.icu_data_path = L"C:\\foo\\icudtl.dat";
properties.aot_library_path = L"C:\\foo\\aot.so";
FlutterProjectBundle project(properties);
auto engine = std::make_unique<FlutterWindowsEngineSpy>(project);
auto engine = std::make_unique<FlutterWindowsEngine>(project);

EngineModifier modifier(engine.get());
modifier.embedder_api().UpdateSemanticsEnabled =
Expand Down Expand Up @@ -167,18 +166,16 @@ ui::AXNode* AXNodeFromID(std::shared_ptr<AccessibilityBridge> bridge,

std::shared_ptr<AccessibilityBridgeWindowsSpy> GetAccessibilityBridgeSpy(
FlutterWindowsEngine* engine) {
FlutterWindowsEngineSpy* engine_spy =
static_cast<FlutterWindowsEngineSpy*>(engine);
return std::static_pointer_cast<AccessibilityBridgeWindowsSpy>(
engine_spy->accessibility_bridge().lock());
engine->accessibility_bridge().lock());
}

void ExpectWinEventFromAXEvent(int32_t node_id,
ui::AXEventGenerator::Event ax_event,
ax::mojom::Event expected_event) {
auto window_binding_handler =
std::make_unique<::testing::NiceMock<MockWindowBindingHandler>>();
FlutterWindowsView view(std::move(window_binding_handler));
FlutterWindowsViewSpy view(std::move(window_binding_handler));
view.SetEngine(GetTestEngine());
view.OnUpdateSemanticsEnabled(true);

Expand All @@ -197,7 +194,7 @@ void ExpectWinEventFromAXEvent(int32_t node_id,
TEST(AccessibilityBridgeWindows, GetParent) {
auto window_binding_handler =
std::make_unique<::testing::NiceMock<MockWindowBindingHandler>>();
FlutterWindowsView view(std::move(window_binding_handler));
FlutterWindowsViewSpy view(std::move(window_binding_handler));
view.SetEngine(GetTestEngine());
view.OnUpdateSemanticsEnabled(true);

Expand All @@ -213,7 +210,7 @@ TEST(AccessibilityBridgeWindows, GetParent) {
TEST(AccessibilityBridgeWindows, GetParentOnRootRetunsNullptr) {
auto window_binding_handler =
std::make_unique<::testing::NiceMock<MockWindowBindingHandler>>();
FlutterWindowsView view(std::move(window_binding_handler));
FlutterWindowsViewSpy view(std::move(window_binding_handler));
view.SetEngine(GetTestEngine());
view.OnUpdateSemanticsEnabled(true);

Expand All @@ -227,7 +224,7 @@ TEST(AccessibilityBridgeWindows, GetParentOnRootRetunsNullptr) {
TEST(AccessibilityBridgeWindows, DispatchAccessibilityAction) {
auto window_binding_handler =
std::make_unique<::testing::NiceMock<MockWindowBindingHandler>>();
FlutterWindowsView view(std::move(window_binding_handler));
FlutterWindowsViewSpy view(std::move(window_binding_handler));
view.SetEngine(GetTestEngine());
view.OnUpdateSemanticsEnabled(true);

Expand All @@ -245,7 +242,7 @@ TEST(AccessibilityBridgeWindows, DispatchAccessibilityAction) {
return kSuccess;
}));

AccessibilityBridgeWindows delegate(view.GetEngine(), &view);
AccessibilityBridgeWindows delegate(&view);
delegate.DispatchAccessibilityAction(1, kFlutterSemanticsActionCopy, {});
EXPECT_EQ(actual_action, kFlutterSemanticsActionCopy);
}
Expand All @@ -263,7 +260,7 @@ TEST(AccessibilityBridgeWindows, OnAccessibilityEventChildrenChanged) {
TEST(AccessibilityBridgeWindows, OnAccessibilityEventFocusChanged) {
auto window_binding_handler =
std::make_unique<::testing::NiceMock<MockWindowBindingHandler>>();
FlutterWindowsView view(std::move(window_binding_handler));
FlutterWindowsViewSpy view(std::move(window_binding_handler));
view.SetEngine(GetTestEngine());
view.OnUpdateSemanticsEnabled(true);

Expand Down
34 changes: 16 additions & 18 deletions shell/platform/windows/flutter_windows_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -342,19 +342,22 @@ bool FlutterWindowsEngine::Run(std::string_view entrypoint) {
args.update_semantics_callback2 = [](const FlutterSemanticsUpdate2* update,
void* user_data) {
auto host = static_cast<FlutterWindowsEngine*>(user_data);
auto accessibility_bridge = host->accessibility_bridge().lock();
if (!accessibility_bridge) {
return;
}

for (size_t i = 0; i < update->node_count; i++) {
const FlutterSemanticsNode2* node = update->nodes[i];
host->accessibility_bridge_->AddFlutterSemanticsNodeUpdate(*node);
accessibility_bridge->AddFlutterSemanticsNodeUpdate(*node);
}

for (size_t i = 0; i < update->custom_action_count; i++) {
const FlutterSemanticsCustomAction2* action = update->custom_actions[i];
host->accessibility_bridge_->AddFlutterSemanticsCustomActionUpdate(
*action);
accessibility_bridge->AddFlutterSemanticsCustomActionUpdate(*action);
}

host->accessibility_bridge_->CommitUpdates();
accessibility_bridge->CommitUpdates();
};
args.root_isolate_create_callback = [](void* user_data) {
auto host = static_cast<FlutterWindowsEngine*>(user_data);
Expand Down Expand Up @@ -667,21 +670,10 @@ void FlutterWindowsEngine::UpdateSemanticsEnabled(bool enabled) {
if (engine_ && semantics_enabled_ != enabled) {
semantics_enabled_ = enabled;
embedder_api_.UpdateSemanticsEnabled(engine_, enabled);

if (!semantics_enabled_ && accessibility_bridge_) {
accessibility_bridge_.reset();
} else if (semantics_enabled_ && !accessibility_bridge_) {
accessibility_bridge_ = CreateAccessibilityBridge(this, view());
}
view_->UpdateSemanticsEnabled(enabled);
}
}

std::shared_ptr<AccessibilityBridgeWindows>
FlutterWindowsEngine::CreateAccessibilityBridge(FlutterWindowsEngine* engine,
FlutterWindowsView* view) {
return std::make_shared<AccessibilityBridgeWindows>(engine, view);
}

void FlutterWindowsEngine::OnPreEngineRestart() {
// Reset the keyboard's state on hot restart.
if (view_) {
Expand All @@ -690,11 +682,12 @@ void FlutterWindowsEngine::OnPreEngineRestart() {
}

gfx::NativeViewAccessible FlutterWindowsEngine::GetNativeViewAccessible() {
if (!accessibility_bridge_) {
auto bridge = accessibility_bridge().lock();
if (!bridge) {
return nullptr;
}

return accessibility_bridge_->GetChildOfAXFragmentRoot();
return bridge->GetChildOfAXFragmentRoot();
}

std::string FlutterWindowsEngine::GetExecutableName() const {
Expand Down Expand Up @@ -776,4 +769,9 @@ void FlutterWindowsEngine::OnQuit(std::optional<HWND> hwnd,
lifecycle_manager_->Quit(hwnd, wparam, lparam, exit_code);
}

std::weak_ptr<AccessibilityBridgeWindows>
FlutterWindowsEngine::accessibility_bridge() {
return view_->accessibility_bridge();
}

} // namespace flutter
15 changes: 2 additions & 13 deletions shell/platform/windows/flutter_windows_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,8 @@ class FlutterWindowsEngine {
// rendering using software instead of OpenGL.
AngleSurfaceManager* surface_manager() { return surface_manager_.get(); }

std::weak_ptr<AccessibilityBridgeWindows> accessibility_bridge() {
return accessibility_bridge_;
}
// Return the AccessibilityBridgeWindows for this engine's view.
std::weak_ptr<AccessibilityBridgeWindows> accessibility_bridge();

WindowProcDelegateManager* window_proc_delegate_manager() {
return window_proc_delegate_manager_.get();
Expand Down Expand Up @@ -284,14 +283,6 @@ class FlutterWindowsEngine {
virtual std::unique_ptr<TextInputPlugin> CreateTextInputPlugin(
BinaryMessenger* messenger);

// Creates an accessibility bridge with the provided parameters.
//
// By default this method calls AccessibilityBridge's constructor. Exposing
// this method allows unit tests to override in order to capture information.
virtual std::shared_ptr<AccessibilityBridgeWindows> CreateAccessibilityBridge(
FlutterWindowsEngine* engine,
FlutterWindowsView* view);

// Invoked by the engine right before the engine is restarted.
//
// This should reset necessary states to as if the engine has just been
Expand Down Expand Up @@ -394,8 +385,6 @@ class FlutterWindowsEngine {

bool high_contrast_enabled_ = false;

std::shared_ptr<AccessibilityBridgeWindows> accessibility_bridge_;

// The manager for WindowProc delegate registration and callbacks.
std::unique_ptr<WindowProcDelegateManager> window_proc_delegate_manager_;

Expand Down
17 changes: 17 additions & 0 deletions shell/platform/windows/flutter_windows_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -644,4 +644,21 @@ ui::AXPlatformNodeWin* FlutterWindowsView::AlertNode() const {
return binding_handler_->GetAlert();
}

std::shared_ptr<AccessibilityBridgeWindows>
FlutterWindowsView::CreateAccessibilityBridge() {
return std::make_shared<AccessibilityBridgeWindows>(this);
}

void FlutterWindowsView::UpdateSemanticsEnabled(bool enabled) {
if (semantics_enabled_ != enabled) {
semantics_enabled_ = enabled;

if (!semantics_enabled_ && accessibility_bridge_) {
accessibility_bridge_.reset();
} else if (semantics_enabled_ && !accessibility_bridge_) {
accessibility_bridge_ = CreateAccessibilityBridge();
}
}
}

} // namespace flutter
15 changes: 15 additions & 0 deletions shell/platform/windows/flutter_windows_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "flutter/shell/platform/common/client_wrapper/include/flutter/plugin_registrar.h"
#include "flutter/shell/platform/common/geometry.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/windows/accessibility_bridge_windows.h"
#include "flutter/shell/platform/windows/angle_surface_manager.h"
#include "flutter/shell/platform/windows/flutter_windows_engine.h"
#include "flutter/shell/platform/windows/public/flutter_windows.h"
Expand Down Expand Up @@ -200,10 +201,21 @@ class FlutterWindowsView : public WindowBindingHandlerDelegate,
// |WindowBindingHandlerDelegate|
virtual ui::AXFragmentRootDelegateWin* GetAxFragmentRootDelegate() override;

// Called to re/set the accessibility bridge pointer.
virtual void UpdateSemanticsEnabled(bool enabled);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The content of this new method could have instead been placed in OnUpdateSemanticsEnabled, which is what calls FlutterWindowsEngine::UpdateSemanticsEnabled. However, once we have multiple views, a call to OnUpdateSemanticsEnabled on a view would not necessarily call it for other views.


std::weak_ptr<AccessibilityBridgeWindows> accessibility_bridge() {
return accessibility_bridge_;
}

protected:
virtual void NotifyWinEventWrapper(ui::AXPlatformNodeWin* node,
ax::mojom::Event event);

// Create an AccessibilityBridgeWindows using this view.
virtual std::shared_ptr<AccessibilityBridgeWindows>
CreateAccessibilityBridge();

private:
// Struct holding the state of an individual pointer. The engine doesn't keep
// track of which buttons have been pressed, so it's the embedding's
Expand Down Expand Up @@ -374,6 +386,9 @@ class FlutterWindowsView : public WindowBindingHandlerDelegate,
// True when flutter's semantics tree is enabled.
bool semantics_enabled_ = false;

// The accessibility bridge associated with this view.
std::shared_ptr<AccessibilityBridgeWindows> accessibility_bridge_;

FML_DISALLOW_COPY_AND_ASSIGN(FlutterWindowsView);
};

Expand Down