Unverified Commit 137ec45d authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

Call onTapCancel when down pointer gets cancelled (#28546)

parent 3054a935
......@@ -174,6 +174,9 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
_finalPosition = event.position;
_checkUp();
} else if (event is PointerCancelEvent) {
if (_sentTapDown && onTapCancel != null) {
invokeCallback<void>('onTapCancel', onTapCancel);
}
_reset();
}
}
......@@ -183,6 +186,7 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
if (_wonArenaForPrimaryPointer && disposition == GestureDisposition.rejected) {
// This can happen if the superclass decides the primary pointer
// exceeded the touch slop, or if the recognizer is disposed.
assert(_sentTapDown);
if (onTapCancel != null)
invokeCallback<void>('spontaneous onTapCancel', onTapCancel);
_reset();
......@@ -211,7 +215,7 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
if (pointer == primaryPointer) {
// Another gesture won the arena.
assert(state != GestureRecognizerState.possible);
if (onTapCancel != null)
if (_sentTapDown && onTapCancel != null)
invokeCallback<void>('forced onTapCancel', onTapCancel);
_reset();
}
......
......@@ -388,7 +388,6 @@ void main() {
'tapA onTapDown',
'tapA onTapUp',
'tapA onTap',
'tapB onTapCancel',
'swept 1',
'down 2 to A',
'down 2 to B',
......@@ -398,10 +397,74 @@ void main() {
'tapA onTapDown',
'tapA onTapUp',
'tapA onTap',
'tapB onTapCancel',
'swept 2',
'disposed A',
'disposed B',
]);
});
testGesture('PointerCancelEvent cancels tap', (GestureTester tester) {
const PointerDownEvent down = PointerDownEvent(
pointer: 5,
position: Offset(10.0, 10.0)
);
const PointerCancelEvent cancel = PointerCancelEvent(
pointer: 5,
position: Offset(10.0, 10.0)
);
final TapGestureRecognizer tap = TapGestureRecognizer();
final List<String> recognized = <String>[];
tap.onTapDown = (_) {
recognized.add('down');
};
tap.onTapUp = (_) {
recognized.add('up');
};
tap.onTap = () {
recognized.add('tap');
};
tap.onTapCancel = () {
recognized.add('cancel');
};
tap.addPointer(down);
tester.closeArena(5);
tester.async.elapse(const Duration(milliseconds: 5000));
expect(recognized, <String>['down']);
tester.route(cancel);
expect(recognized, <String>['down', 'cancel']);
tap.dispose();
});
testGesture('losing tap gesture recognizer does not send onTapCancel', (GestureTester tester) {
final TapGestureRecognizer tap = TapGestureRecognizer();
final HorizontalDragGestureRecognizer drag = HorizontalDragGestureRecognizer();
final List<String> recognized = <String>[];
tap.onTapDown = (_) {
recognized.add('down');
};
tap.onTapUp = (_) {
recognized.add('up');
};
tap.onTap = () {
recognized.add('tap');
};
tap.onTapCancel = () {
recognized.add('cancel');
};
tap.addPointer(down3);
drag.addPointer(down3);
tester.closeArena(3);
tester.route(move3);
GestureBinding.instance.gestureArena.sweep(3);
expect(recognized, isEmpty);
tap.dispose();
drag.dispose();
});
}
......@@ -54,7 +54,7 @@ void main() {
await tester.tap(find.byType(InkWell), pointer: 2);
await tester.tap(find.byType(InkWell), pointer: 3);
expect(log, equals(<String>['tap-cancel', 'double-tap']));
expect(log, equals(<String>['double-tap']));
log.clear();
await tester.longPress(find.byType(InkWell), pointer: 4);
......
......@@ -287,33 +287,32 @@ void main() {
);
// Pointer is dragged from the center of the 800x100 gesture detector
// to a point (400,300) below it. This always causes onTapCancel to be
// called; onTap should never be called.
// to a point (400,300) below it. This should never call onTap.
Future<void> dragOut(Duration timeout) async {
final TestGesture gesture = await tester.startGesture(const Offset(400.0, 50.0));
// If the timeout is less than kPressTimeout the recognizer will just trigger
// the onTapCancel callback. If the timeout is greater than kLongPressTimeout
// If the timeout is less than kPressTimeout the recognizer will not
// trigger any callbacks. If the timeout is greater than kLongPressTimeout
// then onTapDown, onLongPress, and onCancel will be called.
await tester.pump(timeout);
await gesture.moveTo(const Offset(400.0, 300.0));
await gesture.up();
}
await dragOut(kPressTimeout * 0.5); // generates tapCancel
await dragOut(kPressTimeout * 0.5); // generates nothing
expect(tapDown, 0);
expect(tapCancel, 1);
expect(tapCancel, 0);
expect(tap, 0);
expect(longPress, 0);
await dragOut(kPressTimeout); // generates tapDown, tapCancel
expect(tapDown, 1);
expect(tapCancel, 2);
expect(tapCancel, 1);
expect(tap, 0);
expect(longPress, 0);
await dragOut(kLongPressTimeout); // generates tapDown, longPress, tapCancel
expect(tapDown, 2);
expect(tapCancel, 3);
expect(tapCancel, 2);
expect(tap, 0);
expect(longPress, 1);
});
......
......@@ -119,7 +119,7 @@ void main() {
expect(singleLongTapStartCount, 0);
});
testWidgets('a very quick swipe is just a canceled tap', (WidgetTester tester) async {
testWidgets('a very quick swipe is ignored', (WidgetTester tester) async {
await pumpGestureDetector(tester);
final TestGesture gesture = await tester.startGesture(const Offset(200, 200));
await tester.pump(const Duration(milliseconds: 20));
......@@ -127,7 +127,7 @@ void main() {
await tester.pump();
expect(singleTapUpCount, 0);
expect(tapCount, 0);
expect(singleTapCancelCount, 1);
expect(singleTapCancelCount, 0);
expect(doubleTapDownCount, 0);
expect(singleLongTapStartCount, 0);
......@@ -135,7 +135,7 @@ void main() {
// Nothing else happens on up.
expect(singleTapUpCount, 0);
expect(tapCount, 0);
expect(singleTapCancelCount, 1);
expect(singleTapCancelCount, 0);
expect(doubleTapDownCount, 0);
expect(singleLongTapStartCount, 0);
});
......
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