godotengine / godotengine/godot

Mouse enter & exit signals trigger falsely when viewport is scaled (canvas_items mode) and mouse input is manually triggered

Open
#96,808 3 comments 0 reactions 0 assignees View on GitHub
documentation topic:2d topic:input
Dominant language
C++
Stars
117k
Forks
26.8k
PR merge metrics
PR metrics pending

Description

### Tested versions

- Reproducible in Godot 4.3 Mono.

### System information

Windows 11 - Godot Engine v4.3.stable.mono.official

### Issue description

This seems to have been fixed, but it may only have been for 2D? For a 3D project I had to use the manual position update when I move the camera to get mouse enter and exit to trigger: https://github.com/godotengine/godot/issues/69708

doing this I seem to get the same additional bug with 2D or 3D resulting from a few steps.
So, when calling something like this to manually update the mouse position:
```gdscript
var mouse_event = InputEventMouseMotion.new()
mouse_event.position = get_viewport().get_mouse_position()
Input.parse_input_event(mouse_event)
```
### Mouse Enter & Mouse Exit Signals will fire on an object at a different location to the mouse position if the viewport has been scaled and the stretch mode is set to canvas_items.

i.e. `get_viewport().get_mouse_position()` seems to be accurately produced, and you can draw things to the screen or make things follow to that mouse location and it works and produces the correct location and output, but somewhere in the processing of handling the simulated mouse input above, it will seemingly use a different or incorrect position value (maybe due to scale).

This causes other objects with mouse enter and exit signals to trigger when the mouse is not over them, or flickering to occur on the object you are mousing over.

I'm not sure if I'm doing something wrong, please let me know. Or in any case if there is a good workaround, please let me know.

### Steps to reproduce

1. Create a 2D scene
2. set Project Settings -> Display -> Window -> Stretch -> Mode to **canvas_items**
3. create a 2D node and give it these functions
```gdscript
extends Node2D

var mousePos = Vector2.ZERO;

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
var mouse_event = InputEventMouseMotion.new()
mouse_event.position = get_viewport().get_mouse_position()
Input.parse_input_event(mouse_event)

mousePos = mouse_event.position
print(mousePos)
queue_redraw()
pass

func _draw():
draw_circle(mousePos,20.0,Color.ANTIQUE_WHITE)
pass
```
4. Create a staticbody2D, with a sprite and a collision shape
5. give the static body a script with these functions
```gdscript
extends StaticBody2D

@onready var sprite = $Sprite2D

func _on_mouse_entered() -> void:
print("hit")
sprite.modulate = Color.BROWN
pass # Replace with function body.

func _on_mouse_exited() -> void:
sprite.modulate = Color.WHITE
pass # Replace with function body.
```
6. Run the game
7. Observe the proper behavior (do not scale the viewport yet)
8. Scale the viewport any way you'd like
9. Observe flickering and false positives.

https://github.com/user-attachments/assets/14fccba0-d70b-475d-9e46-5899931a7f77

### Minimal reproduction project (MRP)

[ScalingMouseEnter_MRP.zip](https://github.com/user-attachments/files/16948759/ScalingMouseEnter_MRP.zip)

Contributor guide

Open the contributing guide

Research direction

Reproduce the issue with the linked ScalingMouseEnter_MRP.zip using canvas_items scaling and the Input.parse_input_event mouse-motion sequence. Trace the viewport mouse-position and mouse enter/exit processing from that entry point, then verify that scaled viewports no longer produce false signals or flickering in the provided reproduction.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
game-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.