Commit c9b0b3bb authored by xster's avatar xster Committed by GitHub

Fix iOS last up event velocity calculation - version 3 (#11571)

* Add synthesized property to pointer events

* test
parent 680d581d
...@@ -170,7 +170,8 @@ class PointerEventConverter { ...@@ -170,7 +170,8 @@ class PointerEventConverter {
radiusMin: datum.radiusMin, radiusMin: datum.radiusMin,
radiusMax: datum.radiusMax, radiusMax: datum.radiusMax,
orientation: datum.orientation, orientation: datum.orientation,
tilt: datum.tilt tilt: datum.tilt,
synthesized: true,
); );
state.lastPosition = position; state.lastPosition = position;
} }
...@@ -257,7 +258,8 @@ class PointerEventConverter { ...@@ -257,7 +258,8 @@ class PointerEventConverter {
radiusMin: datum.radiusMin, radiusMin: datum.radiusMin,
radiusMax: datum.radiusMax, radiusMax: datum.radiusMax,
orientation: datum.orientation, orientation: datum.orientation,
tilt: datum.tilt tilt: datum.tilt,
synthesized: true,
); );
state.lastPosition = position; state.lastPosition = position;
} }
......
...@@ -113,7 +113,8 @@ abstract class PointerEvent { ...@@ -113,7 +113,8 @@ abstract class PointerEvent {
this.radiusMin: 0.0, this.radiusMin: 0.0,
this.radiusMax: 0.0, this.radiusMax: 0.0,
this.orientation: 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. /// Time of event dispatch, relative to an arbitrary timeline.
...@@ -235,6 +236,18 @@ abstract class PointerEvent { ...@@ -235,6 +236,18 @@ abstract class PointerEvent {
/// the stylus is flat on that surface). /// the stylus is flat on that surface).
final double tilt; 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 @override
String toString() => '$runtimeType($position)'; String toString() => '$runtimeType($position)';
...@@ -261,7 +274,8 @@ abstract class PointerEvent { ...@@ -261,7 +274,8 @@ abstract class PointerEvent {
'radiusMin: $radiusMin, ' 'radiusMin: $radiusMin, '
'radiusMax: $radiusMax, ' 'radiusMax: $radiusMax, '
'orientation: $orientation, ' 'orientation: $orientation, '
'tilt: $tilt' 'tilt: $tilt, '
'synthesized: $synthesized'
')'; ')';
} }
} }
...@@ -365,7 +379,8 @@ class PointerHoverEvent extends PointerEvent { ...@@ -365,7 +379,8 @@ class PointerHoverEvent extends PointerEvent {
double radiusMin: 0.0, double radiusMin: 0.0,
double radiusMax: 0.0, double radiusMax: 0.0,
double orientation: 0.0, double orientation: 0.0,
double tilt: 0.0 double tilt: 0.0,
bool synthesized: false,
}) : super( }) : super(
timeStamp: timeStamp, timeStamp: timeStamp,
kind: kind, kind: kind,
...@@ -384,7 +399,8 @@ class PointerHoverEvent extends PointerEvent { ...@@ -384,7 +399,8 @@ class PointerHoverEvent extends PointerEvent {
radiusMin: radiusMin, radiusMin: radiusMin,
radiusMax: radiusMax, radiusMax: radiusMax,
orientation: orientation, orientation: orientation,
tilt: tilt tilt: tilt,
synthesized: synthesized,
); );
} }
...@@ -463,7 +479,8 @@ class PointerMoveEvent extends PointerEvent { ...@@ -463,7 +479,8 @@ class PointerMoveEvent extends PointerEvent {
double radiusMin: 0.0, double radiusMin: 0.0,
double radiusMax: 0.0, double radiusMax: 0.0,
double orientation: 0.0, double orientation: 0.0,
double tilt: 0.0 double tilt: 0.0,
bool synthesized: false,
}) : super( }) : super(
timeStamp: timeStamp, timeStamp: timeStamp,
pointer: pointer, pointer: pointer,
...@@ -484,7 +501,8 @@ class PointerMoveEvent extends PointerEvent { ...@@ -484,7 +501,8 @@ class PointerMoveEvent extends PointerEvent {
radiusMin: radiusMin, radiusMin: radiusMin,
radiusMax: radiusMax, radiusMax: radiusMax,
orientation: orientation, orientation: orientation,
tilt: tilt tilt: tilt,
synthesized: synthesized,
); );
} }
......
...@@ -130,7 +130,8 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -130,7 +130,8 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
if (event is PointerMoveEvent) { if (event is PointerMoveEvent) {
final VelocityTracker tracker = _velocityTrackers[event.pointer]; final VelocityTracker tracker = _velocityTrackers[event.pointer];
assert(tracker != null); assert(tracker != null);
tracker.addPosition(event.timeStamp, event.position); if (!event.synthesized)
tracker.addPosition(event.timeStamp, event.position);
final Offset delta = event.delta; final Offset delta = event.delta;
if (_state == _DragState.accepted) { if (_state == _DragState.accepted) {
if (onUpdate != null) { if (onUpdate != null) {
......
...@@ -62,7 +62,8 @@ abstract class MultiDragPointerState { ...@@ -62,7 +62,8 @@ abstract class MultiDragPointerState {
void _move(PointerMoveEvent event) { void _move(PointerMoveEvent event) {
assert(_arenaEntry != null); assert(_arenaEntry != null);
_velocityTracker.addPosition(event.timeStamp, event.position); if (!event.synthesized)
_velocityTracker.addPosition(event.timeStamp, event.position);
if (_client != null) { if (_client != null) {
assert(pendingDelta == null); assert(pendingDelta == null);
// Call client last to avoid reentrancy. // Call client last to avoid reentrancy.
......
...@@ -152,7 +152,8 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -152,7 +152,8 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
if (event is PointerMoveEvent) { if (event is PointerMoveEvent) {
final VelocityTracker tracker = _velocityTrackers[event.pointer]; final VelocityTracker tracker = _velocityTrackers[event.pointer];
assert(tracker != null); assert(tracker != null);
tracker.addPosition(event.timeStamp, event.position); if (!event.synthesized)
tracker.addPosition(event.timeStamp, event.position);
_pointerLocations[event.pointer] = event.position; _pointerLocations[event.pointer] = event.position;
shouldStartIfAccepted = true; shouldStartIfAccepted = true;
} else if (event is PointerDownEvent) { } else if (event is PointerDownEvent) {
......
...@@ -236,6 +236,38 @@ void main() { ...@@ -236,6 +236,38 @@ void main() {
drag.dispose(); 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) { testGesture('Drag details', (GestureTester tester) {
expect(new DragDownDetails(), hasOneLineDescription); expect(new DragDownDetails(), hasOneLineDescription);
expect(new DragStartDetails(), hasOneLineDescription); expect(new DragStartDetails(), hasOneLineDescription);
......
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