Unverified Commit b2d53f60 authored by Tong Mu's avatar Tong Mu Committed by GitHub

Tap gesture no longer add pointer after resetting (#52450)

* TapGestureRecognizer no longer adds the pointer after it resets.

* Adds an assertion to make sure TapGestureRecognizer.startTrackingPointer is never called when _down is null
parent 1e8c4572
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:vector_math/vector_math_64.dart' show Matrix4;
import 'package:flutter/foundation.dart';
import 'arena.dart';
......@@ -183,13 +184,30 @@ abstract class BaseTapGestureRecognizer extends PrimaryPointerGestureRecognizer
@override
void addAllowedPointer(PointerDownEvent event) {
assert(event != null);
if (state == GestureRecognizerState.ready) {
// `_down` must be assigned in this method instead of `handlePrimaryPointer`,
// because `acceptGesture` might be called before `handlePrimaryPointer`,
// which relies on `_down` to call `handleTapDown`.
_down = event;
}
super.addAllowedPointer(event);
if (_down != null) {
// This happens when this tap gesture has been rejected while the pointer
// is down (i.e. due to movement), when another allowed pointer is added,
// in which case all pointers are simply ignored. The `_down` being null
// means that _reset() has been called, since it is always set at the
// first allowed down event and will not be cleared except for reset(),
super.addAllowedPointer(event);
}
}
@override
@protected
void startTrackingPointer(int pointer, [Matrix4 transform]) {
// The recognizer should never track any pointers when `_down` is null,
// because calling `_checkDown` in this state will throw exception.
assert(_down != null);
super.startTrackingPointer(pointer, transform);
}
@override
......
......@@ -4,8 +4,8 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter_test/flutter_test.dart';
import '../flutter_test_alternative.dart';
import 'gesture_tester.dart';
class TestGestureArenaMember extends GestureArenaMember {
......@@ -904,4 +904,38 @@ void main() {
expect(recognized, <String>['secondaryCancel']);
});
});
testGesture('A second tap after rejection is ignored', (GestureTester tester) {
bool didTap = false;
final TapGestureRecognizer tap = TapGestureRecognizer()
..onTap = () {
didTap = true;
};
// Add drag recognizer for competition
final HorizontalDragGestureRecognizer drag = HorizontalDragGestureRecognizer()
..onStart = (_) {};
final TestPointer pointer1 = TestPointer(1);
final PointerDownEvent down = pointer1.down(const Offset(0.0, 0.0));
drag.addPointer(down);
tap.addPointer(down);
tester.closeArena(1);
// One-finger moves, canceling the tap
tester.route(down);
tester.route(pointer1.move(const Offset(50.0, 0)));
// Add another finger
final TestPointer pointer2 = TestPointer(2);
final PointerDownEvent down2 = pointer2.down(const Offset(10.0, 20.0));
drag.addPointer(down2);
tap.addPointer(down2);
tester.closeArena(2);
tester.route(down2);
expect(didTap, isFalse);
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment