Repository: godot
Issue: InputEventPanGesture different delta on different screens
Labels: bug,topic:input

### Godot version

v4.2.beta2.mono.official [f8818f85e]

### System information

Godot v4.2.beta2.mono - Windows 10.0.22621 - Vulkan (Mobile) - dedicated NVIDIA GeForce RTX 2070 with Max-Q Design (NVIDIA; 31.0.15.2206) - Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz (12 Threads) - Galaxy S21 Ultra

### Issue description

**TLDR: InputEventPanGesture delta field is wrong, the fix might be one line of code**

The event `InputEventPanGesture` contains a delta field that does not take into account screen changes (different DPI etc.)
Thus using `InputEventPanGesture` on different devices is most likely to cause relative offsetting to the amount of panning (or any use of the delta field in user code)

Given the following code on a 2D node:
```
if (@event is InputEventPanGesture panEvent)
{
    float correctionFactor = ***
    Vector2 correctedDelta = panEvent.Delta * correctionFactor;
    affected.GlobalPosition -= correctedDelta;
}
```
On my case using a desktop with DPI 120, screen size (1920, 1080), screen scale 1, I had to set `correctionFactor` to 0.5f for the node to follow the mouse perfectly
On my phone (Galaxy 21 ultra) with DPI 450, screen size (1080, 2280), screen scale 1.35, I had to set `correctionFactor` to `DisplayServer.ScreenGetScale() * 2` (`2.7f`) for the same "pixel perfect" behavior where the node follows the touch position perfectly. I think this magic number depends also on screen orientation.

.
.
.

### **Possible steps for resolution**

I think this is most likely coming from [these lines](https://github.com/godotengine/godot/blob/f71f4b80e32f6e98a4cd3cb1c06071223297e8fc/core/input/input_event.cpp#L1633) in [godot](https://github.com/godotengine/godot/tree/f71f4b80e32f6e98a4cd3cb1c06071223297e8fc)/[core](https://github.com/godotengine/godot/tree/f71f4b80e32f6e98a4cd3cb1c06071223297e8fc/core)/[input](https://github.com/godotengine/godot/tree/f71f4b80e32f6e98a4cd3cb1c06071223297e8fc/core/input)
/[input_event.cpp](https://github.com/godotengine/godot/blob/f71f4b80e32f6e98a4cd3cb1c06071223297e8fc/core/input/input_event.cpp#L1633):
```
Ref<InputEvent> InputEventPanGesture::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
        ...
	ev->set_delta(get_delta());
        ...
}
```
Where we can see the delta is returned without running `p_xform.basis_xform` on it, thus staying "relative"
If we look at another touch event containing a delta field like `InputEventScreenDrag.Relative`:
```
Ref<InputEvent> InputEventScreenDrag::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
        ...
	sd->set_position(p_xform.xform(pos + p_local_ofs));
	sd->set_relative(p_xform.basis_xform(relative));
	sd->set_velocity(p_xform.basis_xform(velocity));
	...
}
```
We can see that before setting the relative field, the function `p_xform.basis_xform` is run on it: 
```sd->set_relative(p_xform.basis_xform(relative));``` 
While the pan gesture delta stays as:
```ev->set_delta(get_delta());``` 
Making this possibly just a one line fix.

I would like to do it myself but I do not have prior experience in compiling Godot, or a working environment, so considering the size of the change it would take me heaps of time more than an active contributor to this (amazing) project

### Steps to reproduce

1) Create a new mobile renderer project.
2) In project setting enable the setting
input_devices/pointing/android/enable_pan_and_scale_gestures
3) Add a Node2D and add sample code that uses the PanGesture to move its parent Node2D:
```
using Godot;
using System;
using System.Collections.Generic;

public partial class GestureController : Node
{
	private Node2D affected;
	public override void _Ready()
	{
		affected = GetParent<Node2D>();
	}

	public override void _Input(InputEvent @event)
	{
	        if (@event is InputEventPanGesture panEvent)
	        {
		        float correctionFactor = DisplayServer.ScreenGetScale() * 2;  // this setting looks like it works for Galaxy s21u with 1.35 screen scale 420 dpi, for desktop probably 0.5f would work
		        Vector2 correctedDelta = panEvent.Delta * correctionFactor;
		        affected.GlobalPosition -= correctedDelta;
	        }
	}
}
```
4) Try to build the project for your desktop and for your mobile phone (or any other screen you have that has high DPI or different resolution)

**Result:** you will quickly see the node2D gaining an offset the more you "pan" it if you didn't put the right `correctionFactor` for your screen.

### Minimal reproduction project

[tryBuildAndroid reproduction.zip](https://github.com/godotengine/godot/files/13061500/tryBuildAndroid.reproduction.zip)
The provided project contains an android export, and code that fakes InputEventPanGesture when pressing ctrl while clicking and moving the mouse.
Please do not take this as an example of my coding cleanliness, it is a quick reproduction :D
I'm aware my calculation for faking it on desktop can be wrong, but it doesn't change the fact that `InputEventPanGesture.Drag` is not calculated correctly on mobile devices with real gestures.