Unverified Commit c8aa37d1 authored by Dan Field's avatar Dan Field Committed by GitHub

Fix for #112403 and b/249091367 (#121615)

Fix monodrag gestures for #112403 and b/249091367
parent 0a1af28a
...@@ -222,6 +222,24 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -222,6 +222,24 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
late OffsetPair _initialPosition; late OffsetPair _initialPosition;
late OffsetPair _pendingDragOffset; late OffsetPair _pendingDragOffset;
Duration? _lastPendingEventTimestamp; Duration? _lastPendingEventTimestamp;
/// When asserts are enabled, returns the last tracked pending event timestamp
/// for this recognizer.
///
/// Otherwise, returns null.
///
/// This getter is intended for use in framework unit tests. Applications must
/// not depend on its value.
@visibleForTesting
Duration? get debugLastPendingEventTimestamp {
Duration? lastPendingEventTimestamp;
assert(() {
lastPendingEventTimestamp = _lastPendingEventTimestamp;
return true;
}());
return lastPendingEventTimestamp;
}
// The buttons sent by `PointerDownEvent`. If a `PointerMoveEvent` comes with a // The buttons sent by `PointerDownEvent`. If a `PointerMoveEvent` comes with a
// different set of buttons, the gesture is canceled. // different set of buttons, the gesture is canceled.
int? _initialButtons; int? _initialButtons;
...@@ -363,7 +381,7 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -363,7 +381,7 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
if (_state != _DragState.accepted) { if (_state != _DragState.accepted) {
_state = _DragState.accepted; _state = _DragState.accepted;
final OffsetPair delta = _pendingDragOffset; final OffsetPair delta = _pendingDragOffset;
final Duration timestamp = _lastPendingEventTimestamp!; final Duration? timestamp = _lastPendingEventTimestamp;
final Matrix4? transform = _lastTransform; final Matrix4? transform = _lastTransform;
final Offset localUpdateDelta; final Offset localUpdateDelta;
switch (dragStartBehavior) { switch (dragStartBehavior) {
...@@ -449,7 +467,7 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -449,7 +467,7 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
} }
} }
void _checkStart(Duration timestamp, int pointer) { void _checkStart(Duration? timestamp, int pointer) {
if (onStart != null) { if (onStart != null) {
final DragStartDetails details = DragStartDetails( final DragStartDetails details = DragStartDetails(
sourceTimeStamp: timestamp, sourceTimeStamp: timestamp,
......
...@@ -10,6 +10,31 @@ import 'gesture_tester.dart'; ...@@ -10,6 +10,31 @@ import 'gesture_tester.dart';
void main() { void main() {
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
test('acceptGesture tolerates a null lastPendingEventTimestamp', () {
// Regression test for https://github.com/flutter/flutter/issues/112403
// and b/249091367
final DragGestureRecognizer recognizer = VerticalDragGestureRecognizer();
const PointerDownEvent event = PointerDownEvent(timeStamp: Duration(days: 10));
expect(recognizer.debugLastPendingEventTimestamp, null);
recognizer.addAllowedPointer(event);
expect(recognizer.debugLastPendingEventTimestamp, event.timeStamp);
// Normal case: acceptGesture called and we have a last timestamp set.
recognizer.acceptGesture(event.pointer);
expect(recognizer.debugLastPendingEventTimestamp, null);
// Reject the gesture to reset state and allow accepting it again.
recognizer.rejectGesture(event.pointer);
expect(recognizer.debugLastPendingEventTimestamp, null);
// Not entirely clear how this can happen, but the bugs mentioned above show
// we can end up in this state empircally.
recognizer.acceptGesture(event.pointer);
expect(recognizer.debugLastPendingEventTimestamp, null);
});
testGesture('do not crash on up event for a pending pointer after winning arena for another pointer', (GestureTester tester) { testGesture('do not crash on up event for a pending pointer after winning arena for another pointer', (GestureTester tester) {
// Regression test for https://github.com/flutter/flutter/issues/75061. // Regression test for https://github.com/flutter/flutter/issues/75061.
......
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