未验证 提交 d36c65c9 编写于 作者: G gaaclarke 提交者: GitHub

refactored the accessibility bridge to have a view controller instead of a view (#18800)

上级 c2d3ca6f
......@@ -18,6 +18,7 @@
#include "flutter/lib/ui/semantics/custom_accessibility_action.h"
#include "flutter/lib/ui/semantics/semantics_node.h"
#include "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h"
#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/SemanticsObject.h"
......@@ -42,12 +43,13 @@ class AccessibilityBridge final : public AccessibilityBridgeIos {
virtual ~IosDelegate() = default;
/// Returns true when the FlutterViewController associated with the `view`
/// is presenting a modal view controller.
virtual bool IsFlutterViewControllerPresentingModalViewController(UIView* view) = 0;
virtual bool IsFlutterViewControllerPresentingModalViewController(
FlutterViewController* view_controller) = 0;
virtual void PostAccessibilityNotification(UIAccessibilityNotifications notification,
id argument) = 0;
};
AccessibilityBridge(UIView* view,
AccessibilityBridge(FlutterViewController* view_controller,
PlatformViewIOS* platform_view,
FlutterPlatformViewsController* platform_views_controller,
std::unique_ptr<IosDelegate> ios_delegate = nullptr);
......@@ -62,7 +64,7 @@ class AccessibilityBridge final : public AccessibilityBridgeIos {
UIView<UITextInput>* textInputView() override;
UIView* view() const override { return view_; }
UIView* view() const override { return view_controller_.view; }
fml::WeakPtr<AccessibilityBridge> GetWeakPtr();
......@@ -78,7 +80,7 @@ class AccessibilityBridge final : public AccessibilityBridgeIos {
NSMutableArray<NSNumber*>* doomed_uids);
void HandleEvent(NSDictionary<NSString*, id>* annotatedEvent);
UIView* view_;
FlutterViewController* view_controller_;
PlatformViewIOS* platform_view_;
FlutterPlatformViewsController* platform_views_controller_;
fml::scoped_nsobject<NSMutableDictionary<NSNumber*, SemanticsObject*>> objects_;
......
......@@ -16,27 +16,12 @@ FLUTTER_ASSERT_NOT_ARC
namespace flutter {
namespace {
FlutterViewController* _Nullable GetFlutterViewControllerForView(UIView* view) {
// There is no way to get a view's view controller in UIKit directly, this is
// somewhat of a hacky solution to get that. This could be eliminated if the
// bridge actually kept a reference to a FlutterViewController instead of a
// UIView.
id nextResponder = [view nextResponder];
if ([nextResponder isKindOfClass:[FlutterViewController class]]) {
return nextResponder;
} else if ([nextResponder isKindOfClass:[UIView class]]) {
return GetFlutterViewControllerForView(nextResponder);
} else {
return nil;
}
}
class DefaultIosDelegate : public AccessibilityBridge::IosDelegate {
public:
bool IsFlutterViewControllerPresentingModalViewController(UIView* view) override {
FlutterViewController* viewController = GetFlutterViewControllerForView(view);
if (viewController) {
return viewController.isPresentingViewController;
bool IsFlutterViewControllerPresentingModalViewController(
FlutterViewController* view_controller) override {
if (view_controller) {
return view_controller.isPresentingViewController;
} else {
return false;
}
......@@ -49,11 +34,11 @@ class DefaultIosDelegate : public AccessibilityBridge::IosDelegate {
};
} // namespace
AccessibilityBridge::AccessibilityBridge(UIView* view,
AccessibilityBridge::AccessibilityBridge(FlutterViewController* view_controller,
PlatformViewIOS* platform_view,
FlutterPlatformViewsController* platform_views_controller,
std::unique_ptr<IosDelegate> ios_delegate)
: view_(view),
: view_controller_(view_controller),
platform_view_(platform_view),
platform_views_controller_(platform_views_controller),
objects_([[NSMutableDictionary alloc] init]),
......@@ -74,7 +59,7 @@ AccessibilityBridge::AccessibilityBridge(UIView* view,
AccessibilityBridge::~AccessibilityBridge() {
[accessibility_channel_.get() setMessageHandler:nil];
clearState();
view_.accessibilityElements = nil;
view_controller_.view.accessibilityElements = nil;
}
UIView<UITextInput>* AccessibilityBridge::textInputView() {
......@@ -164,8 +149,8 @@ void AccessibilityBridge::UpdateSemantics(flutter::SemanticsNodeUpdates nodes,
SemanticsObject* lastAdded = nil;
if (root) {
if (!view_.accessibilityElements) {
view_.accessibilityElements = @[ [root accessibilityContainer] ];
if (!view_controller_.view.accessibilityElements) {
view_controller_.view.accessibilityElements = @[ [root accessibilityContainer] ];
}
NSMutableArray<SemanticsObject*>* newRoutes = [[[NSMutableArray alloc] init] autorelease];
[root collectRoutes:newRoutes];
......@@ -188,7 +173,7 @@ void AccessibilityBridge::UpdateSemantics(flutter::SemanticsNodeUpdates nodes,
previous_routes_.push_back([route uid]);
}
} else {
view_.accessibilityElements = nil;
view_controller_.view.accessibilityElements = nil;
}
NSMutableArray<NSNumber*>* doomed_uids = [NSMutableArray arrayWithArray:[objects_.get() allKeys]];
......@@ -198,7 +183,7 @@ void AccessibilityBridge::UpdateSemantics(flutter::SemanticsNodeUpdates nodes,
layoutChanged = layoutChanged || [doomed_uids count] > 0;
if (routeChanged) {
if (!ios_delegate_->IsFlutterViewControllerPresentingModalViewController(view_)) {
if (!ios_delegate_->IsFlutterViewControllerPresentingModalViewController(view_controller_)) {
ios_delegate_->PostAccessibilityNotification(UIAccessibilityScreenChangedNotification,
[lastAdded routeFocusObject]);
}
......
......@@ -96,7 +96,8 @@ class MockDelegate : public PlatformView::Delegate {
class MockIosDelegate : public AccessibilityBridge::IosDelegate {
public:
bool IsFlutterViewControllerPresentingModalViewController(UIView* view) override {
bool IsFlutterViewControllerPresentingModalViewController(
FlutterViewController* view_controller) override {
return result_IsFlutterViewControllerPresentingModalViewController_;
};
......@@ -157,9 +158,11 @@ fml::RefPtr<fml::TaskRunner> CreateNewThread(std::string name) {
/*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
/*task_runners=*/runners);
id mockFlutterView = OCMClassMock([FlutterView class]);
id mockFlutterViewController = OCMClassMock([FlutterViewController class]);
OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView);
OCMExpect([mockFlutterView setAccessibilityElements:[OCMArg isNil]]);
auto bridge =
std::make_unique<flutter::AccessibilityBridge>(/*view=*/mockFlutterView,
std::make_unique<flutter::AccessibilityBridge>(/*view_controller=*/mockFlutterViewController,
/*platform_view=*/platform_view.get(),
/*platform_views_controller=*/nil);
flutter::SemanticsNodeUpdates nodes;
......@@ -181,10 +184,12 @@ fml::RefPtr<fml::TaskRunner> CreateNewThread(std::string name) {
/*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
/*task_runners=*/runners);
id mockFlutterView = OCMClassMock([FlutterView class]);
id mockFlutterViewController = OCMClassMock([FlutterViewController class]);
OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView);
std::string label = "some label";
__block auto bridge =
std::make_unique<flutter::AccessibilityBridge>(/*view=*/mockFlutterView,
std::make_unique<flutter::AccessibilityBridge>(/*view_controller=*/mockFlutterViewController,
/*platform_view=*/platform_view.get(),
/*platform_views_controller=*/nil);
......@@ -224,6 +229,8 @@ fml::RefPtr<fml::TaskRunner> CreateNewThread(std::string name) {
/*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
/*task_runners=*/runners);
id mockFlutterView = OCMClassMock([FlutterView class]);
id mockFlutterViewController = OCMClassMock([FlutterViewController class]);
OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView);
std::string label = "some label";
auto flutterPlatformViewsController =
......@@ -243,7 +250,7 @@ fml::RefPtr<fml::TaskRunner> CreateNewThread(std::string name) {
result);
auto bridge = std::make_unique<flutter::AccessibilityBridge>(
/*view=*/mockFlutterView,
/*view_controller=*/mockFlutterViewController,
/*platform_view=*/platform_view.get(),
/*platform_views_controller=*/flutterPlatformViewsController.get());
......@@ -274,6 +281,8 @@ fml::RefPtr<fml::TaskRunner> CreateNewThread(std::string name) {
/*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
/*task_runners=*/runners);
id mockFlutterView = OCMClassMock([FlutterView class]);
id mockFlutterViewController = OCMClassMock([FlutterViewController class]);
OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView);
std::string label = "some label";
NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
......@@ -287,7 +296,7 @@ fml::RefPtr<fml::TaskRunner> CreateNewThread(std::string name) {
}];
};
__block auto bridge =
std::make_unique<flutter::AccessibilityBridge>(/*view=*/mockFlutterView,
std::make_unique<flutter::AccessibilityBridge>(/*view_controller=*/mockFlutterViewController,
/*platform_view=*/platform_view.get(),
/*platform_views_controller=*/nil,
/*ios_delegate=*/std::move(ios_delegate));
......@@ -331,6 +340,8 @@ fml::RefPtr<fml::TaskRunner> CreateNewThread(std::string name) {
/*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
/*task_runners=*/runners);
id mockFlutterView = OCMClassMock([FlutterView class]);
id mockFlutterViewController = OCMClassMock([FlutterViewController class]);
OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView);
std::string label = "some label";
NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
......@@ -345,7 +356,7 @@ fml::RefPtr<fml::TaskRunner> CreateNewThread(std::string name) {
};
ios_delegate->result_IsFlutterViewControllerPresentingModalViewController_ = true;
__block auto bridge =
std::make_unique<flutter::AccessibilityBridge>(/*view=*/mockFlutterView,
std::make_unique<flutter::AccessibilityBridge>(/*view_controller=*/mockFlutterViewController,
/*platform_view=*/platform_view.get(),
/*platform_views_controller=*/nil,
/*ios_delegate=*/std::move(ios_delegate));
......
......@@ -107,9 +107,8 @@ void PlatformViewIOS::attachView() {
FML_DCHECK(ios_surface_ != nullptr);
if (accessibility_bridge_) {
accessibility_bridge_.reset(
new AccessibilityBridge(static_cast<FlutterView*>(owner_controller_.get().view), this,
[owner_controller_.get() platformViewsController]));
accessibility_bridge_.reset(new AccessibilityBridge(
owner_controller_.get(), this, [owner_controller_.get() platformViewsController]));
}
}
......@@ -150,9 +149,8 @@ void PlatformViewIOS::SetSemanticsEnabled(bool enabled) {
return;
}
if (enabled && !accessibility_bridge_) {
accessibility_bridge_.reset(
new AccessibilityBridge(static_cast<FlutterView*>(owner_controller_.get().view), this,
[owner_controller_.get() platformViewsController]));
accessibility_bridge_.reset(new AccessibilityBridge(
owner_controller_.get(), this, [owner_controller_.get() platformViewsController]));
} else if (!enabled && accessibility_bridge_) {
accessibility_bridge_.reset();
} else {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册