Description
Godot version
master, 4.2 dev3+, since 1c3c17
System information
Windows 10
Issue description
#81909 is caused by the same root cause, #67791
#82182 does not solve the issues.
Mouse enter and exit are not in sync with _gui_input InputEventMouseButton and other mouse events.
This leads to issues where a button can be clicked on without being hovered:
InputEventMouseMotion should be called only between mouse enter and exit events, currently this is not the case.
The existing mouse events (InputEventMouse*) are fine and work as expected, the mouse enter and exit signals need to match it.
Mouse enter and exit do not respect MOUSE_FILTER_PASS
.
Only MOUSE_FILTER_IGNORE
and MOUSE_FILTER_STOP
are respected. This means there is not a good way to get the event in a parent while the child needs mouse events.
Workarounds include:
- Manually set all child Controls to
MOUSE_FILTER_IGNORE
. This does not scale and doesn't work if the children also need mouse input. (Doesn'tMOUSE_FILTER_PASS
exist for this reason?) - Manually track the proper state by listening to InputEventMouseMotion. This can tell you when the mouse has entered, but not exited.
- Continuously check
Rect2.has_point()
. This is only axis-aligned and doesn't include children.
These workarounds are cumbersome and not performant.
All Nodes that use NOTIFICATION_MOUSE_ENTER
like BaseButton
would also need to do be changed.
The current implementation of mouse enter and exit is useful in its own way, but should not be the default used for most events.
No other UI system I could find does mouse enter and exit events like this.
For the ones that provide multiple ways, this way isn't the default.
- Unity has both mouse enter/leave and mouse over/out
- HTML has both onmouseenter/onmouseleave (doesn't bubble up, excludes overlaps, includes children) and onmouseover/onmouseout (bubbles up, excludes overlaps, includes children)
- Windows has both IsMouseOver (includes child elements) and IsMouseDirectlyOver (does not)
- Phaser and has a toponly input flag to ignore overlaps
- Haxeflixel has mouseChildren flag that allows children to receive mouse events
- Gamemaker does bounding box test, no overlaps
Proposed Solution
Change the current mouse_enter
and mouse_exited
signals to mouse_over
and mouse_out
. Add a NOTIFICATION_MOUSE_OVER
and NOTIFICATION_MOUSE_OUT
for it.
mouse_entered
signal: Emitted when the mouse enters the control's Rect area or any of its descendants, provided its mouse_filter lets the event reach it.
mouse_exited
signal: Emitted when the mouse exits the control's Rect area and all of its descendants, provided its mouse_filter lets the event reach it.
The signals should not propagate up if the parent already received that signal.
Implementation details for this:
- The mouse entered signal would propagate up until the last gui.mouse_over,
- The mouse exited signal would propagate up until where the new gui.mouse_over is a parent of the old gui.mouse_over.
- otherwise they do propagate like the mouse events do.
This ensures that a Control first receives mouse_enter
then mouse move events then mouse_exit
.
Steps to reproduce
Add a button
Add a visible control to it with MOUSE_FILTER_PASS
set, like an image.
Hover over the button and the image.
The button does not get hovered, even though it will accept a mouse click.
Minimal reproduction project
N/A
Metadata
Metadata
Assignees
Type
Projects
Status
No status
Activity
mouse_entered
andmouse_exited
signals #67791TheKassaK commentedon Oct 12, 2023
Any news ? I see 4.2 beta is out but theses signals are broken and unusable now since the rework
1 remaining item