diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 63a8c7515baec..d5cee1934690d 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -817,7 +817,6 @@ - (void)dealloc { - (void)applicationBecameActive:(NSNotification*)notification { TRACE_EVENT0("flutter", "applicationBecameActive"); - self.view.accessibilityElementsHidden = NO; if (_viewportMetrics.physical_width) { [self surfaceUpdated:YES]; } @@ -826,7 +825,6 @@ - (void)applicationBecameActive:(NSNotification*)notification { - (void)applicationWillResignActive:(NSNotification*)notification { TRACE_EVENT0("flutter", "applicationWillResignActive"); - self.view.accessibilityElementsHidden = YES; [self goToApplicationLifecycle:@"AppLifecycleState.inactive"]; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm index 24d194fa86971..207d2379e3a84 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm @@ -932,7 +932,7 @@ - (void)testHideOverlay { engine.viewController = nil; } -- (void)testHideA11yElements { +- (void)testDoNotHideA11yElements { FlutterDartProject* project = [[FlutterDartProject alloc] init]; FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"foobar" project:project]; [engine createShell:@"" libraryURI:@"" initialRoute:nil]; @@ -943,7 +943,7 @@ - (void)testHideA11yElements { [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationWillResignActiveNotification object:nil]; - XCTAssertTrue(realVC.view.accessibilityElementsHidden); + XCTAssertFalse(realVC.view.accessibilityElementsHidden); [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationDidBecomeActiveNotification object:nil]; diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm index 3deec8958c432..72ab0b75e5697 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm +++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm @@ -200,8 +200,8 @@ void PostAccessibilityNotification(UIAccessibilityNotifications notification, for (SemanticsObject* object in [objects_ allValues]) { [object accessibilityBridgeDidFinishUpdate]; } - - if (!ios_delegate_->IsFlutterViewControllerPresentingModalViewController(view_controller_)) { + if (!ios_delegate_->IsFlutterViewControllerPresentingModalViewController(view_controller_) && + [UIApplication sharedApplication].applicationState == UIApplicationStateActive) { layoutChanged = layoutChanged || [doomed_uids count] > 0; if (routeChanged) { diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm b/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm index 096af929bbbf6..544a0f95128ae 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm +++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm @@ -1618,6 +1618,67 @@ - (void)testAnnouncesIgnoresLayoutChangeWhenModal { XCTAssertEqual([accessibility_notifications count], 0ul); } +- (void)testAnnouncesIgnoresLayoutChangeWhenApplicationIsInactive { + flutter::MockDelegate mock_delegate; + auto thread_task_runner = CreateNewThread("AccessibilityBridgeTest"); + flutter::TaskRunners runners(/*label=*/self.name.UTF8String, + /*platform=*/thread_task_runner, + /*raster=*/thread_task_runner, + /*ui=*/thread_task_runner, + /*io=*/thread_task_runner); + auto platform_view = std::make_unique( + /*delegate=*/mock_delegate, + /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware, + /*platform_views_controller=*/nil, + /*task_runners=*/runners); + id mockFlutterView = OCMClassMock([FlutterView class]); + id mockFlutterViewController = OCMClassMock([FlutterViewController class]); + OCMStub([mockFlutterViewController view]).andReturn(mockFlutterView); + + NSMutableArray*>* accessibility_notifications = + [[[NSMutableArray alloc] init] autorelease]; + auto ios_delegate = std::make_unique(); + ios_delegate->on_PostAccessibilityNotification_ = + [accessibility_notifications](UIAccessibilityNotifications notification, id argument) { + [accessibility_notifications addObject:@{ + @"notification" : @(notification), + @"argument" : argument ? argument : [NSNull null], + }]; + }; + __block auto bridge = + std::make_unique(/*view_controller=*/mockFlutterViewController, + /*platform_view=*/platform_view.get(), + /*platform_views_controller=*/nil, + /*ios_delegate=*/std::move(ios_delegate)); + id mockApplication = OCMPartialMock([UIApplication sharedApplication]); + OCMStub([mockApplication applicationState]).andReturn(UIApplicationStateInactive); + + flutter::CustomAccessibilityActionUpdates actions; + flutter::SemanticsNodeUpdates nodes; + + flutter::SemanticsNode child_node; + child_node.id = 1; + child_node.label = "child_node"; + nodes[child_node.id] = child_node; + flutter::SemanticsNode root_node; + root_node.id = kRootNodeId; + root_node.label = "root"; + root_node.childrenInTraversalOrder = {1}; + root_node.childrenInHitTestOrder = {1}; + nodes[root_node.id] = root_node; + bridge->UpdateSemantics(/*nodes=*/nodes, /*actions=*/actions); + + // Removes child_node to simulate a layout change. + flutter::SemanticsNodeUpdates new_nodes; + flutter::SemanticsNode new_root_node; + new_root_node.id = kRootNodeId; + new_root_node.label = "root"; + new_nodes[new_root_node.id] = new_root_node; + bridge->UpdateSemantics(/*nodes=*/new_nodes, /*actions=*/actions); + + XCTAssertEqual([accessibility_notifications count], 0ul); +} + - (void)testAnnouncesIgnoresScrollChangeWhenModal { flutter::MockDelegate mock_delegate; auto thread_task_runner = CreateNewThread("AccessibilityBridgeTest");