Skip to content

Commit

Permalink
[iOS][A11Y] fix hittest with non-SemanticsObject (flutter#44014)
Browse files Browse the repository at this point in the history
PlatformViewSemanticsContainer did not implement the nativeAccessibility method, leads to a nil object being returned. 

Fixes flutter/flutter#131014

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
  • Loading branch information
Chris Yang authored Aug 2, 2023
1 parent c93d7a9 commit 2e0bb5c
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 3 deletions.
9 changes: 6 additions & 3 deletions shell/platform/darwin/ios/framework/Source/SemanticsObject.mm
Original file line number Diff line number Diff line change
Expand Up @@ -547,17 +547,16 @@ - (bool)containsPoint:(CGPoint)point {
}

// Finds the first eligiable semantics object in hit test order.
- (SemanticsObject*)search:(CGPoint)point {
- (id)search:(CGPoint)point {
// Search children in hit test order.
for (SemanticsObject* child in [self childrenInHitTestOrder]) {
if ([child containsPoint:point]) {
SemanticsObject* childSearchResult = [child search:point];
id childSearchResult = [child search:point];
if (childSearchResult != nil) {
return childSearchResult;
}
}
}

// Check if the current semantic object should be returned.
if ([self containsPoint:point] && [self isFocusable]) {
return self.nativeAccessibility;
Expand Down Expand Up @@ -879,6 +878,10 @@ - (void)dealloc {
[super dealloc];
}

- (id)nativeAccessibility {
return _platformView;
}

#pragma mark - UIAccessibilityContainer overrides

- (NSArray*)accessibilityElements {
Expand Down
48 changes: 48 additions & 0 deletions shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,54 @@ - (void)testAccessibilityHitTestNoFocusableItem {
XCTAssertNil(hitTestResult);
}

- (void)testAccessibilityHitTestSearchCanReturnPlatformView {
fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
new flutter::MockAccessibilityBridge());
fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
SemanticsObject* object0 = [[SemanticsObject alloc] initWithBridge:bridge uid:0];
SemanticsObject* object1 = [[SemanticsObject alloc] initWithBridge:bridge uid:1];
SemanticsObject* object3 = [[SemanticsObject alloc] initWithBridge:bridge uid:3];
UIView* platformView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
FlutterPlatformViewSemanticsContainer* platformViewSemanticsContainer =
[[FlutterPlatformViewSemanticsContainer alloc] initWithBridge:bridge
uid:1
platformView:platformView];

object0.children = @[ object1 ];
object0.childrenInHitTestOrder = @[ object1 ];
object1.children = @[ platformViewSemanticsContainer, object3 ];
object1.childrenInHitTestOrder = @[ platformViewSemanticsContainer, object3 ];

flutter::SemanticsNode node0;
node0.id = 0;
node0.rect = SkRect::MakeXYWH(0, 0, 200, 200);
node0.label = "0";
[object0 setSemanticsNode:&node0];

flutter::SemanticsNode node1;
node1.id = 1;
node1.rect = SkRect::MakeXYWH(0, 0, 200, 200);
node1.label = "1";
[object1 setSemanticsNode:&node1];

flutter::SemanticsNode node2;
node2.id = 2;
node2.rect = SkRect::MakeXYWH(0, 0, 100, 100);
node2.label = "2";
[platformViewSemanticsContainer setSemanticsNode:&node2];

flutter::SemanticsNode node3;
node3.id = 3;
node3.rect = SkRect::MakeXYWH(0, 0, 200, 200);
node3.label = "3";
[object3 setSemanticsNode:&node3];

CGPoint point = CGPointMake(10, 10);
id hitTestResult = [object0 _accessibilityHitTest:point withEvent:nil];

XCTAssertEqual(hitTestResult, platformView);
}

- (void)testAccessibilityScrollToVisible {
fml::WeakPtrFactory<flutter::MockAccessibilityBridge> factory(
new flutter::MockAccessibilityBridge());
Expand Down

0 comments on commit 2e0bb5c

Please sign in to comment.