Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 016206d

Browse files
authored
Support accessibility back gesture to pop route from view controller (#51241)
Adapted suggestion from flutter/flutter#74246 (comment) to pop the route if the view controller route if `accessibilityPerformEscape` is called at that level in the responder chain. Ideally this could know if the route was successfully popped, and only then return `YES` (halting propagation through the responder chain). I confirmed by editing https://docs.flutter.dev/cookbook/navigation/navigation-basics#interactive-example as a demo that that the two-finger scrub (move two fingers back and forth three times quickly, making a "z") navigates back to the last route, and that the [`SementicObject`](https://github.com/flutter/engine/blob/88882292c952d76069cee67d76acc0fbae51c749/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm#L763) scrub, which already worked, continued to work. I'm not super familiar with this code, hopefully there aren't further gotchas I'm not thinking of. Fixes flutter/flutter#74246 [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent ad75e93 commit 016206d

File tree

4 files changed

+26
-5
lines changed

4 files changed

+26
-5
lines changed

shell/platform/darwin/ios/framework/Source/FlutterViewController.mm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2104,6 +2104,15 @@ - (int32_t)accessibilityFlags {
21042104
return flags;
21052105
}
21062106

2107+
- (BOOL)accessibilityPerformEscape {
2108+
FlutterMethodChannel* navigationChannel = [_engine.get() navigationChannel];
2109+
if (navigationChannel) {
2110+
[self popRoute];
2111+
return YES;
2112+
}
2113+
return NO;
2114+
}
2115+
21072116
+ (BOOL)accessibilityIsOnOffSwitchLabelsEnabled {
21082117
if (@available(iOS 13, *)) {
21092118
return UIAccessibilityIsOnOffSwitchLabelsEnabled();

shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,6 +1365,22 @@ - (void)testItReportsAccessibilityOnOffSwitchLabelsFlagSet {
13651365
XCTAssert((flags & (int32_t)flutter::AccessibilityFeatureFlag::kOnOffSwitchLabels) != 0);
13661366
}
13671367

1368+
- (void)testAccessibilityPerformEscapePopsRoute {
1369+
FlutterEngine* mockEngine = OCMPartialMock([[FlutterEngine alloc] init]);
1370+
[mockEngine createShell:@"" libraryURI:@"" initialRoute:nil];
1371+
id mockNavigationChannel = OCMClassMock([FlutterMethodChannel class]);
1372+
OCMStub([mockEngine navigationChannel]).andReturn(mockNavigationChannel);
1373+
1374+
FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:mockEngine
1375+
nibName:nil
1376+
bundle:nil];
1377+
XCTAssertTrue([viewController accessibilityPerformEscape]);
1378+
1379+
OCMVerify([mockNavigationChannel invokeMethod:@"popRoute" arguments:nil]);
1380+
1381+
[mockNavigationChannel stopMocking];
1382+
}
1383+
13681384
- (void)testPerformOrientationUpdateForcesOrientationChange {
13691385
[self orientationTestWithOrientationUpdate:UIInterfaceOrientationMaskPortrait
13701386
currentOrientation:UIInterfaceOrientationLandscapeLeft

testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050
0AC232F724BA71D300A85907 /* FlutterEngineTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterEngineTest.mm; sourceTree = "<group>"; };
5151
0AC2330324BA71D300A85907 /* accessibility_bridge_test.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = accessibility_bridge_test.mm; sourceTree = "<group>"; };
5252
0AC2330B24BA71D300A85907 /* FlutterTextInputPluginTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterTextInputPluginTest.mm; sourceTree = "<group>"; };
53-
0AC2330F24BA71D300A85907 /* FlutterBinaryMessengerRelayTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterBinaryMessengerRelayTest.mm; sourceTree = "<group>"; };
5453
0AC2331024BA71D300A85907 /* connection_collection_test.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = connection_collection_test.mm; sourceTree = "<group>"; };
5554
0AC2331224BA71D300A85907 /* FlutterEnginePlatformViewTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterEnginePlatformViewTest.mm; sourceTree = "<group>"; };
5655
0AC2331924BA71D300A85907 /* FlutterPluginAppLifeCycleDelegateTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterPluginAppLifeCycleDelegateTest.mm; sourceTree = "<group>"; };
@@ -72,7 +71,6 @@
7271
3DD7D38C27D2B81000DA365C /* FlutterUndoManagerPluginTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterUndoManagerPluginTest.mm; sourceTree = "<group>"; };
7372
689EC1E2281B30D3008FEB58 /* FlutterSpellCheckPluginTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterSpellCheckPluginTest.mm; sourceTree = "<group>"; };
7473
68B6091227F62F990036AC78 /* VsyncWaiterIosTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = VsyncWaiterIosTest.mm; sourceTree = "<group>"; };
75-
73F12C22288F92FF00AFC3A6 /* FlutterViewControllerTest_mrc.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterViewControllerTest_mrc.mm; sourceTree = "<group>"; };
7674
D2D361A52B234EAC0018964E /* FlutterMetalLayerTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterMetalLayerTest.mm; sourceTree = "<group>"; };
7775
F7521D7226BB671E005F15C5 /* libios_test_flutter.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libios_test_flutter.dylib; path = "../../../../out/$(FLUTTER_ENGINE)/libios_test_flutter.dylib"; sourceTree = "<group>"; };
7876
F7521D7526BB673E005F15C5 /* libocmock_shared.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libocmock_shared.dylib; path = "../../../../out/$(FLUTTER_ENGINE)/libocmock_shared.dylib"; sourceTree = "<group>"; };
@@ -109,12 +107,10 @@
109107
0AC232F724BA71D300A85907 /* FlutterEngineTest.mm */,
110108
0AC2330324BA71D300A85907 /* accessibility_bridge_test.mm */,
111109
0AC2330B24BA71D300A85907 /* FlutterTextInputPluginTest.mm */,
112-
0AC2330F24BA71D300A85907 /* FlutterBinaryMessengerRelayTest.mm */,
113110
0AC2331024BA71D300A85907 /* connection_collection_test.mm */,
114111
0AC2331224BA71D300A85907 /* FlutterEnginePlatformViewTest.mm */,
115112
0AC2331924BA71D300A85907 /* FlutterPluginAppLifeCycleDelegateTest.mm */,
116113
0AC2332124BA71D300A85907 /* FlutterViewControllerTest.mm */,
117-
73F12C22288F92FF00AFC3A6 /* FlutterViewControllerTest_mrc.mm */,
118114
D2D361A52B234EAC0018964E /* FlutterMetalLayerTest.mm */,
119115
);
120116
name = Source;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
FLUTTER_ENGINE[arch=x86_64]=ios_debug_sim_unopt
22
FLUTTER_ENGINE[arch=arm64]=ios_debug_sim_unopt_arm64
3-
FLUTTER_ENGINE=ios_debug_sim_unopt
3+
FLUTTER_ENGINE=ios_debug_sim_unopt_arm64

0 commit comments

Comments
 (0)