From 0bc6dc97465934c44353b38456ed91c3ccb037c8 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Fri, 10 May 2019 09:58:33 -0700 Subject: [PATCH] Platform_views gesture: let flutter view controller be the media to pass the touches. (#8685) This PR updated the forwarding gesture recognizer to pass the touch events directly to the FlutterViewContoller instead of FlutterView which ensures the touches events are passed to the framework. --- .../framework/Source/FlutterPlatformViews.mm | 37 ++++++++++++------- .../Source/FlutterPlatformViews_Internal.h | 6 ++- .../framework/Source/FlutterViewController.mm | 2 + 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 0c89e580311..d912e0d136f 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -22,6 +22,11 @@ void FlutterPlatformViewsController::SetFlutterView(UIView* flutter_view) { flutter_view_.reset([flutter_view retain]); } +void FlutterPlatformViewsController::SetFlutterViewController( + UIViewController* flutter_view_controller) { + flutter_view_controller_.reset([flutter_view_controller retain]); +} + void FlutterPlatformViewsController::OnMethodCall(FlutterMethodCall* call, FlutterResult& result) { if ([[call method] isEqualToString:@"create"]) { OnCreate(call, result); @@ -80,9 +85,9 @@ void FlutterPlatformViewsController::OnCreate(FlutterMethodCall* call, FlutterRe arguments:params]; views_[viewId] = fml::scoped_nsobject>([embedded_view retain]); - FlutterTouchInterceptingView* touch_interceptor = - [[[FlutterTouchInterceptingView alloc] initWithEmbeddedView:embedded_view.view - flutterView:flutter_view_] autorelease]; + FlutterTouchInterceptingView* touch_interceptor = [[[FlutterTouchInterceptingView alloc] + initWithEmbeddedView:embedded_view.view + flutterViewController:flutter_view_controller_.get()] autorelease]; touch_interceptors_[viewId] = fml::scoped_nsobject([touch_interceptor retain]); @@ -355,13 +360,15 @@ void FlutterPlatformViewsController::EnsureGLOverlayInitialized( // as well. So during this phase as well the ForwardingGestureRecognizer dispatched the events // directly to the FlutterView. @interface ForwardingGestureRecognizer : UIGestureRecognizer -- (instancetype)initWithTarget:(id)target flutterView:(UIView*)flutterView; +- (instancetype)initWithTarget:(id)target + flutterViewController:(UIViewController*)flutterViewController; @end @implementation FlutterTouchInterceptingView { fml::scoped_nsobject _delayingRecognizer; } -- (instancetype)initWithEmbeddedView:(UIView*)embeddedView flutterView:(UIView*)flutterView { +- (instancetype)initWithEmbeddedView:(UIView*)embeddedView + flutterViewController:(UIViewController*)flutterViewController { self = [super initWithFrame:embeddedView.frame]; if (self) { self.multipleTouchEnabled = YES; @@ -372,7 +379,7 @@ void FlutterPlatformViewsController::EnsureGLOverlayInitialized( ForwardingGestureRecognizer* forwardingRecognizer = [[[ForwardingGestureRecognizer alloc] initWithTarget:self - flutterView:flutterView] autorelease]; + flutterViewController:flutterViewController] autorelease]; _delayingRecognizer.reset([[DelayingGestureRecognizer alloc] initWithTarget:self @@ -446,35 +453,37 @@ void FlutterPlatformViewsController::EnsureGLOverlayInitialized( @implementation ForwardingGestureRecognizer { // We can't dispatch events to the framework without this back pointer. // This is a weak reference, the ForwardingGestureRecognizer is owned by the - // FlutterTouchInterceptingView which is strong referenced only by the FlutterView. + // FlutterTouchInterceptingView which is strong referenced only by the FlutterView, + // which is strongly referenced by the FlutterViewController. // So this is safe as when FlutterView is deallocated the reference to ForwardingGestureRecognizer // will go away. - UIView* _flutterView; + UIViewController* _flutterViewController; // Counting the pointers that has started in one touch sequence. NSInteger _currentTouchPointersCount; } -- (instancetype)initWithTarget:(id)target flutterView:(UIView*)flutterView { +- (instancetype)initWithTarget:(id)target + flutterViewController:(UIViewController*)flutterViewController { self = [super initWithTarget:target action:nil]; if (self) { self.delegate = self; - _flutterView = flutterView; + _flutterViewController = flutterViewController; _currentTouchPointersCount = 0; } return self; } - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { - [_flutterView touchesBegan:touches withEvent:event]; + [_flutterViewController touchesBegan:touches withEvent:event]; _currentTouchPointersCount += touches.count; } - (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { - [_flutterView touchesMoved:touches withEvent:event]; + [_flutterViewController touchesMoved:touches withEvent:event]; } - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { - [_flutterView touchesEnded:touches withEvent:event]; + [_flutterViewController touchesEnded:touches withEvent:event]; _currentTouchPointersCount -= touches.count; // Touches in one touch sequence are sent to the touchesEnded method separately if different // fingers stop touching the screen at different time. So one touchesEnded method triggering does @@ -486,7 +495,7 @@ void FlutterPlatformViewsController::EnsureGLOverlayInitialized( } - (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event { - [_flutterView touchesCancelled:touches withEvent:event]; + [_flutterViewController touchesCancelled:touches withEvent:event]; _currentTouchPointersCount = 0; self.state = UIGestureRecognizerStateFailed; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index aaab1720b76..5361fced0cc 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -18,7 +18,8 @@ // 1. Delay or prevent touch events from arriving the embedded view. // 2. Dispatching all events that are hittested to the embedded view to the FlutterView. @interface FlutterTouchInterceptingView : UIView -- (instancetype)initWithEmbeddedView:(UIView*)embeddedView flutterView:(UIView*)flutterView; +- (instancetype)initWithEmbeddedView:(UIView*)embeddedView + flutterViewController:(UIViewController*)flutterViewController; // Stop delaying any active touch sequence (and let it arrive the embedded view). - (void)releaseGesture; @@ -52,6 +53,8 @@ class FlutterPlatformViewsController { void SetFlutterView(UIView* flutter_view); + void SetFlutterViewController(UIViewController* flutter_view_controller); + void RegisterViewFactory(NSObject* factory, NSString* factoryId); void SetFrameSize(SkISize frame_size); @@ -81,6 +84,7 @@ class FlutterPlatformViewsController { private: fml::scoped_nsobject channel_; fml::scoped_nsobject flutter_view_; + fml::scoped_nsobject flutter_view_controller_; std::map>> factories_; std::map>> views_; std::map> touch_interceptors_; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 0f987d42e40..0230321fc6e 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -382,10 +382,12 @@ NSNotificationName const FlutterSemanticsUpdateNotification = @"FlutterSemantics if (appeared) { [self installSplashScreenViewCallback]; [_engine.get() platformViewsController] -> SetFlutterView(_flutterView.get()); + [_engine.get() platformViewsController] -> SetFlutterViewController(self); [_engine.get() platformView] -> NotifyCreated(); } else { [_engine.get() platformView] -> NotifyDestroyed(); [_engine.get() platformViewsController] -> SetFlutterView(nullptr); + [_engine.get() platformViewsController] -> SetFlutterViewController(nullptr); } }