Skip to content

Add "OneSequenceRecognizer.resolvePointer". Fix DragGestureRecognizer crash on multiple pointers#39017

Merged
dkwingsmt merged 18 commits intoflutter:masterfrom
dkwingsmt:fix-multi-press-crash
Aug 27, 2019
Merged

Add "OneSequenceRecognizer.resolvePointer". Fix DragGestureRecognizer crash on multiple pointers#39017
dkwingsmt merged 18 commits intoflutter:masterfrom
dkwingsmt:fix-multi-press-crash

Conversation

@dkwingsmt
Copy link
Contributor

@dkwingsmt dkwingsmt commented Aug 22, 2019

Description

This PR fixes some edge cases when DragGestureRecognizer interacts with multiple pointers.

It also changes drag_test.dart so that all GestureRecognizer.dispose calls are guarded by addTearDown.

New method resolvePointer

To fix this, a new API OneSequenceRecognizer.resolvePointer is introduced. Here is why this new API is necessary:

Currently OneSequenceRecognizer provides the following ways to control arena entries:

  1. startTrackingPointer(pointer) adds one pointer to the arena.
  2. resolve(GestureDisposition.rejected) removes all pointers from the arena.

In other words, there is no way to remove one pointer from the arena.

But it is needed for DragGestureRecognizer. Consider the following scenario:

  1. Pointer 1 down
  2. Pointer 2 down
  3. Pointer 1 up
  4. Pointer 2 might go up, or might move away.

Expect: If pointer 2 goes up, the drag is canceled. If pointer 2 moves away, the drag is accepted.

This can not be done with the current tools:

  • If we don't remove pointer 1 from the arena, then arena 1 will sweep, and this drag gesture might be incorrectly considered as a viable candidate in the sweep and get accepted, violating the expectation when pointer 2 goes up.
  • If we do remove pointer 1 from the arena, since we currently have to remove all pointers at once, then pointer 2 will be removed as well, violating the expectation when pointer 2 moves away.

I've also considered embedding this functionality into other methods, mostly stopTrackingPoitner. The problem is gestures that stop tracking pointer do not always want to give up the arena. For example, TapGestureRecognizer stops tracking when the pointer is no longer down, but it does not declare either victory or defeat of the arena, instead waits until itself to be the last member and wins via sweeping.

As a conclusion, we need a new API that can resolve a single pointer. Theoretically we only need to resolve to rejection in this case, but there is no reason not to provide both rejection and acceptance.

Related Issues

Tests

I added the following tests:

On multiple pointers:

  • DragGestureRecognizer is canceled when all pointers are canceled (FIFO)
  • DragGestureRecognizer is canceled when all pointers are canceled (FILO)
  • DragGestureRecognizer is accepted when the first pointer is accepted
  • canceled pointers (due to up) do not prevent later pointers getting accepted
  • canceled pointers (due to buttons) do not prevent later pointers getting accepted

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 Flutter Style Guide, including Features we expect every widget to implement.
  • I updated/added relevant documentation (doc comments with ///).
  • All existing and new tests are passing.
  • The analyzer (flutter analyze --flutter-repo) does not report any problems on my PR.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require Flutter developers to manually update their apps to accommodate your change?

  • Yes, this is a breaking change (Please read Handling breaking changes). Replace this with a link to the e-mail where you asked for input on this proposed change.
  • No, this is not a breaking change.

@dkwingsmt dkwingsmt changed the title Add "OneSequenceRecognizer.giveUpArena". Fix DragGestureRecognizer crash on multiple pointers Add "OneSequenceRecognizer.resolvePointer". Fix DragGestureRecognizer crash on multiple pointers Aug 22, 2019
@dnfield dnfield added a: desktop Running on desktop f: gestures flutter/packages/flutter/gestures repository. framework flutter/packages/flutter repository. See also f: labels. labels Aug 22, 2019
@dkwingsmt dkwingsmt requested a review from gspencergoog August 23, 2019 21:55
Copy link
Contributor

@gspencergoog gspencergoog left a comment

Choose a reason for hiding this comment

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

32384589-a60f0e74-c078-11e7-9bc1-e5b5287aea9d

@dkwingsmt dkwingsmt merged commit 7f02566 into flutter:master Aug 27, 2019
@dkwingsmt dkwingsmt deleted the fix-multi-press-crash branch August 27, 2019 00:44
@dkwingsmt
Copy link
Contributor Author

This should also have fixed #36350

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 4, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

a: desktop Running on desktop f: gestures flutter/packages/flutter/gestures repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

4 participants