forked from firka/flutter
Fix iOS last up event velocity calculation - version 3 (#11571)
* Add synthesized property to pointer events * test
This commit is contained in:
@@ -170,7 +170,8 @@ class PointerEventConverter {
|
||||
radiusMin: datum.radiusMin,
|
||||
radiusMax: datum.radiusMax,
|
||||
orientation: datum.orientation,
|
||||
tilt: datum.tilt
|
||||
tilt: datum.tilt,
|
||||
synthesized: true,
|
||||
);
|
||||
state.lastPosition = position;
|
||||
}
|
||||
@@ -257,7 +258,8 @@ class PointerEventConverter {
|
||||
radiusMin: datum.radiusMin,
|
||||
radiusMax: datum.radiusMax,
|
||||
orientation: datum.orientation,
|
||||
tilt: datum.tilt
|
||||
tilt: datum.tilt,
|
||||
synthesized: true,
|
||||
);
|
||||
state.lastPosition = position;
|
||||
}
|
||||
|
||||
@@ -113,7 +113,8 @@ abstract class PointerEvent {
|
||||
this.radiusMin: 0.0,
|
||||
this.radiusMax: 0.0,
|
||||
this.orientation: 0.0,
|
||||
this.tilt: 0.0
|
||||
this.tilt: 0.0,
|
||||
this.synthesized: false,
|
||||
});
|
||||
|
||||
/// Time of event dispatch, relative to an arbitrary timeline.
|
||||
@@ -235,6 +236,18 @@ abstract class PointerEvent {
|
||||
/// the stylus is flat on that surface).
|
||||
final double tilt;
|
||||
|
||||
/// We occasionally synthesize PointerEvents that aren't exact translations
|
||||
/// of [ui.PointerData] from the engine to cover small cross-OS discrepancies
|
||||
/// in pointer behaviours.
|
||||
///
|
||||
/// For instance, on end events, Android always drops any location changes
|
||||
/// that happened between its reporting intervals when emiting the end events.
|
||||
///
|
||||
/// On iOS, minor incorrect location changes from the previous move events
|
||||
/// can be reported on end events. We synthesize a [PointerEvent] to cover
|
||||
/// the difference between the 2 events in that case.
|
||||
final bool synthesized;
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType($position)';
|
||||
|
||||
@@ -261,7 +274,8 @@ abstract class PointerEvent {
|
||||
'radiusMin: $radiusMin, '
|
||||
'radiusMax: $radiusMax, '
|
||||
'orientation: $orientation, '
|
||||
'tilt: $tilt'
|
||||
'tilt: $tilt, '
|
||||
'synthesized: $synthesized'
|
||||
')';
|
||||
}
|
||||
}
|
||||
@@ -365,7 +379,8 @@ class PointerHoverEvent extends PointerEvent {
|
||||
double radiusMin: 0.0,
|
||||
double radiusMax: 0.0,
|
||||
double orientation: 0.0,
|
||||
double tilt: 0.0
|
||||
double tilt: 0.0,
|
||||
bool synthesized: false,
|
||||
}) : super(
|
||||
timeStamp: timeStamp,
|
||||
kind: kind,
|
||||
@@ -384,7 +399,8 @@ class PointerHoverEvent extends PointerEvent {
|
||||
radiusMin: radiusMin,
|
||||
radiusMax: radiusMax,
|
||||
orientation: orientation,
|
||||
tilt: tilt
|
||||
tilt: tilt,
|
||||
synthesized: synthesized,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -463,7 +479,8 @@ class PointerMoveEvent extends PointerEvent {
|
||||
double radiusMin: 0.0,
|
||||
double radiusMax: 0.0,
|
||||
double orientation: 0.0,
|
||||
double tilt: 0.0
|
||||
double tilt: 0.0,
|
||||
bool synthesized: false,
|
||||
}) : super(
|
||||
timeStamp: timeStamp,
|
||||
pointer: pointer,
|
||||
@@ -484,7 +501,8 @@ class PointerMoveEvent extends PointerEvent {
|
||||
radiusMin: radiusMin,
|
||||
radiusMax: radiusMax,
|
||||
orientation: orientation,
|
||||
tilt: tilt
|
||||
tilt: tilt,
|
||||
synthesized: synthesized,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -130,7 +130,8 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
if (event is PointerMoveEvent) {
|
||||
final VelocityTracker tracker = _velocityTrackers[event.pointer];
|
||||
assert(tracker != null);
|
||||
tracker.addPosition(event.timeStamp, event.position);
|
||||
if (!event.synthesized)
|
||||
tracker.addPosition(event.timeStamp, event.position);
|
||||
final Offset delta = event.delta;
|
||||
if (_state == _DragState.accepted) {
|
||||
if (onUpdate != null) {
|
||||
|
||||
@@ -62,7 +62,8 @@ abstract class MultiDragPointerState {
|
||||
|
||||
void _move(PointerMoveEvent event) {
|
||||
assert(_arenaEntry != null);
|
||||
_velocityTracker.addPosition(event.timeStamp, event.position);
|
||||
if (!event.synthesized)
|
||||
_velocityTracker.addPosition(event.timeStamp, event.position);
|
||||
if (_client != null) {
|
||||
assert(pendingDelta == null);
|
||||
// Call client last to avoid reentrancy.
|
||||
|
||||
@@ -152,7 +152,8 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
if (event is PointerMoveEvent) {
|
||||
final VelocityTracker tracker = _velocityTrackers[event.pointer];
|
||||
assert(tracker != null);
|
||||
tracker.addPosition(event.timeStamp, event.position);
|
||||
if (!event.synthesized)
|
||||
tracker.addPosition(event.timeStamp, event.position);
|
||||
_pointerLocations[event.pointer] = event.position;
|
||||
shouldStartIfAccepted = true;
|
||||
} else if (event is PointerDownEvent) {
|
||||
|
||||
@@ -236,6 +236,38 @@ void main() {
|
||||
drag.dispose();
|
||||
});
|
||||
|
||||
testGesture('Synthesized pointer events are ignored for velocity tracking', (GestureTester tester) {
|
||||
final HorizontalDragGestureRecognizer drag = new HorizontalDragGestureRecognizer();
|
||||
|
||||
Velocity velocity;
|
||||
drag.onEnd = (DragEndDetails details) {
|
||||
velocity = details.velocity;
|
||||
};
|
||||
|
||||
final TestPointer pointer = new TestPointer(1);
|
||||
final PointerDownEvent down = pointer.down(const Offset(10.0, 25.0), timeStamp: const Duration(milliseconds: 10));
|
||||
drag.addPointer(down);
|
||||
tester.closeArena(1);
|
||||
tester.route(down);
|
||||
tester.route(pointer.move(const Offset(20.0, 25.0), timeStamp: const Duration(milliseconds: 20)));
|
||||
tester.route(pointer.move(const Offset(30.0, 25.0), timeStamp: const Duration(milliseconds: 30)));
|
||||
tester.route(pointer.move(const Offset(40.0, 25.0), timeStamp: const Duration(milliseconds: 40)));
|
||||
tester.route(pointer.move(const Offset(50.0, 25.0), timeStamp: const Duration(milliseconds: 50)));
|
||||
tester.route(new PointerMoveEvent(
|
||||
pointer: 1,
|
||||
// Simulate a small synthesized wobble which would have slowed down the
|
||||
// horizontal velocity from 1 px/ms and introduced a slight vertical velocity.
|
||||
position: const Offset(51.0, 26.0),
|
||||
timeStamp: const Duration(milliseconds: 60),
|
||||
synthesized: true,
|
||||
));
|
||||
tester.route(pointer.up(timeStamp: const Duration(milliseconds: 20)));
|
||||
expect(velocity.pixelsPerSecond.dx, moreOrLessEquals(1000.0));
|
||||
expect(velocity.pixelsPerSecond.dy, moreOrLessEquals(0.0));
|
||||
|
||||
drag.dispose();
|
||||
});
|
||||
|
||||
testGesture('Drag details', (GestureTester tester) {
|
||||
expect(new DragDownDetails(), hasOneLineDescription);
|
||||
expect(new DragStartDetails(), hasOneLineDescription);
|
||||
|
||||
Reference in New Issue
Block a user