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

Conversation

@cyanglaz
Copy link
Contributor

@cyanglaz cyanglaz commented Nov 9, 2020

Description

Regression: After #20708, touch events might not able to finish if FlutterViewController is unset in the middle of the touch events. This PR asks the ForwardGestureRecognizer to hold a reference to the FlutterViewController at least until the end of the touch events.

Related Issues

Fixes flutter/flutter#66097

Tests

testSetFlutterViewControllerToNilInTheMiddleOfTouchEventShouldStillAllowGesturesToBeHandled

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the contributor guide and followed the process outlined there for submitting PRs.
  • I signed the CLA.
  • I read and followed the C++, Objective-C, Java style guides for the engine.
  • I read the tree hygiene wiki page, which explains my responsibilities.
  • I updated/added relevant documentation.
  • All existing and new tests are passing.
  • I am willing to follow-up on review comments in a timely manner.

Reviewer Checklist

Breaking Change

Did any tests fail when you ran them? Please read handling breaking changes.

Comment on lines 912 to 914
if (!_flutterViewController) {
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think these aren't necessary, since sending a message to nil is a noop.

}
}
[_flutterViewController touchesBegan:touches withEvent:event];
_currentTouchPointersCount += touches.count;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the implication of not incrementing this counter if we have no VC?

Should we be setting to zero in the early return above?

Copy link
Contributor Author

@cyanglaz cyanglaz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dnfield @gaaclarke Updated per your comments. PTAL


- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
[_platformViewsController->getFlutterViewController() touchesBegan:touches withEvent:event];
_flutterViewController = _platformViewsController->getFlutterViewController();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible that _platformViewsController->getFlutterViewController() could return different values between calls touchesBegan before touchesEnded has happened?

  1. touch-1 began
  2. flutter view controller changed
  3. touch-2 began
  4. touch-1 ended
  5. touch-2 ended

If so you'd have to be super vigilant and track the FlutterViewController at touchesBegan for each event.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has this been addressed in the recent commit(s)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the code to support this scenario. I also added a test for this.

0D6AB6C922BB05E200EEE540 /* IosUnitTestsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IosUnitTestsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
0D6AB6CF22BB05E200EEE540 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0D6AB73E22BD8F0200EEE540 /* FlutterEngineConfig.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = FlutterEngineConfig.xcconfig; sourceTree = "<group>"; };
68FF0A70255A3B4E00165B60 /* FlutterPlatformViewsTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterPlatformViewsTest.mm; sourceTree = "<group>"; };
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found that this test file is not referenced by the project, so while I'm here, I added it to the project so it helps the debugging process easier.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't suppose to be in here. That is linked in as part of ios_test_flutter_mrc

"framework/Source/FlutterPlatformViewsTest.mm",

You'll get duplicate symbols if you do this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You still need to remove this.

Comment on lines 898 to 903
if (_currentTouchPointersCount == 0) {
// At the start of each gesture sequence, we reset the `_flutterViewController`,
// so that all the touch events in the same sequence are forwarded to the same `_flutterViewController`.
_flutterViewController = _platformViewsController->getFlutterViewController();
}
[_flutterViewController touchesBegan:touches withEvent:event];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still makes me a bit nervous. Particularly the fact that _flutterViewController is a weak reference and we are sending messages to it potentially after _platformViewsController has gotten rid of it. My suggestion was to keep a map between events and FlutterViewControllers.

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
  _flutterViewControllers[event] = _platformViewsController->getFlutterViewController();
  [_flutterViewControllers[event] touchesBegan:touches withEvent:event];
}

-(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
  [_flutterViewControllers[event] touchesEnded:touches withEvent:event];
  [_flutterViewControllers removeObject:event];
}

This has the added benefit of having a retain on the flutter view controller while it is being interacted with and everyone gets the correct message. You'll have to verify that the same event is getting passed across all of the calls.

Comment on lines +931 to +936
[_flutterViewController.get() touchesCancelled:touches withEvent:event];
_currentTouchPointersCount -= touches.count;
if (_currentTouchPointersCount == 0) {
self.state = UIGestureRecognizerStateFailed;
_flutterViewController.reset(nil);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case where we get Begin-Begin-Cancel-End the state will no longer be Failed like it was previously, is that expected?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Begin-Begin-Cancel-End makes the count to 0 at the last End, so it state would still be failed.
I don't think Begin-Begin-Cancel-End would be possible anyway, if a Cancel happens during a sequence, it cancels all the touches had begun.

Comment on lines 897 to 902
if (_currentTouchPointersCount < 0) {
// _currentTouchPointersCount should never be less than 0.
// To not breaking production code, we reset the count to 0 if a negative value
// is reached.
_currentTouchPointersCount = 0;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be possible now that you've changed the cancel logic, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, removed

Copy link
Member

@gaaclarke gaaclarke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once the PlatformViewsTest is removed from the project. There are still some things I'm not clear about but comparing this code to what was before it, this is an improvement and a fix. Thanks chris.

0D6AB6C922BB05E200EEE540 /* IosUnitTestsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IosUnitTestsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
0D6AB6CF22BB05E200EEE540 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0D6AB73E22BD8F0200EEE540 /* FlutterEngineConfig.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = FlutterEngineConfig.xcconfig; sourceTree = "<group>"; };
68FF0A70255A3B4E00165B60 /* FlutterPlatformViewsTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterPlatformViewsTest.mm; sourceTree = "<group>"; };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You still need to remove this.

@cyanglaz
Copy link
Contributor Author

@gaaclarke Removed the reference.

@dnfield PTAL

@cyanglaz cyanglaz added the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Nov 13, 2020
@fluttergithubbot fluttergithubbot merged commit 92e5a95 into flutter:master Nov 13, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 14, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 15, 2020
@cyanglaz cyanglaz deleted the gesture branch November 16, 2020 17:25
chaselatta pushed a commit to chaselatta/engine that referenced this pull request Nov 30, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

cla: yes platform-ios waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GestureDetector producing incorrect results when used with UiKitView on iOS 12 and 14

5 participants