From 1473eb100e0b9a57f6cf7e3e384f0c1ff1b5a6df Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 25 Jul 2023 14:02:20 -0700 Subject: [PATCH 1/3] fix cleanup review fix test --- .../ios/framework/Source/SemanticsObject.mm | 35 ++++++++-- .../framework/Source/SemanticsObjectTest.mm | 70 +++++++++++++++++++ 2 files changed, 101 insertions(+), 4 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm b/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm index 6e2f9c5a20160..7d0fe4c75d234 100644 --- a/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm @@ -93,6 +93,12 @@ CGRect ConvertRectToGlobal(SemanticsObject* reference, CGRect local_rect) { } // namespace +@interface NSObject (FlutterSemantics) + +- (id)_accessibilityHitTest:(CGPoint)point withEvent:(UIEvent*)event; + +@end + @interface FlutterSwitchSemanticsObject () @property(nonatomic, readonly) UISwitch* nativeSwitch; @end @@ -547,17 +553,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; @@ -573,7 +578,13 @@ - (SemanticsObject*)search:(CGPoint)point { // IOS 16. Overrides this method to focus the first eligiable semantics // object in hit test order. - (id)_accessibilityHitTest:(CGPoint)point withEvent:(UIEvent*)event { - return [self search:point]; + id hittest = [self search:point]; + if (![hittest isKindOfClass:[SemanticsObject class]]) { + // If hittest result is not a SemanticsObject (e.g. PlatformView), + // call the default hittest method to find the hittest result inside the "hittest". + return [(NSObject*)hittest _accessibilityHitTest:point withEvent:event]; + } + return hittest; } // iOS calls this method when this item is swipe-to-focusd in VoiceOver. @@ -879,6 +890,22 @@ - (void)dealloc { [super dealloc]; } +- (id)nativeAccessibility { + return _platformView; +} + +- (id)_accessibilityHitTest:(CGPoint)point withEvent:(UIEvent*)event { + return [_platformView _accessibilityHitTest:point withEvent:event]; +} + +- (BOOL)isFocusable { + return YES; +} + +- (BOOL)isAccessibilityElement { + return NO; +} + #pragma mark - UIAccessibilityContainer overrides - (NSArray*)accessibilityElements { diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm b/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm index 48ebd0063563a..2b9e955e7d740 100644 --- a/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm @@ -89,6 +89,23 @@ void AccessibilityObjectDidLoseFocus(int32_t id) override {} } // namespace } // namespace flutter +@interface FakePlatformView : UIView + +@property(nonatomic, strong, readonly) UIView* subview; + +@end + +@implementation FakePlatformView + +- (id)_accessibilityHitTest:(CGPoint)point withEvent:(UIEvent*)event { + if (_subview) { + _subview = [[UIView alloc] init]; + } + return _subview; +} + +@end + @interface SemanticsObjectTest : XCTestCase @end @@ -203,6 +220,59 @@ - (void)testAccessibilityHitTestNoFocusableItem { XCTAssertNil(hitTestResult); } +- (void)testAccessibilityHitTestSearchPlatformViewSubtree { + fml::WeakPtrFactory factory( + new flutter::MockAccessibilityBridge()); + fml::WeakPtr 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]; + FakePlatformView* platformView = + [[FakePlatformView 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 partialMockPlatformView = OCMPartialMock(platformView); + // OCMStub([partialMockPlatformView _accessibilityHitTest:point + // withEvent:nil]).andReturn(subView); + id hitTestResult = [object0 _accessibilityHitTest:point withEvent:nil]; + + // Focus to object2 because it's the first object in hit test order + XCTAssertEqual(hitTestResult, platformView.subview); +} + - (void)testAccessibilityScrollToVisible { fml::WeakPtrFactory factory( new flutter::MockAccessibilityBridge()); From c1d3fd0885fec72ca0eb34cdaa793960558ee531 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 1 Aug 2023 13:36:41 -0700 Subject: [PATCH 2/3] fix --- .../ios/framework/Source/SemanticsObject.mm | 28 +++---------------- .../framework/Source/SemanticsObjectTest.mm | 28 ++----------------- 2 files changed, 7 insertions(+), 49 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm b/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm index 7d0fe4c75d234..7221a35c7b86a 100644 --- a/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm @@ -93,12 +93,6 @@ CGRect ConvertRectToGlobal(SemanticsObject* reference, CGRect local_rect) { } // namespace -@interface NSObject (FlutterSemantics) - -- (id)_accessibilityHitTest:(CGPoint)point withEvent:(UIEvent*)event; - -@end - @interface FlutterSwitchSemanticsObject () @property(nonatomic, readonly) UISwitch* nativeSwitch; @end @@ -578,13 +572,7 @@ - (id)search:(CGPoint)point { // IOS 16. Overrides this method to focus the first eligiable semantics // object in hit test order. - (id)_accessibilityHitTest:(CGPoint)point withEvent:(UIEvent*)event { - id hittest = [self search:point]; - if (![hittest isKindOfClass:[SemanticsObject class]]) { - // If hittest result is not a SemanticsObject (e.g. PlatformView), - // call the default hittest method to find the hittest result inside the "hittest". - return [(NSObject*)hittest _accessibilityHitTest:point withEvent:event]; - } - return hittest; + return [self search:point]; } // iOS calls this method when this item is swipe-to-focusd in VoiceOver. @@ -890,17 +878,9 @@ - (void)dealloc { [super dealloc]; } -- (id)nativeAccessibility { - return _platformView; -} - -- (id)_accessibilityHitTest:(CGPoint)point withEvent:(UIEvent*)event { - return [_platformView _accessibilityHitTest:point withEvent:event]; -} - -- (BOOL)isFocusable { - return YES; -} +// - (id)nativeAccessibility { +// return _platformView; +// } - (BOOL)isAccessibilityElement { return NO; diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm b/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm index 2b9e955e7d740..c2200af6a6881 100644 --- a/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm @@ -89,23 +89,6 @@ void AccessibilityObjectDidLoseFocus(int32_t id) override {} } // namespace } // namespace flutter -@interface FakePlatformView : UIView - -@property(nonatomic, strong, readonly) UIView* subview; - -@end - -@implementation FakePlatformView - -- (id)_accessibilityHitTest:(CGPoint)point withEvent:(UIEvent*)event { - if (_subview) { - _subview = [[UIView alloc] init]; - } - return _subview; -} - -@end - @interface SemanticsObjectTest : XCTestCase @end @@ -220,15 +203,14 @@ - (void)testAccessibilityHitTestNoFocusableItem { XCTAssertNil(hitTestResult); } -- (void)testAccessibilityHitTestSearchPlatformViewSubtree { +- (void)testAccessibilityHitTestSearchCanReturnPlatformView { fml::WeakPtrFactory factory( new flutter::MockAccessibilityBridge()); fml::WeakPtr 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]; - FakePlatformView* platformView = - [[FakePlatformView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; + UIView* platformView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; FlutterPlatformViewSemanticsContainer* platformViewSemanticsContainer = [[FlutterPlatformViewSemanticsContainer alloc] initWithBridge:bridge uid:1 @@ -264,13 +246,9 @@ - (void)testAccessibilityHitTestSearchPlatformViewSubtree { [object3 setSemanticsNode:&node3]; CGPoint point = CGPointMake(10, 10); - // id partialMockPlatformView = OCMPartialMock(platformView); - // OCMStub([partialMockPlatformView _accessibilityHitTest:point - // withEvent:nil]).andReturn(subView); id hitTestResult = [object0 _accessibilityHitTest:point withEvent:nil]; - // Focus to object2 because it's the first object in hit test order - XCTAssertEqual(hitTestResult, platformView.subview); + XCTAssertEqual(hitTestResult, platformView); } - (void)testAccessibilityScrollToVisible { From e06ae311124abdea2b385cab51604cd04295d108 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Tue, 1 Aug 2023 13:41:55 -0700 Subject: [PATCH 3/3] fix --- .../darwin/ios/framework/Source/SemanticsObject.mm | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm b/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm index 7221a35c7b86a..5889a32463892 100644 --- a/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm @@ -878,12 +878,8 @@ - (void)dealloc { [super dealloc]; } -// - (id)nativeAccessibility { -// return _platformView; -// } - -- (BOOL)isAccessibilityElement { - return NO; +- (id)nativeAccessibility { + return _platformView; } #pragma mark - UIAccessibilityContainer overrides