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 _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 {
|
|||||||
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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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';
|
|||||||
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.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user