Warping mouse position adds some weird offset.

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By navett52

I have a character that the player controls. This character has a little friend that follows them around, but can be controlled by the player using the mouse. When the player presses a button I want the friend to detach and start following the mouse. To accomplish this I want to warp the mouse to the location of the friend, then allow the friend to start being moved around by the mouse.

Instead, when I hit the button to release the friend, the mouse warp warps the mouse by some seemingly constant offset to the left and up of where it should be by a wide margin and I can’t figure out why.

func _process(delta):
if (Input.is_action_just_pressed("release_buddi")):
	Input.warp_mouse_position(self.position)
    # anchored is whether or not the friend should follow the player
	anchored = false

if (anchored):
	self.position = Vector2(filip.position.x, filip.position.y - 50)
else:
	self.position = Vector2(get_global_mouse_position().x, get_global_mouse_position().y)
:bust_in_silhouette: Reply From: navett52

Digging into the code of the engine for the Linux visual server it utilizes the XWarpPointer function of XLib. The documentation for that method states:

If dest_w is a window, XWarpPointer() moves the pointer to the offsets (dest_x, dest_y) relative to the origin of dest_w.

In the engine code dest_w is set to the open window, and the origin is the top left of the window, so the GDScript function Input.warp_mouse_position(to: Vector2) uses the Vector2 passed as an offset from the window origin, which is the top left of the window.

The fix was to pass self.get_global_transform_with_canvas().origin to Input.warp_mouse_position() instead of self.position or self.global_position because that gets the node’s position relative to the origin of the viewport (aka window) and will set the mouse position appropriately.