mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Move ownership of AccessibilityBridgeWindows to FlutterWindowsView (flutter/engine#41308)
Move ownership of the pointer to `AccessibilityBridgeWindows` from `FlutterWindowsEngine` to `FlutterWindowsView` in preparation for multi-window. https://github.com/flutter/flutter/issues/124995 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide] and the [C++, Objective-C, Java style guides]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test-exempt. See [testing the engine] for instructions on writing and running engine tests. - [x] I updated/added relevant documentation (doc comments with `///`). - [ ] I signed the [CLA]. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style [testing the engine]: https://github.com/flutter/flutter/wiki/Testing-the-engine [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat
This commit is contained in:
parent
57773fc8af
commit
690791e88a
@ -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_);
|
||||
}
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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|
|
||||
@ -70,7 +69,6 @@ class AccessibilityBridgeWindows : public AccessibilityBridge,
|
||||
CreateFlutterPlatformNodeDelegate() override;
|
||||
|
||||
private:
|
||||
FlutterWindowsEngine* engine_;
|
||||
FlutterWindowsView* view_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(AccessibilityBridgeWindows);
|
||||
|
||||
@ -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,
|
||||
@ -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 =
|
||||
@ -167,10 +166,8 @@ 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,
|
||||
@ -178,7 +175,7 @@ void ExpectWinEventFromAXEvent(int32_t node_id,
|
||||
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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
@ -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_) {
|
||||
@ -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 {
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
@ -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
|
||||
@ -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_;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"
|
||||
@ -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);
|
||||
|
||||
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
|
||||
@ -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);
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user