From 6487041c750ffad1e9124387db8cf30015cdd831 Mon Sep 17 00:00:00 2001 From: Huan Lin Date: Mon, 7 Oct 2024 20:27:27 -0700 Subject: [PATCH 1/2] [ios][platform_view]delaying recognizer requires forwarding recognizer to fail --- .../ios/framework/Source/FlutterPlatformViews_Internal.mm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm index 5e76654bed179..90c4d42e1dadf 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm @@ -654,14 +654,14 @@ - (instancetype)initWithTarget:(id)target - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer { - // The forwarding gesture recognizer should always get all touch events, so it should not be - // required to fail by any other gesture recognizer. - return otherGestureRecognizer != _forwardingRecognizer && otherGestureRecognizer != self; + // The forwarding gesture recognizer should always get all touch events, so it should not + // require other gesture recognizer to fail. + return otherGestureRecognizer != _forwardingRecognizer; } - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer { - return otherGestureRecognizer == self; + return otherGestureRecognizer == _forwardingRecognizer; } - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { From 7381f377315faadd81d848beff7e85bc1acb56f5 Mon Sep 17 00:00:00 2001 From: Huan Lin Date: Wed, 9 Oct 2024 19:32:36 -0700 Subject: [PATCH 2/2] add tests --- .../Source/FlutterPlatformViewsTest.mm | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm index 904a3eace2564..0013657a6ab33 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm @@ -2782,6 +2782,79 @@ - (void)testFlutterPlatformViewTouchesCancelledEventAreForcedToBeCancelled { flutterPlatformViewsController->Reset(); } +- (void)testFlutterPlatformViewForwardingAndDelayingRecognizerFailureCondition { + flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate; + + flutter::TaskRunners runners(/*label=*/self.name.UTF8String, + /*platform=*/GetDefaultTaskRunner(), + /*raster=*/GetDefaultTaskRunner(), + /*ui=*/GetDefaultTaskRunner(), + /*io=*/GetDefaultTaskRunner()); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + auto platform_view = std::make_unique( + /*delegate=*/mock_delegate, + /*rendering_api=*/mock_delegate.settings_.enable_impeller + ? flutter::IOSRenderingAPI::kMetal + : flutter::IOSRenderingAPI::kSoftware, + /*platform_views_controller=*/flutterPlatformViewsController, + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_jsync_switch=*/std::make_shared()); + + FlutterPlatformViewsTestMockFlutterPlatformFactory* factory = + [[FlutterPlatformViewsTestMockFlutterPlatformFactory alloc] init]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + FlutterResult result = ^(id result) { + }; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); + + XCTAssertNotNil(gMockPlatformView); + + // Find touch inteceptor view + UIView* touchInteceptorView = gMockPlatformView; + while (touchInteceptorView != nil && + ![touchInteceptorView isKindOfClass:[FlutterTouchInterceptingView class]]) { + touchInteceptorView = touchInteceptorView.superview; + } + XCTAssertNotNil(touchInteceptorView); + + // Find ForwardGestureRecognizer + UIGestureRecognizer* forwardingGestureRecognizer = nil; + UIGestureRecognizer* delayingGestureRecognizer = nil; + for (UIGestureRecognizer* gestureRecognizer in touchInteceptorView.gestureRecognizers) { + if ([gestureRecognizer isKindOfClass:NSClassFromString(@"ForwardingGestureRecognizer")]) { + forwardingGestureRecognizer = gestureRecognizer; + } + if ([gestureRecognizer isKindOfClass:NSClassFromString(@"FlutterDelayingGestureRecognizer")]) { + delayingGestureRecognizer = gestureRecognizer; + } + } + UIGestureRecognizer* otherGestureRecognizer = OCMClassMock([UIGestureRecognizer class]); + + id flutterViewContoller = OCMClassMock([FlutterViewController class]); + flutterPlatformViewsController->SetFlutterViewController(flutterViewContoller); + + XCTAssertFalse([delayingGestureRecognizer.delegate + gestureRecognizer:delayingGestureRecognizer + shouldBeRequiredToFailByGestureRecognizer:forwardingGestureRecognizer]); + XCTAssertTrue([delayingGestureRecognizer.delegate gestureRecognizer:delayingGestureRecognizer + shouldBeRequiredToFailByGestureRecognizer:otherGestureRecognizer]); + + XCTAssertTrue([delayingGestureRecognizer.delegate gestureRecognizer:delayingGestureRecognizer + shouldRequireFailureOfGestureRecognizer:forwardingGestureRecognizer]); + XCTAssertFalse([delayingGestureRecognizer.delegate gestureRecognizer:delayingGestureRecognizer + shouldRequireFailureOfGestureRecognizer:otherGestureRecognizer]); + + flutterPlatformViewsController->Reset(); +} + - (void)testFlutterPlatformViewControllerSubmitFrameWithoutFlutterViewNotCrashing { flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;