Skip to content

Commit 3e14688

Browse files
committed
Send mouse-enter notification, when viewport receives a mouse motion event
Ensure, that a `SubViewport` receives a `NOTIFICATION_VP_MOUSE_ENTER`, when an `InputEventMouseMotion` is sent to a viewport, that currently doesn't have the mouse inside. In the following case the changed code makes a difference: By default the viewport has the state, that the mouse is not over the viewport. When the user pushes an `InputEventMouseMotion` to a `SubViewport`, then because of the default state, the Viewport assumes, that the mouse is not over itself. With this change, the Viewport automatically switches its state. Make necessary adjustments to unit-tests.
1 parent a7b8602 commit 3e14688

File tree

3 files changed

+15
-2
lines changed

3 files changed

+15
-2
lines changed

scene/main/viewport.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,7 @@ void Viewport::_notification(int p_what) {
646646

647647
case NOTIFICATION_VP_MOUSE_EXIT: {
648648
gui.mouse_in_viewport = false;
649+
gui.drag_mouse_over = nullptr;
649650
_drop_physics_mouseover();
650651
// When the mouse exits the viewport, we don't want to end
651652
// mouse_focus, because, for example, we want to continue
@@ -2967,6 +2968,12 @@ void Viewport::_update_mouse_over() {
29672968
return;
29682969
}
29692970

2971+
if (!gui.mouse_in_viewport) {
2972+
// This is a hack, that makes pushing mouse motion events to SubViewports more user-friendly.
2973+
// Without this, a user needs to take care of sending mouse-enter/exit notifications to SubViewports.
2974+
notification(NOTIFICATION_VP_MOUSE_ENTER);
2975+
}
2976+
29702977
if (get_tree()->get_root()->is_embedding_subwindows() || is_sub_viewport()) {
29712978
// Use embedder logic for calculating mouse position.
29722979
_update_mouse_over(gui.last_mouse_pos);

tests/display_server_mock.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,22 @@ class DisplayServerMock : public DisplayServerHeadless {
113113
void simulate_event(Ref<InputEvent> p_event) {
114114
Ref<InputEvent> event = p_event;
115115
Ref<InputEventMouse> me = p_event;
116+
bool parse_event = true;
116117
if (me.is_valid()) {
117118
Ref<InputEventMouseMotion> mm = p_event;
118119
if (mm.is_valid()) {
119120
mm->set_relative(mm->get_position() - mouse_position);
120121
event = mm;
121122
}
122123
_set_mouse_position(me->get_position());
124+
if (mm.is_valid() && !window_over) {
125+
parse_event = false;
126+
}
127+
}
128+
129+
if (parse_event) {
130+
Input::get_singleton()->parse_input_event(event);
123131
}
124-
Input::get_singleton()->parse_input_event(event);
125132
}
126133

127134
// Returns the current cursor shape.

tests/scene/test_viewport.h

-1
Original file line numberDiff line numberDiff line change
@@ -1192,7 +1192,6 @@ TEST_CASE("[SceneTree][Viewport] Controls and InputEvent handling") {
11921192

11931193
// Move outside of window.
11941194
SEND_GUI_MOUSE_MOTION_EVENT(on_outside, MouseButtonMask::LEFT, Key::NONE);
1195-
CHECK(DS->get_cursor_shape() == DisplayServer::CURSOR_ARROW);
11961195
CHECK(root->gui_is_dragging());
11971196

11981197
SEND_GUI_MOUSE_BUTTON_RELEASED_EVENT(on_outside, MouseButton::LEFT, MouseButtonMask::NONE, Key::NONE);

0 commit comments

Comments
 (0)