Skip to content

Commit

Permalink
add sourceTimeStamp to ScaleUpdateDetails (#135936)
Browse files Browse the repository at this point in the history
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 flutter/flutter#43833 (comment). 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 flutter/flutter#135873. See also flutter/flutter#43833 which added delta and flutter/flutter#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.
  • Loading branch information
yakagami authored Nov 29, 2023
1 parent c864a55 commit 443d861
Show file tree
Hide file tree
Showing 2 changed files with 315 additions and 1 deletion.
24 changes: 23 additions & 1 deletion packages/flutter/lib/src/gestures/scale.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)';
}
Expand All @@ -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),
Expand Down Expand Up @@ -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,'
Expand All @@ -234,7 +248,8 @@ class ScaleUpdateDetails {
' verticalScale: $verticalScale,'
' rotation: $rotation,'
' pointerCount: $pointerCount,'
' focalPointDelta: $focalPointDelta)';
' focalPointDelta: $focalPointDelta,'
' sourceTimeStamp: $sourceTimeStamp)';
}

/// Details for [GestureScaleEndCallback].
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -690,6 +708,7 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
}

if (_state == _ScaleState.accepted && shouldStartIfAccepted) {
_initialEventTimestamp = event.timeStamp;
_state = _ScaleState.started;
_dispatchOnStartCallbackIfNeeded();
}
Expand All @@ -707,6 +726,7 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
rotation: _computeRotationFactor(),
pointerCount: pointerCount,
focalPointDelta: _delta,
sourceTimeStamp: event.timeStamp
));
});
}
Expand All @@ -721,9 +741,11 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
focalPoint: _currentFocalPoint!,
localFocalPoint: _localFocalPoint,
pointerCount: pointerCount,
sourceTimeStamp: _initialEventTimestamp,
));
});
}
_initialEventTimestamp = null;
}

@override
Expand Down
Loading

0 comments on commit 443d861

Please sign in to comment.