You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-14 13:41:12 +00:00
Refactor mouse_entered and mouse_exited notifications
The previous implementation for signals mouse_entered and mouse_exited had shortcomings that relate to focused windows and pressed mouse buttons. For example a Control can be hovered by mouse, even if it is occluded by an embedded window. This patch changes the behavior, so that Control and Viewport send their mouse-enter/exit-notifications based solely on mouse position, visible area, and input restrictions and not on which window has focus or which mouse buttons are pressed. This implicitly also changes when the mouse_entered and mouse_exited signals are sent. This functionality can not be implemented as a part of Viewport::_gui_input_event, because of its interplay with Windows and because Viewport::_gui_input_event is based on input and not on visibility.
This commit is contained in:
@@ -677,16 +677,20 @@ void Window::_event_callback(DisplayServer::WindowEvent p_event) {
|
||||
switch (p_event) {
|
||||
case DisplayServer::WINDOW_EVENT_MOUSE_ENTER: {
|
||||
_propagate_window_notification(this, NOTIFICATION_WM_MOUSE_ENTER);
|
||||
emit_signal(SNAME("mouse_entered"));
|
||||
Window *root = get_tree()->get_root();
|
||||
DEV_ASSERT(!root->gui.windowmanager_window_over); // Entering a window while a window is hovered should never happen.
|
||||
root->gui.windowmanager_window_over = this;
|
||||
notification(NOTIFICATION_VP_MOUSE_ENTER);
|
||||
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CURSOR_SHAPE)) {
|
||||
DisplayServer::get_singleton()->cursor_set_shape(DisplayServer::CURSOR_ARROW); //restore cursor shape
|
||||
}
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EVENT_MOUSE_EXIT: {
|
||||
notification(NOTIFICATION_VP_MOUSE_EXIT);
|
||||
Window *root = get_tree()->get_root();
|
||||
DEV_ASSERT(root->gui.windowmanager_window_over); // Exiting a window, while no window is hovered should never happen.
|
||||
root->gui.windowmanager_window_over->_mouse_leave_viewport();
|
||||
root->gui.windowmanager_window_over = nullptr;
|
||||
_propagate_window_notification(this, NOTIFICATION_WM_MOUSE_EXIT);
|
||||
emit_signal(SNAME("mouse_exited"));
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EVENT_FOCUS_IN: {
|
||||
focused = true;
|
||||
@@ -1283,6 +1287,14 @@ void Window::_notification(int p_what) {
|
||||
|
||||
RS::get_singleton()->viewport_set_active(get_viewport_rid(), false);
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_VP_MOUSE_ENTER: {
|
||||
emit_signal(SceneStringNames::get_singleton()->mouse_entered);
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_VP_MOUSE_EXIT: {
|
||||
emit_signal(SceneStringNames::get_singleton()->mouse_exited);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2495,6 +2507,10 @@ bool Window::is_directly_attached_to_screen() const {
|
||||
return is_inside_tree();
|
||||
}
|
||||
|
||||
bool Window::is_attached_in_viewport() const {
|
||||
return get_embedder();
|
||||
}
|
||||
|
||||
void Window::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_title", "title"), &Window::set_title);
|
||||
ClassDB::bind_method(D_METHOD("get_title"), &Window::get_title);
|
||||
|
||||
Reference in New Issue
Block a user