Skip to content

Commit

Permalink
Send mouse-enter notification, when viewport receives a mouse motion …
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
Sauermann committed Apr 9, 2024
1 parent a7b8602 commit 3e14688
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 2 deletions.
7 changes: 7 additions & 0 deletions scene/main/viewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,7 @@ void Viewport::_notification(int p_what) {

case NOTIFICATION_VP_MOUSE_EXIT: {
gui.mouse_in_viewport = false;
gui.drag_mouse_over = nullptr;
_drop_physics_mouseover();
// When the mouse exits the viewport, we don't want to end
// mouse_focus, because, for example, we want to continue
Expand Down Expand Up @@ -2967,6 +2968,12 @@ void Viewport::_update_mouse_over() {
return;
}

if (!gui.mouse_in_viewport) {
// This is a hack, that makes pushing mouse motion events to SubViewports more user-friendly.
// Without this, a user needs to take care of sending mouse-enter/exit notifications to SubViewports.
notification(NOTIFICATION_VP_MOUSE_ENTER);
}

if (get_tree()->get_root()->is_embedding_subwindows() || is_sub_viewport()) {
// Use embedder logic for calculating mouse position.
_update_mouse_over(gui.last_mouse_pos);
Expand Down
9 changes: 8 additions & 1 deletion tests/display_server_mock.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,22 @@ class DisplayServerMock : public DisplayServerHeadless {
void simulate_event(Ref<InputEvent> p_event) {
Ref<InputEvent> event = p_event;
Ref<InputEventMouse> me = p_event;
bool parse_event = true;
if (me.is_valid()) {
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) {
mm->set_relative(mm->get_position() - mouse_position);
event = mm;
}
_set_mouse_position(me->get_position());
if (mm.is_valid() && !window_over) {
parse_event = false;
}
}

if (parse_event) {
Input::get_singleton()->parse_input_event(event);
}
Input::get_singleton()->parse_input_event(event);
}

// Returns the current cursor shape.
Expand Down
1 change: 0 additions & 1 deletion tests/scene/test_viewport.h
Original file line number Diff line number Diff line change
Expand Up @@ -1192,7 +1192,6 @@ TEST_CASE("[SceneTree][Viewport] Controls and InputEvent handling") {

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

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

0 comments on commit 3e14688

Please sign in to comment.