From 4641fc252556709d2f18af43e8605763d4a8c43b Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Wed, 29 Mar 2023 17:00:00 -0700 Subject: [PATCH] WIP struggling to test --- .../src/widgets/tap_and_drag_gestures.dart | 11 +++ .../widgets/tap_and_drag_gestures_test.dart | 90 +++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/packages/flutter/lib/src/widgets/tap_and_drag_gestures.dart b/packages/flutter/lib/src/widgets/tap_and_drag_gestures.dart index 5d8c337fa11f..249f2bf6b5e6 100644 --- a/packages/flutter/lib/src/widgets/tap_and_drag_gestures.dart +++ b/packages/flutter/lib/src/widgets/tap_and_drag_gestures.dart @@ -955,6 +955,7 @@ class TapAndDragGestureRecognizer extends OneSequenceGestureRecognizer with _Tap _wonArenaForPrimaryPointer = true; + print('justin acceptGesture $_start, just set _wonArenaForPrimaryPointer to true'); if (_start != null) { _acceptDrag(_start!); } @@ -999,9 +1000,12 @@ class TapAndDragGestureRecognizer extends OneSequenceGestureRecognizer with _Tap _checkDragEnd(); } + print('justin didStopTrackingLastPointer would usually clear start here'); _stopDeadlineTimer(); _dragState = _DragState.ready; _pastSlopTolerance = false; + // TODO(justinmc): Undo this when test is working. + //_start = null; } @override @@ -1032,6 +1036,7 @@ class TapAndDragGestureRecognizer extends OneSequenceGestureRecognizer with _Tap if (_dragState == _DragState.accepted) { _checkDragUpdate(event); } else if (_dragState == _DragState.possible) { + print('justin possible $_start'); if (_start == null) { // Only check for a drag if the start of a drag was not already identified. _checkDrag(event); @@ -1081,9 +1086,11 @@ class TapAndDragGestureRecognizer extends OneSequenceGestureRecognizer with _Tap String get debugDescription => 'tap_and_drag'; void _acceptDrag(PointerEvent event) { + print('justin _acceptDrag $_wonArenaForPrimaryPointer'); if (!_wonArenaForPrimaryPointer) { return; } + print('justin drag accepted');// \n${StackTrace.current}'); _dragState = _DragState.accepted; if (dragStartBehavior == DragStartBehavior.start) { _initialPosition = _initialPosition + OffsetPair(global: event.delta, local: event.localDelta); @@ -1111,7 +1118,9 @@ class TapAndDragGestureRecognizer extends OneSequenceGestureRecognizer with _Tap untransformedDelta: event.localDelta, untransformedEndPosition: event.localPosition ).distance * 1.sign; + print('justin _checkDrag has enough? ${event.localDelta}'); if (_hasSufficientGlobalDistanceToAccept(event.kind, gestureSettings?.touchSlop)) { + print('justin _checkDrag setting _start'); _start = event; } } @@ -1173,6 +1182,7 @@ class TapAndDragGestureRecognizer extends OneSequenceGestureRecognizer with _Tap invokeCallback('onDragStart', () => onDragStart!(details)); } + print('justin _checkDragStart clearing _start'); _start = null; } @@ -1265,6 +1275,7 @@ class TapAndDragGestureRecognizer extends OneSequenceGestureRecognizer with _Tap } void _resetTaps() { + print('justin reset taps'); _sentTapDown = false; _wonArenaForPrimaryPointer = false; _primaryPointer = null; diff --git a/packages/flutter/test/widgets/tap_and_drag_gestures_test.dart b/packages/flutter/test/widgets/tap_and_drag_gestures_test.dart index b52930c62191..c6c617c16884 100644 --- a/packages/flutter/test/widgets/tap_and_drag_gestures_test.dart +++ b/packages/flutter/test/widgets/tap_and_drag_gestures_test.dart @@ -588,4 +588,94 @@ void main() { GestureBinding.instance.gestureArena.sweep(1); expect(events, ['down#1']); }); + + // This is a regression test for https://github.com/flutter/flutter/issues/102084. + testGesture('Does not get stuck waiting for a drag when losing the arena', (GestureTester tester) { + final TapAndDragGestureRecognizer tapAndDrag1 = _RejectingTapAndDragGestureRecognizer() + ..dragStartBehavior = DragStartBehavior.down + ..maxConsecutiveTap = 3 + ..onTapDown = (TapDragDownDetails details) { + events.add('down#${details.consecutiveTapCount}'); + } + ..onTapUp = (TapDragUpDetails details) { + events.add('up#${details.consecutiveTapCount}'); + } + ..onDragStart = (TapDragStartDetails details) { + events.add('dragstart#${details.consecutiveTapCount}'); + } + ..onDragUpdate = (TapDragUpdateDetails details) { + events.add('dragupdate#${details.consecutiveTapCount}'); + } + ..onDragEnd = (TapDragEndDetails details) { + events.add('dragend#${details.consecutiveTapCount}'); + } + ..onCancel = () { + events.add('cancel'); + }; + + const PointerDownEvent horizontalDragDown = PointerDownEvent( + pointer: 6, + position: Offset(10.0, 10.0), + ); + const PointerMoveEvent horizontalDragMove = PointerMoveEvent( + pointer: 6, + position: Offset(55.0, 10.0), + ); + const PointerUpEvent horizontalDragUp = PointerUpEvent( + pointer: 6, + position: Offset(55.0, 10.0), + ); + + // TODO(justinmc): Either do this 2 detector approach, or extend it and dont accept? + + print('justin start drag'); + /* + tapAndDrag.addPointer(horizontalDragDown); + tester.closeArena(horizontalDragDown.pointer); + tester.route(horizontalDragDown); + tester.route(horizontalDragMove); + tester.route(horizontalDragUp); + GestureBinding.instance.gestureArena.sweep(horizontalDragDown.pointer); + expect(events, ['down#1', 'dragstart#1', 'dragend#1']); + */ + final TestPointer pointer = TestPointer(5); + final PointerDownEvent down = pointer.down(const Offset(10.0, 10.0)); + tapAndDrag1.addPointer(down); + tester.closeArena(5); + tester.route(down); + tester.route(pointer.move(const Offset(50.0, 10.0))); + tester.route(pointer.up()); + GestureBinding.instance.gestureArena.sweep(5); + expect(events, ['down#1', 'dragstart#1', 'dragupdate#1', 'dragend#1']); + print('justin done drag\n'); + + print('justin start tap'); + events.clear(); + tester.async.elapse(const Duration(milliseconds: 1000)); + tapAndDrag1.addPointer(down1); + tester.closeArena(1); + tester.route(down1); + tester.route(up1); + GestureBinding.instance.gestureArena.sweep(1); + expect(events, ['down#1', 'up#1']); + print('justin done tap\n'); + + print('justin start second tap'); + events.clear(); + tester.async.elapse(const Duration(milliseconds: 1000)); + tapAndDrag1.addPointer(down2); + tester.closeArena(2); + tester.route(down2); + tester.route(up2); + GestureBinding.instance.gestureArena.sweep(2); + expect(events, ['down#1', 'up#1']); + }); +} + +class _RejectingTapAndDragGestureRecognizer extends TapAndDragGestureRecognizer { + @override + void acceptGesture(int pointer) { + print('justin should I accept this? $pointer'); + return; + } }