提交 c5602ab1 编写于 作者: M Michael Goderbauer 提交者: GitHub

Three finger a11y scrolling for iOS (#4123)

* Three finger a11y scrolling for iOS

* review comments

* review feedback
上级 bd64e8dc
......@@ -127,8 +127,8 @@ class PlatformMessageResponseDarwin : public blink::PlatformMessageResponse {
_orientationPreferences = UIInterfaceOrientationMaskAll;
_statusBarStyle = UIStatusBarStyleDefault;
_platformView =
std::make_shared<shell::PlatformViewIOS>(reinterpret_cast<CAEAGLLayer*>(self.view.layer));
_platformView = std::make_shared<shell::PlatformViewIOS>(
reinterpret_cast<CAEAGLLayer*>(self.view.layer), self);
_platformView->Attach(
// First frame callback.
......
......@@ -12,6 +12,7 @@
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/lib/ui/semantics/semantics_node.h"
#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h"
#include "lib/fxl/macros.h"
#include "third_party/skia/include/core/SkMatrix44.h"
......@@ -58,10 +59,12 @@ class AccessibilityBridge final {
void VisitObjectsRecursivelyAndRemove(SemanticsObject* object,
NSMutableArray<NSNumber*>* doomed_uids);
void ReleaseObjects(std::unordered_map<int, SemanticsObject*>& objects);
void HandleEvent(NSDictionary<NSString*, id>* annotatedEvent);
UIView* view_;
PlatformViewIOS* platform_view_;
fml::scoped_nsobject<NSMutableDictionary<NSNumber*, SemanticsObject*>> objects_;
fml::scoped_nsprotocol<FlutterBasicMessageChannel*> accessibility_channel_;
FXL_DISALLOW_COPY_AND_ASSIGN(AccessibilityBridge);
};
......
......@@ -240,8 +240,6 @@ bool GeometryComparator(SemanticsObject* a, SemanticsObject* b) {
if (!_node.HasAction(action))
return NO;
_bridge->DispatchSemanticsAction(_uid, action);
// TODO(tvolkert): provide meaningful string (e.g. "page 2 of 5")
UIAccessibilityPostNotification(UIAccessibilityPageScrolledNotification, nil);
return YES;
}
......@@ -320,6 +318,12 @@ bool GeometryComparator(SemanticsObject* a, SemanticsObject* b) {
: [[_semanticsObject parent] accessibilityContainer];
}
#pragma mark - UIAccessibilityAction overrides
- (BOOL)accessibilityScroll:(UIAccessibilityScrollDirection)direction {
return [_semanticsObject accessibilityScroll:direction];
}
@end
#pragma mark - AccessibilityBridge impl
......@@ -327,10 +331,19 @@ bool GeometryComparator(SemanticsObject* a, SemanticsObject* b) {
namespace shell {
AccessibilityBridge::AccessibilityBridge(UIView* view, PlatformViewIOS* platform_view)
: view_(view), platform_view_(platform_view), objects_([[NSMutableDictionary alloc] init]) {}
: view_(view), platform_view_(platform_view), objects_([[NSMutableDictionary alloc] init]) {
accessibility_channel_.reset([[FlutterBasicMessageChannel alloc]
initWithName:@"flutter/accessibility"
binaryMessenger:platform_view->binary_messenger()
codec:[FlutterStandardMessageCodec sharedInstance]]);
[accessibility_channel_.get() setMessageHandler:^(id message, FlutterReply reply) {
HandleEvent((NSDictionary*)message);
}];
}
AccessibilityBridge::~AccessibilityBridge() {
view_.accessibilityElements = nil;
[accessibility_channel_.get() setMessageHandler:nil];
}
void AccessibilityBridge::UpdateSemantics(std::vector<blink::SemanticsNode> nodes) {
......@@ -375,28 +388,10 @@ void AccessibilityBridge::UpdateSemantics(std::vector<blink::SemanticsNode> node
NSMutableArray<NSNumber*>* doomed_uids = [NSMutableArray arrayWithArray:[objects_.get() allKeys]];
if (root)
VisitObjectsRecursivelyAndRemove(root, doomed_uids);
bool focused_object_doomed = false;
for (NSNumber* uid in doomed_uids) {
SemanticsObject* object = objects_.get()[uid];
if ([object accessibilityElementIsFocused]) {
focused_object_doomed = true;
break;
}
}
[objects_ removeObjectsForKeys:doomed_uids];
if (focused_object_doomed) {
// Previously focused element is no longer in the tree.
// Passing `nil` as argument to let iOS figure out what to focus next.
// TODO(goderbauer): Figure out which element should be focused next and post
// UIAccessibilityLayoutChangedNotification with that element instead.
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil);
} else {
// Passing `nil` as argument to keep focus where it is.
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
}
// TODO(goderbauer): figure out which node to focus next.
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
}
void AccessibilityBridge::DispatchSemanticsAction(int32_t uid, blink::SemanticsAction action) {
......@@ -419,4 +414,14 @@ void AccessibilityBridge::VisitObjectsRecursivelyAndRemove(SemanticsObject* obje
VisitObjectsRecursivelyAndRemove(child, doomed_uids);
}
void AccessibilityBridge::HandleEvent(NSDictionary<NSString*, id>* annotatedEvent) {
NSString* type = annotatedEvent[@"type"];
if ([type isEqualToString:@"scroll"]) {
// TODO(tvolkert): provide meaningful string (e.g. "page 2 of 5")
UIAccessibilityPostNotification(UIAccessibilityPageScrolledNotification, @"");
} else {
NSCAssert(NO, @"Invalid event type %@", type);
}
}
} // namespace shell
......@@ -22,7 +22,8 @@ namespace shell {
class PlatformViewIOS : public PlatformView {
public:
explicit PlatformViewIOS(CALayer* layer);
explicit PlatformViewIOS(CALayer* layer,
NSObject<FlutterBinaryMessenger>* binaryMessenger);
~PlatformViewIOS() override;
......@@ -55,12 +56,17 @@ class PlatformViewIOS : public PlatformView {
const std::string& main,
const std::string& packages) override;
NSObject<FlutterBinaryMessenger>* binary_messenger() const {
return binary_messenger_;
}
private:
std::unique_ptr<IOSSurface> ios_surface_;
PlatformMessageRouter platform_message_router_;
std::unique_ptr<AccessibilityBridge> accessibility_bridge_;
fxl::Closure firstFrameCallback_;
fxl::WeakPtrFactory<PlatformViewIOS> weak_factory_;
NSObject<FlutterBinaryMessenger>* binary_messenger_;
void SetupAndLoadFromSource(const std::string& assets_directory,
const std::string& main,
......
......@@ -17,10 +17,11 @@
namespace shell {
PlatformViewIOS::PlatformViewIOS(CALayer* layer)
PlatformViewIOS::PlatformViewIOS(CALayer* layer, NSObject<FlutterBinaryMessenger>* binaryMessenger)
: PlatformView(std::make_unique<GPURasterizer>(std::make_unique<ProcessInfoMac>())),
ios_surface_(IOSSurface::Create(surface_config_, layer)),
weak_factory_(this) {}
weak_factory_(this),
binary_messenger_(binaryMessenger) {}
PlatformViewIOS::~PlatformViewIOS() = default;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册