Unverified Commit 443d8617 authored by yakagami's avatar yakagami Committed by GitHub

add sourceTimeStamp to ScaleUpdateDetails (#135936)

This PR adds the ability to get the `sourceTimeStamp` from `ScaleUpdateDetails` in a `GestureScaleUpdateCallback` like so:

```dart
onScaleUpdate: (ScaleUpdateDetails details){
  print(details.sourceTimeStamp);
}
```

`sourceTimeStamp` is necessary when tracking velocity eg.

```dart
VelocityTracker tracker = VelocityTracker.withKind(PointerDeviceKind.touch);
///...
onScaleUpdate: (ScaleUpdateDetails details){
  tracker.addPosition(details.sourceTimeStamp!, details.focalPoint);
}
```

The docs say:

>Having both a pan gesture recognizer and a scale gesture recognizer is redundant; scale is a superset of pan. Just use the scale gesture recognizer.

Currently this is not entirely accurate, and should be fixed, as noted in https://github.com/flutter/flutter/issues/43833#issuecomment-548133779. This PR does not add `sourceTimeStamp` to `ScaleStartDetails` because it is more involved. Specifically, `ScaleStartDetails` can be created in `acceptGesture` which does not have access to the `PointerEvent` to get the `event.timeStamp` (https://github.com/flutter/flutter/blob/54fa25543243e3bf31af6af0c1fef6adabc1d5c1/packages/flutter/lib/src/gestures/scale.dart#L730C5-L730C5).

fixes https://github.com/flutter/flutter/issues/135873. See also https://github.com/flutter/flutter/issues/43833 which added delta and https://github.com/flutter/flutter/issues/49025 which added `numPointers` to `ScaleUpdateDetails` for the reason given above. `sourceTimeStamp` should probably be added to `ScaleStartDetails` as well because it exists in `DragStartDetails` and therefore in `onPanStart`.

I am not sure how to add tests for this, any input about this PR would be appreciated.

- [] All existing and new tests are passing.
parent c864a556
......@@ -100,6 +100,7 @@ class ScaleStartDetails {
this.focalPoint = Offset.zero,
Offset? localFocalPoint,
this.pointerCount = 0,
this.sourceTimeStamp,
}) : localFocalPoint = localFocalPoint ?? focalPoint;
/// The initial focal point of the pointers in contact with the screen.
......@@ -129,6 +130,12 @@ class ScaleStartDetails {
/// recognizer.
final int pointerCount;
/// Recorded timestamp of the source pointer event that triggered the scale
/// event.
///
/// Could be null if triggered from proxied events such as accessibility.
final Duration? sourceTimeStamp;
@override
String toString() => 'ScaleStartDetails(focalPoint: $focalPoint, localFocalPoint: $localFocalPoint, pointersCount: $pointerCount)';
}
......@@ -148,6 +155,7 @@ class ScaleUpdateDetails {
this.rotation = 0.0,
this.pointerCount = 0,
this.focalPointDelta = Offset.zero,
this.sourceTimeStamp,
}) : assert(scale >= 0.0),
assert(horizontalScale >= 0.0),
assert(verticalScale >= 0.0),
......@@ -225,6 +233,12 @@ class ScaleUpdateDetails {
/// recognizer.
final int pointerCount;
/// Recorded timestamp of the source pointer event that triggered the scale
/// event.
///
/// Could be null if triggered from proxied events such as accessibility.
final Duration? sourceTimeStamp;
@override
String toString() => 'ScaleUpdateDetails('
'focalPoint: $focalPoint,'
......@@ -234,7 +248,8 @@ class ScaleUpdateDetails {
' verticalScale: $verticalScale,'
' rotation: $rotation,'
' pointerCount: $pointerCount,'
' focalPointDelta: $focalPointDelta)';
' focalPointDelta: $focalPointDelta,'
' sourceTimeStamp: $sourceTimeStamp)';
}
/// Details for [GestureScaleEndCallback].
......@@ -415,6 +430,7 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
final Map<int, _PointerPanZoomData> _pointerPanZooms = <int, _PointerPanZoomData>{};
double _initialPanZoomScaleFactor = 1;
double _initialPanZoomRotationFactor = 0;
Duration? _initialEventTimestamp;
double get _pointerScaleFactor => _initialSpan > 0.0 ? _currentSpan / _initialSpan : 1.0;
......@@ -475,6 +491,7 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
void addAllowedPointer(PointerDownEvent event) {
super.addAllowedPointer(event);
_velocityTrackers[event.pointer] = VelocityTracker.withKind(event.kind);
_initialEventTimestamp = event.timeStamp;
if (_state == _ScaleState.ready) {
_state = _ScaleState.possible;
_initialSpan = 0.0;
......@@ -494,6 +511,7 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
super.addAllowedPointerPanZoom(event);
startTrackingPointer(event.pointer, event.transform);
_velocityTrackers[event.pointer] = VelocityTracker.withKind(event.kind);
_initialEventTimestamp = event.timeStamp;
if (_state == _ScaleState.ready) {
_state = _ScaleState.possible;
_initialPanZoomScaleFactor = 1.0;
......@@ -690,6 +708,7 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
}
if (_state == _ScaleState.accepted && shouldStartIfAccepted) {
_initialEventTimestamp = event.timeStamp;
_state = _ScaleState.started;
_dispatchOnStartCallbackIfNeeded();
}
......@@ -707,6 +726,7 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
rotation: _computeRotationFactor(),
pointerCount: pointerCount,
focalPointDelta: _delta,
sourceTimeStamp: event.timeStamp
));
});
}
......@@ -721,9 +741,11 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
focalPoint: _currentFocalPoint!,
localFocalPoint: _localFocalPoint,
pointerCount: pointerCount,
sourceTimeStamp: _initialEventTimestamp,
));
});
}
_initialEventTimestamp = null;
}
@override
......
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