Repository: flutter
Issue: globalDelta support for DragUpdateDetails
Labels: framework,f: gestures,c: proposal,P3,team-framework,triaged-framework

## Use case

If I want to retrieve the correct **global delta** in e.g. [`onPanUpdate`](https://api.flutter.dev/flutter/widgets/GestureDetector/onPanUpdate.html), there are currently only two ways of doing so I am aware of:

1. Reverse whatever transformation was applied to the widget that receives the drag gestures. This **assumes** you actually know it. In this example, we rotate on the z-axis, translate on the x-axis and y-axis, and scale on the x-axis and y-axis. The code for figuring out the **global delta** I came up with looks like this (note that for this you also need a tiny bit of matrix transformation knowledge):

```dart
onPanUpdate: (details) {
  final inverseReverseTransform = Matrix4.identity()
    ..translate(childWidth / 2 - translationX, childHeight / 2 - translationY)
    ..rotateZ(-rotationAngle)
    ..scale(1 / scaleX, 1 / scaleY)
    ..translate(
        -childWidth / 2 + translationX, -childHeight / 2 + translationY)
    ..invert();
  final transformedBefore = inverseReverseTransform.transform3(Vector3(
    details.localPosition.dx - details.delta.dx,
    details.localPosition.dy - details.delta.dy,
    0,
  ));
  final transformedAfter = inverseReverseTransform.transform3(Vector3(
    details.localPosition.dx,
    details.localPosition.dy,
    0,
  ));
  // Now, we have the global delta.
  final globalDelta = transformedAfter - transformedBefore;
},
```

2. The other option is more trivial from a "maths standpoint" but way more complex from an implementation standpoint because it requires maintaining state. We can simply use the [`DragStartDetails.globalPosition`](https://api.flutter.dev/flutter/gestures/DragStartDetails/globalPosition.html) to subtract it from the [`DragUpdateDetails.globalPosition`](https://api.flutter.dev/flutter/gestures/DragUpdateDetails-class.html) and we arrive at the same `globalDelta` as before. This is because the `globalPosition` already contains the delta without the transformation - it is just not exposed in a way.

## Proposal

Extend the [`DragUpdateDetails.localPosition`](https://api.flutter.dev/flutter/gestures/DragUpdateDetails/localPosition.html) vs [`DragUpdateDetails.globalPosition`](https://api.flutter.dev/flutter/gestures/DragUpdateDetails/globalPosition.html) concept to also include a proposed:

* `DragUpdateDetails.localDelta`, which is the same as the current [`DragUpdateDetails.delta`](https://api.flutter.dev/flutter/gestures/DragUpdateDetails/delta.html).
* `DragUpdateDetails.globalDelta`, which is the delta of the drag start global position compared to the drag update global position.

### Context

If you are having a difficult time understanding what is going on in my example, this is the widget tree I have in mind:

```
Transform(
  transform: transform, // Our transform matrix that applies the translation, rotation, and scale.
  child: GestureDetector(
    onPanUpdate: (details) {
      // Our onPanUpdate callback that receives the **transformed** hit tests.
      // The delta we get here cannot be used to alter the transform e.g. because
      // we first need to reverse the transform in order to get the correct delta.
    }.
  ),
)
```