Unverified Commit 4aad058a authored by David Reveman's avatar David Reveman Committed by GitHub

Improve resampling of up and remove events. (#69096)

* Improve resampling of up and remove events.

This improves resampling of these events by searching
for them until the next approximate sample time.
Co-authored-by: 's avatarDavid Reveman <reveman@google.com>
parent d306c37b
...@@ -74,9 +74,11 @@ class _Resampler { ...@@ -74,9 +74,11 @@ class _Resampler {
// //
// `samplingOffset` is relative to the current frame time, which // `samplingOffset` is relative to the current frame time, which
// can be in the past when we're not actively resampling. // can be in the past when we're not actively resampling.
// `samplingInterval` is used to determine the approximate next
// time for resampling.
// `currentSystemFrameTimeStamp` is used to determine the current // `currentSystemFrameTimeStamp` is used to determine the current
// frame time. // frame time.
void sample(Duration samplingOffset) { void sample(Duration samplingOffset, Duration samplingInterval) {
final SchedulerBinding? scheduler = SchedulerBinding.instance; final SchedulerBinding? scheduler = SchedulerBinding.instance;
assert(scheduler != null); assert(scheduler != null);
...@@ -86,10 +88,14 @@ class _Resampler { ...@@ -86,10 +88,14 @@ class _Resampler {
// resampling events. // resampling events.
final Duration sampleTime = _frameTime + samplingOffset; final Duration sampleTime = _frameTime + samplingOffset;
// Determine next sample time by adding the sampling interval
// to the current sample time.
final Duration nextSampleTime = sampleTime + samplingInterval;
// Iterate over active resamplers and sample pointer events for // Iterate over active resamplers and sample pointer events for
// current sample time. // current sample time.
for (final PointerEventResampler resampler in _resamplers.values) { for (final PointerEventResampler resampler in _resamplers.values) {
resampler.sample(sampleTime, _handlePointerEvent); resampler.sample(sampleTime, nextSampleTime, _handlePointerEvent);
} }
// Remove inactive resamplers. // Remove inactive resamplers.
...@@ -138,6 +144,13 @@ class _Resampler { ...@@ -138,6 +144,13 @@ class _Resampler {
// 4.666 ms margin is added for this. // 4.666 ms margin is added for this.
const Duration _defaultSamplingOffset = Duration(milliseconds: -38); const Duration _defaultSamplingOffset = Duration(milliseconds: -38);
// The sampling interval.
//
// Sampling interval is used to determine the approximate time for subsequent
// sampling. This is used to decide if early processing of up and removed events
// is appropriate. 16667 us for 60hz sampling interval.
const Duration _samplingInterval = Duration(microseconds: 16667);
/// A binding for the gesture subsystem. /// A binding for the gesture subsystem.
/// ///
/// ## Lifecycle of pointer events and the gesture arena /// ## Lifecycle of pointer events and the gesture arena
...@@ -257,7 +270,7 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H ...@@ -257,7 +270,7 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
if (resamplingEnabled) { if (resamplingEnabled) {
_resampler.addOrDispatch(event); _resampler.addOrDispatch(event);
_resampler.sample(samplingOffset); _resampler.sample(samplingOffset, _samplingInterval);
return; return;
} }
...@@ -388,7 +401,7 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H ...@@ -388,7 +401,7 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
void _handleSampleTimeChanged() { void _handleSampleTimeChanged() {
if (!locked) { if (!locked) {
if (resamplingEnabled) { if (resamplingEnabled) {
_resampler.sample(samplingOffset); _resampler.sample(samplingOffset, _samplingInterval);
} }
else { else {
_resampler.stop(); _resampler.stop();
......
...@@ -164,51 +164,44 @@ class PointerEventResampler { ...@@ -164,51 +164,44 @@ class PointerEventResampler {
void _dequeueAndSampleNonHoverOrMovePointerEventsUntil( void _dequeueAndSampleNonHoverOrMovePointerEventsUntil(
Duration sampleTime, Duration sampleTime,
Duration nextSampleTime,
HandleEventCallback callback, HandleEventCallback callback,
) { ) {
while (_queuedEvents.isNotEmpty) { Duration endTime = sampleTime;
final PointerEvent event = _queuedEvents.first; // Scan queued events to determine end time.
final Iterator<PointerEvent> it = _queuedEvents.iterator;
while (it.moveNext()) {
final PointerEvent event = it.current;
// Potentially stop dispatching events if more recent than `sampleTime`. // Potentially stop dispatching events if more recent than `sampleTime`.
if (event.timeStamp > sampleTime) { if (event.timeStamp > sampleTime) {
// Stop if event is not up or removed. Otherwise, continue to // Definitely stop if more recent than `nextSampleTime`.
// allow early processing of up and remove events as this improves if (event.timeStamp >= nextSampleTime) {
// resampling of these events, which is important for fling
// animations.
if (event is! PointerUpEvent && event is! PointerRemovedEvent) {
break; break;
} }
// When this line is reached, the following two invariants hold: // Update `endTime` to allow early processing of up and removed
// (1) `event.timeStamp > sampleTime` // events as this improves resampling of these events, which is
// (2) `_next` has the smallest time stamp that's no less than // important for fling animations.
// `sampleTime` if (event is PointerUpEvent || event is PointerRemovedEvent) {
// endTime = event.timeStamp;
// Therefore, event must satisfy `event.timeStamp >= _next.timeStamp`. continue;
// }
// Those events with the minimum `event.timeStamp == _next.timeStamp`
// time stamp are processed early for smoother fling. For events with // Stop if event is not move or hover.
// `event.timeStamp > _next.timeStamp`, the following lines break the if (event is! PointerMoveEvent && event is! PointerHoverEvent) {
// while loop to stop the early processing.
//
// Specifically, when `sampleTime < _next.timeStamp`, there must be
// at least one event with `_next.timeStamp == event.timeStamp`
// and that event is `_next` itself, and it will be processed early.
//
// When `sampleTime == _next.timeStamp`, all events with
// `event.timeStamp > sampleTime` must also have
// `event.timeStamp > _next.timeStamp` so no events will be processed
// early.
//
// When the input frequency is no greater than the sampling
// frequency, this early processing should guarantee that `up` and
// `remove` events are always re-sampled.
final Duration nextTimeStamp = _next?.timeStamp ?? Duration.zero;
assert(event.timeStamp >= nextTimeStamp);
if (event.timeStamp > nextTimeStamp) {
break; break;
} }
} }
}
while (_queuedEvents.isNotEmpty) {
final PointerEvent event = _queuedEvents.first;
// Stop dispatching events if more recent than `endTime`.
if (event.timeStamp > endTime) {
break;
}
final bool wasTracked = _isTracked; final bool wasTracked = _isTracked;
final bool wasDown = _isDown; final bool wasDown = _isDown;
...@@ -285,11 +278,19 @@ class PointerEventResampler { ...@@ -285,11 +278,19 @@ class PointerEventResampler {
/// state that has changed since last sample. /// state that has changed since last sample.
/// ///
/// Calling [callback] must not add or sample events. /// Calling [callback] must not add or sample events.
void sample(Duration sampleTime, HandleEventCallback callback) { ///
/// Positive value for `nextSampleTime` allow early processing of
/// up and removed events. This improves resampling of these events,
/// which is important for fling animations.
void sample(
Duration sampleTime,
Duration nextSampleTime,
HandleEventCallback callback,
) {
_processPointerEvents(sampleTime); _processPointerEvents(sampleTime);
// Dequeue and sample pointer events until `sampleTime`. // Dequeue and sample pointer events until `sampleTime`.
_dequeueAndSampleNonHoverOrMovePointerEventsUntil(sampleTime, callback); _dequeueAndSampleNonHoverOrMovePointerEventsUntil(sampleTime, nextSampleTime, callback);
// Dispatch resampled pointer location event if tracked. // Dispatch resampled pointer location event if tracked.
if (_isTracked) { if (_isTracked) {
......
...@@ -30,32 +30,37 @@ void main() { ...@@ -30,32 +30,37 @@ void main() {
ui.PointerData( ui.PointerData(
change: ui.PointerChange.down, change: ui.PointerChange.down,
physicalX: 0.0, physicalX: 0.0,
timeStamp: epoch + const Duration(milliseconds: 1), timeStamp: epoch + const Duration(milliseconds: 10),
), ),
ui.PointerData( ui.PointerData(
change: ui.PointerChange.move, change: ui.PointerChange.move,
physicalX: 10.0, physicalX: 10.0,
timeStamp: epoch + const Duration(milliseconds: 2), timeStamp: epoch + const Duration(milliseconds: 20),
), ),
ui.PointerData( ui.PointerData(
change: ui.PointerChange.move, change: ui.PointerChange.move,
physicalX: 20.0, physicalX: 20.0,
timeStamp: epoch + const Duration(milliseconds: 3), timeStamp: epoch + const Duration(milliseconds: 30),
), ),
ui.PointerData( ui.PointerData(
change: ui.PointerChange.move, change: ui.PointerChange.move,
physicalX: 30.0, physicalX: 30.0,
timeStamp: epoch + const Duration(milliseconds: 4), timeStamp: epoch + const Duration(milliseconds: 40),
),
ui.PointerData(
change: ui.PointerChange.move,
physicalX: 40.0,
timeStamp: epoch + const Duration(milliseconds: 50),
), ),
ui.PointerData( ui.PointerData(
change: ui.PointerChange.up, change: ui.PointerChange.up,
physicalX: 40.0, physicalX: 40.0,
timeStamp: epoch + const Duration(milliseconds: 5), timeStamp: epoch + const Duration(milliseconds: 60),
), ),
ui.PointerData( ui.PointerData(
change: ui.PointerChange.remove, change: ui.PointerChange.remove,
physicalX: 40.0, physicalX: 40.0,
timeStamp: epoch + const Duration(milliseconds: 6), timeStamp: epoch + const Duration(milliseconds: 70),
), ),
], ],
); );
...@@ -74,27 +79,27 @@ void main() { ...@@ -74,27 +79,27 @@ void main() {
); );
GestureBinding.instance!.resamplingEnabled = true; GestureBinding.instance!.resamplingEnabled = true;
const Duration kSamplingOffset = Duration(microseconds: -5500); const Duration kSamplingOffset = Duration(milliseconds: -5);
GestureBinding.instance!.samplingOffset = kSamplingOffset; GestureBinding.instance!.samplingOffset = kSamplingOffset;
ui.window.onPointerDataPacket!(packet); ui.window.onPointerDataPacket!(packet);
expect(events.length, 0); expect(events.length, 0);
await tester.pump(const Duration(milliseconds: 7)); await tester.pump(const Duration(milliseconds: 20));
expect(events.length, 1); expect(events.length, 1);
expect(events[0], isA<PointerDownEvent>()); expect(events[0], isA<PointerDownEvent>());
expect(events[0].timeStamp, currentTestFrameTime() + kSamplingOffset); expect(events[0].timeStamp, currentTestFrameTime() + kSamplingOffset);
expect(events[0].position, Offset(5.0 / ui.window.devicePixelRatio, 0.0)); expect(events[0].position, Offset(5.0 / ui.window.devicePixelRatio, 0.0));
// Now the system time is epoch + 9ms // Now the system time is epoch + 40ms
await tester.pump(const Duration(milliseconds: 2)); await tester.pump(const Duration(milliseconds: 20));
expect(events.length, 2); expect(events.length, 2);
expect(events[1].timeStamp, currentTestFrameTime() + kSamplingOffset); expect(events[1].timeStamp, currentTestFrameTime() + kSamplingOffset);
expect(events[1], isA<PointerMoveEvent>()); expect(events[1], isA<PointerMoveEvent>());
expect(events[1].position, Offset(25.0 / ui.window.devicePixelRatio, 0.0)); expect(events[1].position, Offset(25.0 / ui.window.devicePixelRatio, 0.0));
expect(events[1].delta, Offset(20.0 / ui.window.devicePixelRatio, 0.0)); expect(events[1].delta, Offset(20.0 / ui.window.devicePixelRatio, 0.0));
// Now the system time is epoch + 11ms // Now the system time is epoch + 60ms
await tester.pump(const Duration(milliseconds: 2)); await tester.pump(const Duration(milliseconds: 20));
expect(events.length, 4); expect(events.length, 4);
expect(events[2].timeStamp, currentTestFrameTime() + kSamplingOffset); expect(events[2].timeStamp, currentTestFrameTime() + kSamplingOffset);
expect(events[2], isA<PointerMoveEvent>()); expect(events[2], isA<PointerMoveEvent>());
......
...@@ -56,6 +56,20 @@ void main() { ...@@ -56,6 +56,20 @@ void main() {
); );
} }
PointerEvent _createSimulatedPointerHoverEvent(
int timeStampUs,
double x,
double y,
double deltaX,
double deltaY,
) {
return PointerHoverEvent(
timeStamp: Duration(microseconds: timeStampUs),
position: Offset(x, y),
delta: Offset(deltaX, deltaY),
);
}
PointerEvent _createSimulatedPointerUpEvent( PointerEvent _createSimulatedPointerUpEvent(
int timeStampUs, int timeStampUs,
double x, double x,
...@@ -70,11 +84,14 @@ void main() { ...@@ -70,11 +84,14 @@ void main() {
test('basic', () { test('basic', () {
final PointerEventResampler resampler = PointerEventResampler(); final PointerEventResampler resampler = PointerEventResampler();
final PointerEvent event0 = _createSimulatedPointerAddedEvent(1000, 0.0, 50.0); final PointerEvent event0 = _createSimulatedPointerAddedEvent(1000, 0.0, 50.0);
final PointerEvent event1 = _createSimulatedPointerDownEvent(2000, 10.0, 40.0); final PointerEvent event1 = _createSimulatedPointerHoverEvent(2000, 10.0, 40.0, 10.0, -10.0);
final PointerEvent event2 = _createSimulatedPointerMoveEvent(3000, 20.0, 30.0, 10.0, -10.0); final PointerEvent event2 = _createSimulatedPointerDownEvent(2000, 10.0, 40.0);
final PointerEvent event3 = _createSimulatedPointerMoveEvent(4000, 30.0, 20.0, 10.0, -10.0); final PointerEvent event3 = _createSimulatedPointerMoveEvent(3000, 20.0, 30.0, 10.0, -10.0);
final PointerEvent event4 = _createSimulatedPointerUpEvent(5000, 40.0, 10.0); final PointerEvent event4 = _createSimulatedPointerMoveEvent(4000, 30.0, 20.0, 10.0, -10.0);
final PointerEvent event5 = _createSimulatedPointerRemovedEvent(6000, 50.0, 0.0); final PointerEvent event5 = _createSimulatedPointerUpEvent(4000, 30.0, 20.0);
final PointerEvent event6 = _createSimulatedPointerHoverEvent(5000, 40.0, 10.0, 10.0, -10.0);
final PointerEvent event7 = _createSimulatedPointerHoverEvent(6000, 50.0, 0.0, 10.0, -10.0);
final PointerEvent event8 = _createSimulatedPointerRemovedEvent(6000, 50.0, 0.0);
resampler resampler
..addEvent(event0) ..addEvent(event0)
...@@ -82,16 +99,19 @@ void main() { ...@@ -82,16 +99,19 @@ void main() {
..addEvent(event2) ..addEvent(event2)
..addEvent(event3) ..addEvent(event3)
..addEvent(event4) ..addEvent(event4)
..addEvent(event5); ..addEvent(event5)
..addEvent(event6)
..addEvent(event7)
..addEvent(event8);
final List<PointerEvent> result = <PointerEvent>[]; final List<PointerEvent> result = <PointerEvent>[];
resampler.sample(const Duration(microseconds: 500), result.add); resampler.sample(const Duration(microseconds: 500), Duration.zero, result.add);
// No pointer event should have been returned yet. // No pointer event should have been returned yet.
expect(result.isEmpty, true); expect(result.isEmpty, true);
resampler.sample(const Duration(microseconds: 1500), result.add); resampler.sample(const Duration(microseconds: 1500), Duration.zero, result.add);
// Add pointer event should have been returned. // Add pointer event should have been returned.
expect(result.length, 1); expect(result.length, 1);
...@@ -100,7 +120,7 @@ void main() { ...@@ -100,7 +120,7 @@ void main() {
expect(result[0].position.dx, 5.0); expect(result[0].position.dx, 5.0);
expect(result[0].position.dy, 45.0); expect(result[0].position.dy, 45.0);
resampler.sample(const Duration(microseconds: 2500), result.add); resampler.sample(const Duration(microseconds: 2500), Duration.zero, result.add);
// Hover and down pointer events should have been returned. // Hover and down pointer events should have been returned.
expect(result.length, 3); expect(result.length, 3);
...@@ -115,7 +135,7 @@ void main() { ...@@ -115,7 +135,7 @@ void main() {
expect(result[2].position.dx, 15.0); expect(result[2].position.dx, 15.0);
expect(result[2].position.dy, 35.0); expect(result[2].position.dy, 35.0);
resampler.sample(const Duration(microseconds: 3500), result.add); resampler.sample(const Duration(microseconds: 3500), Duration.zero, result.add);
// Move pointer event should have been returned. // Move pointer event should have been returned.
expect(result.length, 4); expect(result.length, 4);
...@@ -126,7 +146,7 @@ void main() { ...@@ -126,7 +146,7 @@ void main() {
expect(result[3].delta.dx, 10.0); expect(result[3].delta.dx, 10.0);
expect(result[3].delta.dy, -10.0); expect(result[3].delta.dy, -10.0);
resampler.sample(const Duration(microseconds: 4500), result.add); resampler.sample(const Duration(microseconds: 4500), Duration.zero, result.add);
// Move and up pointer events should have been returned. // Move and up pointer events should have been returned.
expect(result.length, 6); expect(result.length, 6);
...@@ -141,35 +161,49 @@ void main() { ...@@ -141,35 +161,49 @@ void main() {
expect(result[5].position.dx, 35.0); expect(result[5].position.dx, 35.0);
expect(result[5].position.dy, 15.0); expect(result[5].position.dy, 15.0);
resampler.sample(const Duration(microseconds: 5500), result.add); resampler.sample(const Duration(microseconds: 5500), Duration.zero, result.add);
// Hover and remove pointer events should have been returned. // Hover pointer event should have been returned.
expect(result.length, 8); expect(result.length, 7);
expect(result[6].timeStamp, const Duration(microseconds: 5500)); expect(result[6].timeStamp, const Duration(microseconds: 5500));
expect(result[6] is PointerHoverEvent, true); expect(result[6] is PointerHoverEvent, true);
expect(result[6].position.dx, 45.0); expect(result[6].position.dx, 45.0);
expect(result[6].position.dy, 5.0); expect(result[6].position.dy, 5.0);
expect(result[6].delta.dx, 10.0); expect(result[6].delta.dx, 10.0);
expect(result[6].delta.dy, -10.0); expect(result[6].delta.dy, -10.0);
expect(result[7].timeStamp, const Duration(microseconds: 5500));
expect(result[7] is PointerRemovedEvent, true);
expect(result[7].position.dx, 45.0);
expect(result[7].position.dy, 5.0);
resampler.sample(const Duration(microseconds: 6500), result.add); resampler.sample(const Duration(microseconds: 6500), Duration.zero, result.add);
// Hover and removed pointer events should have been returned.
expect(result.length, 9);
expect(result[7].timeStamp, const Duration(microseconds: 6500));
expect(result[7] is PointerHoverEvent, true);
expect(result[7].position.dx, 50.0);
expect(result[7].position.dy, 0.0);
expect(result[7].delta.dx, 5.0);
expect(result[7].delta.dy, -5.0);
expect(result[8].timeStamp, const Duration(microseconds: 6500));
expect(result[8] is PointerRemovedEvent, true);
expect(result[8].position.dx, 50.0);
expect(result[8].position.dy, 0.0);
resampler.sample(const Duration(microseconds: 7500), Duration.zero, result.add);
// No pointer event should have been returned. // No pointer event should have been returned.
expect(result.length, 8); expect(result.length, 9);
}); });
test('stream', () { test('stream', () {
final PointerEventResampler resampler = PointerEventResampler(); final PointerEventResampler resampler = PointerEventResampler();
final PointerEvent event0 = _createSimulatedPointerAddedEvent(1000, 0.0, 50.0); final PointerEvent event0 = _createSimulatedPointerAddedEvent(1000, 0.0, 50.0);
final PointerEvent event1 = _createSimulatedPointerDownEvent(2000, 10.0, 40.0); final PointerEvent event1 = _createSimulatedPointerHoverEvent(2000, 10.0, 40.0, 10.0, -10.0);
final PointerEvent event2 = _createSimulatedPointerMoveEvent(3000, 20.0, 30.0, 10.0, -10.0); final PointerEvent event2 = _createSimulatedPointerDownEvent(2000, 10.0, 40.0);
final PointerEvent event3 = _createSimulatedPointerMoveEvent(4000, 30.0, 20.0, 10.0, -10.0); final PointerEvent event3 = _createSimulatedPointerMoveEvent(3000, 20.0, 30.0, 10.0, -10.0);
final PointerEvent event4 = _createSimulatedPointerUpEvent(5000, 40.0, 10.0); final PointerEvent event4 = _createSimulatedPointerMoveEvent(4000, 30.0, 20.0, 10.0, -10.0);
final PointerEvent event5 = _createSimulatedPointerRemovedEvent(6000, 50.0, 0.0); final PointerEvent event5 = _createSimulatedPointerUpEvent(4000, 30.0, 20.0);
final PointerEvent event6 = _createSimulatedPointerHoverEvent(5000, 40.0, 10.0, 10.0, -10.0);
final PointerEvent event7 = _createSimulatedPointerHoverEvent(6000, 50.0, 0.0, 10.0, -10.0);
final PointerEvent event8 = _createSimulatedPointerRemovedEvent(6000, 50.0, 0.0);
resampler.addEvent(event0); resampler.addEvent(event0);
...@@ -179,14 +213,16 @@ void main() { ...@@ -179,14 +213,16 @@ void main() {
final List<PointerEvent> result = <PointerEvent>[]; final List<PointerEvent> result = <PointerEvent>[];
resampler.sample(const Duration(microseconds: 500), result.add); resampler.sample(const Duration(microseconds: 500), Duration.zero, result.add);
// No pointer event should have been returned yet. // No pointer event should have been returned yet.
expect(result.isEmpty, true); expect(result.isEmpty, true);
resampler.addEvent(event1); resampler
..addEvent(event1)
..addEvent(event2);
resampler.sample(const Duration(microseconds: 500), result.add); resampler.sample(const Duration(microseconds: 500), Duration.zero, result.add);
// No pointer event should have been returned yet. // No pointer event should have been returned yet.
expect(result.isEmpty, true); expect(result.isEmpty, true);
...@@ -195,18 +231,18 @@ void main() { ...@@ -195,18 +231,18 @@ void main() {
// Advance sample time to 1.5 ms. // Advance sample time to 1.5 ms.
// //
resampler.sample(const Duration(microseconds: 1500), result.add); resampler.sample(const Duration(microseconds: 1500), Duration.zero, result.add);
// Add pointer event should have been returned. // Added pointer event should have been returned.
expect(result.length, 1); expect(result.length, 1);
expect(result[0].timeStamp, const Duration(microseconds: 1500)); expect(result[0].timeStamp, const Duration(microseconds: 1500));
expect(result[0] is PointerAddedEvent, true); expect(result[0] is PointerAddedEvent, true);
expect(result[0].position.dx, 5.0); expect(result[0].position.dx, 5.0);
expect(result[0].position.dy, 45.0); expect(result[0].position.dy, 45.0);
resampler.addEvent(event2); resampler.addEvent(event3);
resampler.sample(const Duration(microseconds: 1500), result.add); resampler.sample(const Duration(microseconds: 1500), Duration.zero, result.add);
// No more pointer events should have been returned. // No more pointer events should have been returned.
expect(result.length, 1); expect(result.length, 1);
...@@ -215,7 +251,7 @@ void main() { ...@@ -215,7 +251,7 @@ void main() {
// Advance sample time to 2.5 ms. // Advance sample time to 2.5 ms.
// //
resampler.sample(const Duration(microseconds: 2500), result.add); resampler.sample(const Duration(microseconds: 2500), Duration.zero, result.add);
// Hover and down pointer events should have been returned. // Hover and down pointer events should have been returned.
expect(result.length, 3); expect(result.length, 3);
...@@ -230,9 +266,11 @@ void main() { ...@@ -230,9 +266,11 @@ void main() {
expect(result[2].position.dx, 15.0); expect(result[2].position.dx, 15.0);
expect(result[2].position.dy, 35.0); expect(result[2].position.dy, 35.0);
resampler.addEvent(event3); resampler
..addEvent(event4)
..addEvent(event5);
resampler.sample(const Duration(microseconds: 2500), result.add); resampler.sample(const Duration(microseconds: 2500), Duration.zero, result.add);
// No more pointer events should have been returned. // No more pointer events should have been returned.
expect(result.length, 3); expect(result.length, 3);
...@@ -241,7 +279,7 @@ void main() { ...@@ -241,7 +279,7 @@ void main() {
// Advance sample time to 3.5 ms. // Advance sample time to 3.5 ms.
// //
resampler.sample(const Duration(microseconds: 3500), result.add); resampler.sample(const Duration(microseconds: 3500), Duration.zero, result.add);
// Move pointer event should have been returned. // Move pointer event should have been returned.
expect(result.length, 4); expect(result.length, 4);
...@@ -252,9 +290,9 @@ void main() { ...@@ -252,9 +290,9 @@ void main() {
expect(result[3].delta.dx, 10.0); expect(result[3].delta.dx, 10.0);
expect(result[3].delta.dy, -10.0); expect(result[3].delta.dy, -10.0);
resampler.addEvent(event4); resampler.addEvent(event6);
resampler.sample(const Duration(microseconds: 3500), result.add); resampler.sample(const Duration(microseconds: 3500), Duration.zero, result.add);
// No more pointer events should have been returned. // No more pointer events should have been returned.
expect(result.length, 4); expect(result.length, 4);
...@@ -263,7 +301,7 @@ void main() { ...@@ -263,7 +301,7 @@ void main() {
// Advance sample time to 4.5 ms. // Advance sample time to 4.5 ms.
// //
resampler.sample(const Duration(microseconds: 4500), result.add); resampler.sample(const Duration(microseconds: 4500), Duration.zero, result.add);
// Move and up pointer events should have been returned. // Move and up pointer events should have been returned.
expect(result.length, 6); expect(result.length, 6);
...@@ -278,9 +316,11 @@ void main() { ...@@ -278,9 +316,11 @@ void main() {
expect(result[5].position.dx, 35.0); expect(result[5].position.dx, 35.0);
expect(result[5].position.dy, 15.0); expect(result[5].position.dy, 15.0);
resampler.addEvent(event5); resampler
..addEvent(event7)
..addEvent(event8);
resampler.sample(const Duration(microseconds: 4500), result.add); resampler.sample(const Duration(microseconds: 4500), Duration.zero, result.add);
// No more pointer events should have been returned. // No more pointer events should have been returned.
expect(result.length, 6); expect(result.length, 6);
...@@ -289,29 +329,44 @@ void main() { ...@@ -289,29 +329,44 @@ void main() {
// Advance sample time to 5.5 ms. // Advance sample time to 5.5 ms.
// //
resampler.sample(const Duration(microseconds: 5500), result.add); resampler.sample(const Duration(microseconds: 5500), Duration.zero, result.add);
// Hover and remove pointer event should have been returned. // Hover pointer event should have been returned.
expect(result.length, 8); expect(result.length, 7);
expect(result[6].timeStamp, const Duration(microseconds: 5500)); expect(result[6].timeStamp, const Duration(microseconds: 5500));
expect(result[6] is PointerHoverEvent, true); expect(result[6] is PointerHoverEvent, true);
expect(result[6].position.dx, 45.0); expect(result[6].position.dx, 45.0);
expect(result[6].position.dy, 5.0); expect(result[6].position.dy, 5.0);
expect(result[6].delta.dx, 10.0); expect(result[6].delta.dx, 10.0);
expect(result[6].delta.dy, -10.0); expect(result[6].delta.dy, -10.0);
expect(result[7].timeStamp, const Duration(microseconds: 5500));
expect(result[7] is PointerRemovedEvent, true);
expect(result[7].position.dx, 45.0);
expect(result[7].position.dy, 5.0);
// //
// Advance sample time to 6.5 ms. // Advance sample time to 6.5 ms.
// //
resampler.sample(const Duration(microseconds: 6500), result.add); resampler.sample(const Duration(microseconds: 6500), Duration.zero, result.add);
// Hover and removed pointer event should have been returned.
expect(result.length, 9);
expect(result[7].timeStamp, const Duration(microseconds: 6500));
expect(result[7] is PointerHoverEvent, true);
expect(result[7].position.dx, 50.0);
expect(result[7].position.dy, 0.0);
expect(result[7].delta.dx, 5.0);
expect(result[7].delta.dy, -5.0);
expect(result[8].timeStamp, const Duration(microseconds: 6500));
expect(result[8] is PointerRemovedEvent, true);
expect(result[8].position.dx, 50.0);
expect(result[8].position.dy, 0.0);
//
// Advance sample time to 7.5 ms.
//
resampler.sample(const Duration(microseconds: 7500), Duration.zero, result.add);
// No pointer events should have been returned. // No pointer events should have been returned.
expect(result.length, 8); expect(result.length, 9);
}); });
test('quick tap', () { test('quick tap', () {
...@@ -329,7 +384,7 @@ void main() { ...@@ -329,7 +384,7 @@ void main() {
final List<PointerEvent> result = <PointerEvent>[]; final List<PointerEvent> result = <PointerEvent>[];
resampler.sample(const Duration(microseconds: 1500), result.add); resampler.sample(const Duration(microseconds: 1500), Duration.zero, result.add);
// All pointer events should have been returned. // All pointer events should have been returned.
expect(result.length, 4); expect(result.length, 4);
...@@ -356,19 +411,21 @@ void main() { ...@@ -356,19 +411,21 @@ void main() {
final PointerEvent event0 = _createSimulatedPointerAddedEvent(1000, 0.0, 0.0); final PointerEvent event0 = _createSimulatedPointerAddedEvent(1000, 0.0, 0.0);
final PointerEvent event1 = _createSimulatedPointerDownEvent(1000, 0.0, 0.0); final PointerEvent event1 = _createSimulatedPointerDownEvent(1000, 0.0, 0.0);
final PointerEvent event2 = _createSimulatedPointerMoveEvent(2000, 10.0, 0.0, 10.0, 0.0); final PointerEvent event2 = _createSimulatedPointerMoveEvent(2000, 10.0, 0.0, 10.0, 0.0);
final PointerEvent event3 = _createSimulatedPointerUpEvent(3000, 20.0, 0.0); final PointerEvent event3 = _createSimulatedPointerMoveEvent(3000, 20.0, 0.0, 10.0, 0.0);
final PointerEvent event4 = _createSimulatedPointerRemovedEvent(3000, 20.0, 0.0); final PointerEvent event4 = _createSimulatedPointerUpEvent(3000, 20.0, 0.0);
final PointerEvent event5 = _createSimulatedPointerRemovedEvent(3000, 20.0, 0.0);
resampler resampler
..addEvent(event0) ..addEvent(event0)
..addEvent(event1) ..addEvent(event1)
..addEvent(event2) ..addEvent(event2)
..addEvent(event3) ..addEvent(event3)
..addEvent(event4); ..addEvent(event4)
..addEvent(event5);
final List<PointerEvent> result = <PointerEvent>[]; final List<PointerEvent> result = <PointerEvent>[];
resampler.sample(const Duration(microseconds: 1500), result.add); resampler.sample(const Duration(microseconds: 1500), Duration.zero, result.add);
// Added and down pointer events should have been returned. // Added and down pointer events should have been returned.
expect(result.length, 2); expect(result.length, 2);
...@@ -381,12 +438,12 @@ void main() { ...@@ -381,12 +438,12 @@ void main() {
expect(result[1].position.dx, 5.0); expect(result[1].position.dx, 5.0);
expect(result[1].position.dy, 0.0); expect(result[1].position.dy, 0.0);
resampler.sample(const Duration(microseconds: 1500), result.add); resampler.sample(const Duration(microseconds: 1500), Duration.zero, result.add);
// No pointer events should have been returned. // No pointer events should have been returned.
expect(result.length, 2); expect(result.length, 2);
resampler.sample(const Duration(microseconds: 1750), result.add); resampler.sample(const Duration(microseconds: 1750), Duration.zero, result.add);
// Move pointer event should have been returned. // Move pointer event should have been returned.
expect(result.length, 3); expect(result.length, 3);
...@@ -397,7 +454,7 @@ void main() { ...@@ -397,7 +454,7 @@ void main() {
expect(result[2].delta.dx, 2.5); expect(result[2].delta.dx, 2.5);
expect(result[2].delta.dy, 0.0); expect(result[2].delta.dy, 0.0);
resampler.sample(const Duration(microseconds: 2000), result.add); resampler.sample(const Duration(microseconds: 2000), Duration.zero, result.add);
// Another move pointer event should have been returned. // Another move pointer event should have been returned.
expect(result.length, 4); expect(result.length, 4);
...@@ -408,23 +465,23 @@ void main() { ...@@ -408,23 +465,23 @@ void main() {
expect(result[3].delta.dx, 2.5); expect(result[3].delta.dx, 2.5);
expect(result[3].delta.dy, 0.0); expect(result[3].delta.dy, 0.0);
resampler.sample(const Duration(microseconds: 2500), result.add); resampler.sample(const Duration(microseconds: 3000), Duration.zero, result.add);
// Move, up and removed pointer events should have been returned. // Move, up and removed pointer events should have been returned.
expect(result.length, 7); expect(result.length, 7);
expect(result[4].timeStamp, const Duration(microseconds: 2500)); expect(result[4].timeStamp, const Duration(microseconds: 3000));
expect(result[4] is PointerMoveEvent, true); expect(result[4] is PointerMoveEvent, true);
expect(result[4].position.dx, 15.0); expect(result[4].position.dx, 20.0);
expect(result[4].position.dy, 0.0); expect(result[4].position.dy, 0.0);
expect(result[4].delta.dx, 5.0); expect(result[4].delta.dx, 10.0);
expect(result[4].delta.dy, 0.0); expect(result[4].delta.dy, 0.0);
expect(result[5].timeStamp, const Duration(microseconds: 2500)); expect(result[5].timeStamp, const Duration(microseconds: 3000));
expect(result[5] is PointerUpEvent, true); expect(result[5] is PointerUpEvent, true);
expect(result[5].position.dx, 15.0); expect(result[5].position.dx, 20.0);
expect(result[5].position.dy, 0.0); expect(result[5].position.dy, 0.0);
expect(result[6].timeStamp, const Duration(microseconds: 2500)); expect(result[6].timeStamp, const Duration(microseconds: 3000));
expect(result[6] is PointerRemovedEvent, true); expect(result[6] is PointerRemovedEvent, true);
expect(result[6].position.dx, 15.0); expect(result[6].position.dx, 20.0);
expect(result[6].position.dy, 0.0); expect(result[6].position.dy, 0.0);
}); });
...@@ -447,9 +504,9 @@ void main() { ...@@ -447,9 +504,9 @@ void main() {
final List<PointerEvent> result = <PointerEvent>[]; final List<PointerEvent> result = <PointerEvent>[];
resampler.sample(const Duration(microseconds: 2500), result.add); resampler.sample(const Duration(microseconds: 2500), Duration.zero, result.add);
// Add and down pointer events should have been returned. // Addeds and down pointer events should have been returned.
expect(result.length, 2); expect(result.length, 2);
expect(result[0].timeStamp, const Duration(microseconds: 2500)); expect(result[0].timeStamp, const Duration(microseconds: 2500));
expect(result[0] is PointerAddedEvent, true); expect(result[0] is PointerAddedEvent, true);
...@@ -460,7 +517,7 @@ void main() { ...@@ -460,7 +517,7 @@ void main() {
expect(result[1].position.dx, 12.5); expect(result[1].position.dx, 12.5);
expect(result[1].position.dy, 0.0); expect(result[1].position.dy, 0.0);
resampler.sample(const Duration(microseconds: 5500), result.add); resampler.sample(const Duration(microseconds: 5500), Duration.zero, result.add);
// Move, up and removed pointer events should have been returned. // Move, up and removed pointer events should have been returned.
expect(result.length, 5); expect(result.length, 5);
...@@ -479,7 +536,7 @@ void main() { ...@@ -479,7 +536,7 @@ void main() {
expect(result[4].position.dx, 30.0); expect(result[4].position.dx, 30.0);
expect(result[4].position.dy, 0.0); expect(result[4].position.dy, 0.0);
resampler.sample(const Duration(microseconds: 6500), result.add); resampler.sample(const Duration(microseconds: 6500), Duration.zero, result.add);
// No pointer events should have been returned. // No pointer events should have been returned.
expect(result.length, 5); expect(result.length, 5);
...@@ -491,9 +548,11 @@ void main() { ...@@ -491,9 +548,11 @@ void main() {
final PointerEvent event1 = _createSimulatedPointerDownEvent(1000, 0.0, 0.0); final PointerEvent event1 = _createSimulatedPointerDownEvent(1000, 0.0, 0.0);
final PointerEvent event2 = _createSimulatedPointerMoveEvent(2000, 10.0, 0.0, 10.0, 0.0); final PointerEvent event2 = _createSimulatedPointerMoveEvent(2000, 10.0, 0.0, 10.0, 0.0);
final PointerEvent event3 = _createSimulatedPointerUpEvent(3000, 10.0, 0.0); final PointerEvent event3 = _createSimulatedPointerUpEvent(3000, 10.0, 0.0);
final PointerEvent event4 = _createSimulatedPointerDownEvent(4000, 20.0, 0.0); final PointerEvent event4 = _createSimulatedPointerHoverEvent(4000, 20.0, 0.0, 10.0, 0.0);
final PointerEvent event5 = _createSimulatedPointerUpEvent(5000, 30.0, 0.0); final PointerEvent event5 = _createSimulatedPointerDownEvent(4000, 20.0, 0.0);
final PointerEvent event6 = _createSimulatedPointerRemovedEvent(5000, 30.0, 0.0); final PointerEvent event6 = _createSimulatedPointerMoveEvent(5000, 30.0, 0.0, 10.0, 0.0);
final PointerEvent event7 = _createSimulatedPointerUpEvent(5000, 30.0, 0.0);
final PointerEvent event8 = _createSimulatedPointerRemovedEvent(5000, 30.0, 0.0);
resampler resampler
..addEvent(event0) ..addEvent(event0)
...@@ -502,11 +561,13 @@ void main() { ...@@ -502,11 +561,13 @@ void main() {
..addEvent(event3) ..addEvent(event3)
..addEvent(event4) ..addEvent(event4)
..addEvent(event5) ..addEvent(event5)
..addEvent(event6); ..addEvent(event6)
..addEvent(event7)
..addEvent(event8);
final List<PointerEvent> result = <PointerEvent>[]; final List<PointerEvent> result = <PointerEvent>[];
resampler.sample(const Duration(microseconds: 1500), result.add); resampler.sample(const Duration(microseconds: 1500), Duration.zero, result.add);
// Added and down pointer events should have been returned. // Added and down pointer events should have been returned.
expect(result.length, 2); expect(result.length, 2);
...@@ -519,34 +580,34 @@ void main() { ...@@ -519,34 +580,34 @@ void main() {
expect(result[1].position.dx, 5.0); expect(result[1].position.dx, 5.0);
expect(result[1].position.dy, 0.0); expect(result[1].position.dy, 0.0);
resampler.sample(const Duration(microseconds: 4500), result.add); resampler.sample(const Duration(microseconds: 5500), Duration.zero, result.add);
// All remaining pointer events should have been returned. // All remaining pointer events should have been returned.
expect(result.length, 7); expect(result.length, 7);
expect(result[2].timeStamp, const Duration(microseconds: 4500)); expect(result[2].timeStamp, const Duration(microseconds: 5500));
expect(result[2] is PointerMoveEvent, true); expect(result[2] is PointerMoveEvent, true);
expect(result[2].position.dx, 25.0); expect(result[2].position.dx, 30.0);
expect(result[2].position.dy, 0.0); expect(result[2].position.dy, 0.0);
expect(result[2].delta.dx, 20.0); expect(result[2].delta.dx, 25.0);
expect(result[2].delta.dy, 0.0); expect(result[2].delta.dy, 0.0);
expect(result[3].timeStamp, const Duration(microseconds: 4500)); expect(result[3].timeStamp, const Duration(microseconds: 5500));
expect(result[3] is PointerUpEvent, true); expect(result[3] is PointerUpEvent, true);
expect(result[3].position.dx, 25.0); expect(result[3].position.dx, 30.0);
expect(result[3].position.dy, 0.0); expect(result[3].position.dy, 0.0);
expect(result[4].timeStamp, const Duration(microseconds: 4500)); expect(result[4].timeStamp, const Duration(microseconds: 5500));
expect(result[4] is PointerDownEvent, true); expect(result[4] is PointerDownEvent, true);
expect(result[4].position.dx, 25.0); expect(result[4].position.dx, 30.0);
expect(result[4].position.dy, 0.0); expect(result[4].position.dy, 0.0);
expect(result[5].timeStamp, const Duration(microseconds: 4500)); expect(result[5].timeStamp, const Duration(microseconds: 5500));
expect(result[5] is PointerUpEvent, true); expect(result[5] is PointerUpEvent, true);
expect(result[5].position.dx, 25.0); expect(result[5].position.dx, 30.0);
expect(result[5].position.dy, 0.0); expect(result[5].position.dy, 0.0);
expect(result[6].timeStamp, const Duration(microseconds: 4500)); expect(result[6].timeStamp, const Duration(microseconds: 5500));
expect(result[6] is PointerRemovedEvent, true); expect(result[6] is PointerRemovedEvent, true);
expect(result[6].position.dx, 25.0); expect(result[6].position.dx, 30.0);
expect(result[6].position.dy, 0.0); expect(result[6].position.dy, 0.0);
resampler.sample(const Duration(microseconds: 5500), result.add); resampler.sample(const Duration(microseconds: 6500), Duration.zero, result.add);
// No pointer events should have been returned. // No pointer events should have been returned.
expect(result.length, 7); expect(result.length, 7);
...@@ -556,23 +617,25 @@ void main() { ...@@ -556,23 +617,25 @@ void main() {
final PointerEventResampler resampler = PointerEventResampler(); final PointerEventResampler resampler = PointerEventResampler();
final PointerEvent event0 = _createSimulatedPointerAddedEvent(1000, 0.0, 0.0); final PointerEvent event0 = _createSimulatedPointerAddedEvent(1000, 0.0, 0.0);
final PointerEvent event1 = _createSimulatedPointerDownEvent(1000, 0.0, 0.0); final PointerEvent event1 = _createSimulatedPointerDownEvent(1000, 0.0, 0.0);
final PointerEvent event2 = _createSimulatedPointerUpEvent(4000, 30.0, 0.0); final PointerEvent event2 = _createSimulatedPointerMoveEvent(4000, 30.0, 0.0, 30.0, 0.0);
final PointerEvent event3 = _createSimulatedPointerRemovedEvent(4000, 30.0, 0.0); final PointerEvent event3 = _createSimulatedPointerUpEvent(4000, 30.0, 0.0);
final PointerEvent event4 = _createSimulatedPointerRemovedEvent(4000, 30.0, 0.0);
resampler resampler
..addEvent(event0) ..addEvent(event0)
..addEvent(event1) ..addEvent(event1)
..addEvent(event2) ..addEvent(event2)
..addEvent(event3); ..addEvent(event3)
..addEvent(event4);
final List<PointerEvent> result = <PointerEvent>[]; final List<PointerEvent> result = <PointerEvent>[];
resampler.sample(const Duration(microseconds: 500), result.add); resampler.sample(const Duration(microseconds: 500), Duration.zero, result.add);
// No pointer events should have been returned. // No pointer events should have been returned.
expect(result.isEmpty, true); expect(result.isEmpty, true);
resampler.sample(const Duration(microseconds: 5500), result.add); resampler.sample(const Duration(microseconds: 5500), Duration.zero, result.add);
// All remaining pointer events should have been returned. // All remaining pointer events should have been returned.
expect(result.length, 4); expect(result.length, 4);
...@@ -593,7 +656,7 @@ void main() { ...@@ -593,7 +656,7 @@ void main() {
expect(result[3].position.dx, 30.0); expect(result[3].position.dx, 30.0);
expect(result[3].position.dy, 0.0); expect(result[3].position.dy, 0.0);
resampler.sample(const Duration(microseconds: 6500), result.add); resampler.sample(const Duration(microseconds: 6500), Duration.zero, result.add);
// No pointer events should have been returned. // No pointer events should have been returned.
expect(result.length, 4); expect(result.length, 4);
...@@ -604,19 +667,21 @@ void main() { ...@@ -604,19 +667,21 @@ void main() {
final PointerEvent event0 = _createSimulatedPointerAddedEvent(1000, 0.0, 0.0); final PointerEvent event0 = _createSimulatedPointerAddedEvent(1000, 0.0, 0.0);
final PointerEvent event1 = _createSimulatedPointerDownEvent(2000, 0.0, 0.0); final PointerEvent event1 = _createSimulatedPointerDownEvent(2000, 0.0, 0.0);
final PointerEvent event2 = _createSimulatedPointerMoveEvent(3000, 10.0, 0.0, 10.0, 0.0); final PointerEvent event2 = _createSimulatedPointerMoveEvent(3000, 10.0, 0.0, 10.0, 0.0);
final PointerEvent event3 = _createSimulatedPointerUpEvent(4000, 20.0, 0.0); final PointerEvent event3 = _createSimulatedPointerMoveEvent(4000, 20.0, 0.0, 10.0, 0.0);
final PointerEvent event4 = _createSimulatedPointerRemovedEvent(5000, 20.0, 0.0); final PointerEvent event4 = _createSimulatedPointerUpEvent(4000, 20.0, 0.0);
final PointerEvent event5 = _createSimulatedPointerRemovedEvent(5000, 20.0, 0.0);
resampler resampler
..addEvent(event0) ..addEvent(event0)
..addEvent(event1) ..addEvent(event1)
..addEvent(event2) ..addEvent(event2)
..addEvent(event3) ..addEvent(event3)
..addEvent(event4); ..addEvent(event4)
..addEvent(event5);
final List<PointerEvent> result = <PointerEvent>[]; final List<PointerEvent> result = <PointerEvent>[];
resampler.sample(const Duration(microseconds: 500), result.add); resampler.sample(const Duration(microseconds: 500), Duration.zero, result.add);
// No pointer events should have been returned. // No pointer events should have been returned.
expect(result.isEmpty, true); expect(result.isEmpty, true);
...@@ -625,7 +690,7 @@ void main() { ...@@ -625,7 +690,7 @@ void main() {
// All pointer events should have been returned with orignal // All pointer events should have been returned with orignal
// time stamps and positions. // time stamps and positions.
expect(result.length, 5); expect(result.length, 6);
expect(result[0].timeStamp, const Duration(microseconds: 1000)); expect(result[0].timeStamp, const Duration(microseconds: 1000));
expect(result[0] is PointerAddedEvent, true); expect(result[0] is PointerAddedEvent, true);
expect(result[0].position.dx, 0.0); expect(result[0].position.dx, 0.0);
...@@ -641,18 +706,24 @@ void main() { ...@@ -641,18 +706,24 @@ void main() {
expect(result[2].delta.dx, 10.0); expect(result[2].delta.dx, 10.0);
expect(result[2].delta.dy, 0.0); expect(result[2].delta.dy, 0.0);
expect(result[3].timeStamp, const Duration(microseconds: 4000)); expect(result[3].timeStamp, const Duration(microseconds: 4000));
expect(result[3] is PointerUpEvent, true); expect(result[3] is PointerMoveEvent, true);
expect(result[3].position.dx, 20.0); expect(result[3].position.dx, 20.0);
expect(result[3].position.dy, 0.0); expect(result[3].position.dy, 0.0);
expect(result[4].timeStamp, const Duration(microseconds: 5000)); expect(result[3].delta.dx, 10.0);
expect(result[4] is PointerRemovedEvent, true); expect(result[3].delta.dy, 0.0);
expect(result[4].timeStamp, const Duration(microseconds: 4000));
expect(result[4] is PointerUpEvent, true);
expect(result[4].position.dx, 20.0); expect(result[4].position.dx, 20.0);
expect(result[4].position.dy, 0.0); expect(result[4].position.dy, 0.0);
expect(result[5].timeStamp, const Duration(microseconds: 5000));
expect(result[5] is PointerRemovedEvent, true);
expect(result[5].position.dx, 20.0);
expect(result[5].position.dy, 0.0);
resampler.sample(const Duration(microseconds: 10000), result.add); resampler.sample(const Duration(microseconds: 10000), Duration.zero, result.add);
// No pointer events should have been returned. // No pointer events should have been returned.
expect(result.length, 5); expect(result.length, 6);
}); });
test('synthetic move', () { test('synthetic move', () {
...@@ -672,12 +743,12 @@ void main() { ...@@ -672,12 +743,12 @@ void main() {
final List<PointerEvent> result = <PointerEvent>[]; final List<PointerEvent> result = <PointerEvent>[];
resampler.sample(const Duration(microseconds: 500), result.add); resampler.sample(const Duration(microseconds: 500), Duration.zero, result.add);
// No pointer events should have been returned. // No pointer events should have been returned.
expect(result.isEmpty, true); expect(result.isEmpty, true);
resampler.sample(const Duration(microseconds: 2000), result.add); resampler.sample(const Duration(microseconds: 2000), Duration.zero, result.add);
// Added and down pointer events should have been returned. // Added and down pointer events should have been returned.
expect(result.length, 2); expect(result.length, 2);
...@@ -690,7 +761,7 @@ void main() { ...@@ -690,7 +761,7 @@ void main() {
expect(result[1].position.dx, 0.0); expect(result[1].position.dx, 0.0);
expect(result[1].position.dy, 0.0); expect(result[1].position.dy, 0.0);
resampler.sample(const Duration(microseconds: 5000), result.add); resampler.sample(const Duration(microseconds: 5000), Duration.zero, result.add);
// All remaining pointer events and a synthetic move event should // All remaining pointer events and a synthetic move event should
// have been returned. // have been returned.
...@@ -710,9 +781,92 @@ void main() { ...@@ -710,9 +781,92 @@ void main() {
expect(result[4].position.dx, 10.0); expect(result[4].position.dx, 10.0);
expect(result[4].position.dy, 0.0); expect(result[4].position.dy, 0.0);
resampler.sample(const Duration(microseconds: 10000), result.add); resampler.sample(const Duration(microseconds: 10000), Duration.zero, result.add);
// No pointer events should have been returned. // No pointer events should have been returned.
expect(result.length, 5); expect(result.length, 5);
}); });
test('next sample time', () {
final PointerEventResampler resampler = PointerEventResampler();
final PointerEvent event0 = _createSimulatedPointerAddedEvent(1000, 0.0, 0.0);
final PointerEvent event1 = _createSimulatedPointerDownEvent(1000, 0.0, 0.0);
final PointerEvent event2 = _createSimulatedPointerMoveEvent(2000, 10.0, 0.0, 10.0, 0.0);
final PointerEvent event3 = _createSimulatedPointerMoveEvent(3000, 20.0, 0.0, 10.0, 0.0);
final PointerEvent event4 = _createSimulatedPointerUpEvent(3000, 20.0, 0.0);
final PointerEvent event5 = _createSimulatedPointerHoverEvent(4000, 30.0, 0.0, 10.0, 0.0);
final PointerEvent event6 = _createSimulatedPointerRemovedEvent(4000, 30.0, 0.0);
resampler
..addEvent(event0)
..addEvent(event1)
..addEvent(event2)
..addEvent(event3)
..addEvent(event4)
..addEvent(event5)
..addEvent(event6);
final List<PointerEvent> result = <PointerEvent>[];
Duration sampleTime = const Duration(microseconds: 500);
Duration nextSampleTime = const Duration(microseconds: 1500);
resampler.sample(sampleTime, nextSampleTime, result.add);
// No pointer events should have been returned.
expect(result.isEmpty, true);
sampleTime = nextSampleTime;
nextSampleTime = const Duration(microseconds: 2500);
resampler.sample(sampleTime, nextSampleTime, result.add);
// Added and down pointer events should have been returned.
expect(result.length, 2);
expect(result[0].timeStamp, const Duration(microseconds: 1500));
expect(result[0] is PointerAddedEvent, true);
expect(result[0].position.dx, 5.0);
expect(result[0].position.dy, 0.0);
expect(result[1].timeStamp, const Duration(microseconds: 1500));
expect(result[1] is PointerDownEvent, true);
expect(result[1].position.dx, 5.0);
expect(result[1].position.dy, 0.0);
sampleTime = nextSampleTime;
nextSampleTime = const Duration(microseconds: 3500);
resampler.sample(sampleTime, nextSampleTime, result.add);
// Move and up pointer events should have been returned.
expect(result.length, 4);
expect(result[2].timeStamp, const Duration(microseconds: 2500));
expect(result[2] is PointerMoveEvent, true);
expect(result[2].position.dx, 15.0);
expect(result[2].position.dy, 0.0);
expect(result[2].delta.dx, 10.0);
expect(result[2].delta.dy, 0.0);
expect(result[3].timeStamp, const Duration(microseconds: 2500));
expect(result[3] is PointerUpEvent, true);
expect(result[3].position.dx, 15.0);
expect(result[3].position.dy, 0.0);
sampleTime = nextSampleTime;
nextSampleTime = const Duration(microseconds: 4500);
resampler.sample(sampleTime, nextSampleTime, result.add);
// All remaining pointer events should have been returned.
expect(result.length, 6);
expect(result[4].timeStamp, const Duration(microseconds: 3500));
expect(result[4] is PointerHoverEvent, true);
expect(result[4].position.dx, 25.0);
expect(result[4].position.dy, 0.0);
expect(result[4].delta.dx, 10.0);
expect(result[4].delta.dy, 0.0);
expect(result[5].timeStamp, const Duration(microseconds: 3500));
expect(result[5] is PointerRemovedEvent, true);
expect(result[5].position.dx, 25.0);
expect(result[5].position.dy, 0.0);
resampler.sample(const Duration(microseconds: 10000), Duration.zero, result.add);
// No pointer events should have been returned.
expect(result.length, 6);
});
} }
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