Reject unaccepted pointers in Drag recognizer (#75943)
This commit is contained in:
parent
46b8ea8fe6
commit
6afbb25a48
@ -309,15 +309,16 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
}
|
||||
}
|
||||
if (event is PointerUpEvent || event is PointerCancelEvent) {
|
||||
_giveUpPointer(
|
||||
event.pointer,
|
||||
reject: event is PointerCancelEvent || _state ==_DragState.possible,
|
||||
);
|
||||
_giveUpPointer(event.pointer);
|
||||
}
|
||||
}
|
||||
|
||||
final Set<int> _acceptedActivePointers = <int>{};
|
||||
|
||||
@override
|
||||
void acceptGesture(int pointer) {
|
||||
assert(!_acceptedActivePointers.contains(pointer));
|
||||
_acceptedActivePointers.add(pointer);
|
||||
if (_state != _DragState.accepted) {
|
||||
_state = _DragState.accepted;
|
||||
final OffsetPair delta = _pendingDragOffset;
|
||||
@ -384,32 +385,36 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
_state = _DragState.ready;
|
||||
}
|
||||
|
||||
void _giveUpPointer(int pointer, {bool reject = true}) {
|
||||
void _giveUpPointer(int pointer) {
|
||||
stopTrackingPointer(pointer);
|
||||
if (reject)
|
||||
// If we never accepted the pointer, we reject it since we are no longer
|
||||
// interested in winning the gesture arena for it.
|
||||
if (!_acceptedActivePointers.remove(pointer))
|
||||
resolvePointer(pointer, GestureDisposition.rejected);
|
||||
}
|
||||
|
||||
void _checkDown() {
|
||||
assert(_initialButtons == kPrimaryButton);
|
||||
final DragDownDetails details = DragDownDetails(
|
||||
globalPosition: _initialPosition.global,
|
||||
localPosition: _initialPosition.local,
|
||||
);
|
||||
if (onDown != null)
|
||||
if (onDown != null) {
|
||||
final DragDownDetails details = DragDownDetails(
|
||||
globalPosition: _initialPosition.global,
|
||||
localPosition: _initialPosition.local,
|
||||
);
|
||||
invokeCallback<void>('onDown', () => onDown!(details));
|
||||
}
|
||||
}
|
||||
|
||||
void _checkStart(Duration timestamp, int pointer) {
|
||||
assert(_initialButtons == kPrimaryButton);
|
||||
final DragStartDetails details = DragStartDetails(
|
||||
sourceTimeStamp: timestamp,
|
||||
globalPosition: _initialPosition.global,
|
||||
localPosition: _initialPosition.local,
|
||||
kind: getKindForPointer(pointer),
|
||||
);
|
||||
if (onStart != null)
|
||||
if (onStart != null) {
|
||||
final DragStartDetails details = DragStartDetails(
|
||||
sourceTimeStamp: timestamp,
|
||||
globalPosition: _initialPosition.global,
|
||||
localPosition: _initialPosition.local,
|
||||
kind: getKindForPointer(pointer),
|
||||
);
|
||||
invokeCallback<void>('onStart', () => onStart!(details));
|
||||
}
|
||||
}
|
||||
|
||||
void _checkUpdate({
|
||||
@ -420,15 +425,16 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
Offset? localPosition,
|
||||
}) {
|
||||
assert(_initialButtons == kPrimaryButton);
|
||||
final DragUpdateDetails details = DragUpdateDetails(
|
||||
sourceTimeStamp: sourceTimeStamp,
|
||||
delta: delta,
|
||||
primaryDelta: primaryDelta,
|
||||
globalPosition: globalPosition,
|
||||
localPosition: localPosition,
|
||||
);
|
||||
if (onUpdate != null)
|
||||
if (onUpdate != null) {
|
||||
final DragUpdateDetails details = DragUpdateDetails(
|
||||
sourceTimeStamp: sourceTimeStamp,
|
||||
delta: delta,
|
||||
primaryDelta: primaryDelta,
|
||||
globalPosition: globalPosition,
|
||||
localPosition: localPosition,
|
||||
);
|
||||
invokeCallback<void>('onUpdate', () => onUpdate!(details));
|
||||
}
|
||||
}
|
||||
|
||||
void _checkEnd(int pointer) {
|
||||
|
56
packages/flutter/test/gestures/monodrag_test.dart
Normal file
56
packages/flutter/test/gestures/monodrag_test.dart
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'gesture_tester.dart';
|
||||
|
||||
void main() {
|
||||
setUp(ensureGestureBinding);
|
||||
|
||||
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.
|
||||
|
||||
final VerticalDragGestureRecognizer v = VerticalDragGestureRecognizer()
|
||||
..onStart = (_) { };
|
||||
final HorizontalDragGestureRecognizer h = HorizontalDragGestureRecognizer()
|
||||
..onStart = (_) { };
|
||||
|
||||
const PointerDownEvent down90 = PointerDownEvent(
|
||||
pointer: 90,
|
||||
position: Offset(10.0, 10.0),
|
||||
);
|
||||
|
||||
const PointerUpEvent up90 = PointerUpEvent(
|
||||
pointer: 90,
|
||||
position: Offset(10.0, 10.0),
|
||||
);
|
||||
|
||||
const PointerDownEvent down91 = PointerDownEvent(
|
||||
pointer: 91,
|
||||
position: Offset(20.0, 20.0),
|
||||
);
|
||||
|
||||
const PointerUpEvent up91 = PointerUpEvent(
|
||||
pointer: 91,
|
||||
position: Offset(20.0, 20.0),
|
||||
);
|
||||
|
||||
v.addPointer(down90);
|
||||
GestureBinding.instance!.gestureArena.close(90);
|
||||
h.addPointer(down91);
|
||||
v.addPointer(down91);
|
||||
GestureBinding.instance!.gestureArena.close(91);
|
||||
tester.async.flushMicrotasks();
|
||||
|
||||
GestureBinding.instance!.handleEvent(up90, HitTestEntry(MockHitTestTarget()));
|
||||
GestureBinding.instance!.handleEvent(up91, HitTestEntry(MockHitTestTarget()));
|
||||
});
|
||||
}
|
||||
|
||||
class MockHitTestTarget implements HitTestTarget {
|
||||
@override
|
||||
void handleEvent(PointerEvent event, HitTestEntry entry) { }
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user