Fix monodrag gestures for #112403 and b/249091367
This commit is contained in:
parent
0a1af28a8b
commit
c8aa37d1ea
@ -222,6 +222,24 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
late OffsetPair _initialPosition;
|
||||
late OffsetPair _pendingDragOffset;
|
||||
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
|
||||
// different set of buttons, the gesture is canceled.
|
||||
int? _initialButtons;
|
||||
@ -363,7 +381,7 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
if (_state != _DragState.accepted) {
|
||||
_state = _DragState.accepted;
|
||||
final OffsetPair delta = _pendingDragOffset;
|
||||
final Duration timestamp = _lastPendingEventTimestamp!;
|
||||
final Duration? timestamp = _lastPendingEventTimestamp;
|
||||
final Matrix4? transform = _lastTransform;
|
||||
final Offset localUpdateDelta;
|
||||
switch (dragStartBehavior) {
|
||||
@ -449,7 +467,7 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
}
|
||||
}
|
||||
|
||||
void _checkStart(Duration timestamp, int pointer) {
|
||||
void _checkStart(Duration? timestamp, int pointer) {
|
||||
if (onStart != null) {
|
||||
final DragStartDetails details = DragStartDetails(
|
||||
sourceTimeStamp: timestamp,
|
||||
|
@ -10,6 +10,31 @@ import 'gesture_tester.dart';
|
||||
void main() {
|
||||
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) {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/75061.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user