From cead1d64eab68294eae2c20867f1ff0b7f33b682 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 20 Apr 2022 15:33:58 -0700 Subject: [PATCH 1/2] only hide a11y when voice over is on --- .../framework/Headers/FlutterViewController.h | 8 +++++ .../framework/Source/FlutterViewController.mm | 8 ++++- .../Source/FlutterViewControllerTest.mm | 29 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h b/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h index 9f71eeccb1a35..0e3b09f8e059f 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h @@ -179,6 +179,14 @@ FLUTTER_DARWIN_EXPORT */ - (id)pluginRegistry; +/** + * A wrapper around UIAccessibilityIsVoiceOverRunning(). + * + * As a C function, UIAccessibilityIsVoiceOverRunning() cannot be mocked in testing. Mock + * this class method to testing features depends on UIAccessibilityIsVoiceOverRunning(). + */ ++ (BOOL)isUIAccessibilityIsVoiceOverRunning; + /** * True if at least one frame has rendered and the ViewController has appeared. * diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 63a8c7515baec..a324e881c3d17 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -826,7 +826,9 @@ - (void)applicationBecameActive:(NSNotification*)notification { - (void)applicationWillResignActive:(NSNotification*)notification { TRACE_EVENT0("flutter", "applicationWillResignActive"); - self.view.accessibilityElementsHidden = YES; + if ([FlutterViewController isUIAccessibilityIsVoiceOverRunning]) { + self.view.accessibilityElementsHidden = YES; + } [self goToApplicationLifecycle:@"AppLifecycleState.inactive"]; } @@ -1718,6 +1720,10 @@ - (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package { return _engine; } ++ (BOOL)isUIAccessibilityIsVoiceOverRunning { + return UIAccessibilityIsVoiceOverRunning(); +} + #pragma mark - FlutterPluginRegistry - (NSObject*)registrarForPlugin:(NSString*)pluginKey { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm index 24d194fa86971..c663b01ce5b7b 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm @@ -939,6 +939,33 @@ - (void)testHideA11yElements { FlutterViewController* realVC = [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil]; + id flutterViewControllerClassMOCK = OCMClassMock([FlutterViewController class]); + OCMStub([flutterViewControllerClassMOCK isUIAccessibilityIsVoiceOverRunning]).andReturn(@YES); + + XCTAssertFalse(realVC.view.accessibilityElementsHidden); + [[NSNotificationCenter defaultCenter] + postNotificationName:UIApplicationWillResignActiveNotification + object:nil]; + XCTAssertTrue(realVC.view.accessibilityElementsHidden); + [[NSNotificationCenter defaultCenter] + postNotificationName:UIApplicationDidBecomeActiveNotification + object:nil]; + XCTAssertFalse(realVC.view.accessibilityElementsHidden); + engine.viewController = nil; + + [flutterViewControllerClassMOCK stopMocking]; +} + +- (void)testDontHideA11yElementsWhenVoiceOverIsOff { + FlutterDartProject* project = [[FlutterDartProject alloc] init]; + FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"foobar" project:project]; + [engine createShell:@"" libraryURI:@"" initialRoute:nil]; + FlutterViewController* realVC = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + id flutterViewControllerClassMOCK = OCMClassMock([FlutterViewController class]); + OCMStub([flutterViewControllerClassMOCK isUIAccessibilityIsVoiceOverRunning]).andReturn(@NO); + XCTAssertFalse(realVC.view.accessibilityElementsHidden); [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationWillResignActiveNotification @@ -949,6 +976,8 @@ - (void)testHideA11yElements { object:nil]; XCTAssertFalse(realVC.view.accessibilityElementsHidden); engine.viewController = nil; + + [flutterViewControllerClassMOCK stopMocking]; } - (void)testNotifyLowMemory { From 0fabf8ae636ded4a7543b8a3a72bca6fd69119c8 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 20 Apr 2022 15:40:13 -0700 Subject: [PATCH 2/2] fix test --- .../ios/framework/Source/FlutterViewControllerTest.mm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm index c663b01ce5b7b..41cab5ba87148 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm @@ -940,7 +940,7 @@ - (void)testHideA11yElements { nibName:nil bundle:nil]; id flutterViewControllerClassMOCK = OCMClassMock([FlutterViewController class]); - OCMStub([flutterViewControllerClassMOCK isUIAccessibilityIsVoiceOverRunning]).andReturn(@YES); + [[[flutterViewControllerClassMOCK stub] andReturnValue:@YES] isUIAccessibilityIsVoiceOverRunning]; XCTAssertFalse(realVC.view.accessibilityElementsHidden); [[NSNotificationCenter defaultCenter] @@ -964,13 +964,13 @@ - (void)testDontHideA11yElementsWhenVoiceOverIsOff { nibName:nil bundle:nil]; id flutterViewControllerClassMOCK = OCMClassMock([FlutterViewController class]); - OCMStub([flutterViewControllerClassMOCK isUIAccessibilityIsVoiceOverRunning]).andReturn(@NO); + [[[flutterViewControllerClassMOCK stub] andReturnValue:@NO] isUIAccessibilityIsVoiceOverRunning]; XCTAssertFalse(realVC.view.accessibilityElementsHidden); [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationWillResignActiveNotification object:nil]; - XCTAssertTrue(realVC.view.accessibilityElementsHidden); + XCTAssertFalse(realVC.view.accessibilityElementsHidden); [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidBecomeActiveNotification object:nil];