diff --git a/editor/gui/editor_title_bar.cpp b/editor/gui/editor_title_bar.cpp index c251c70c6de9..ba406e6704b1 100644 --- a/editor/gui/editor_title_bar.cpp +++ b/editor/gui/editor_title_bar.cpp @@ -40,7 +40,7 @@ void EditorTitleBar::gui_input(const Ref &p_event) { if (mm->get_button_mask().has_flag(MouseButtonMask::LEFT)) { Window *w = Object::cast_to(get_viewport()); if (w) { - Point2 mouse = DisplayServer::get_singleton()->mouse_get_position(); + Point2 mouse = get_viewport()->get_embedder_mouse_position(); w->set_position(mouse - click_pos); } } else { @@ -54,7 +54,7 @@ void EditorTitleBar::gui_input(const Ref &p_event) { if (w) { if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { - click_pos = DisplayServer::get_singleton()->mouse_get_position() - w->get_position(); + click_pos = get_viewport()->get_embedder_mouse_position() - w->get_position(); moving = true; } else { moving = false; diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 9d245959169c..7012799a47ee 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -122,6 +122,7 @@ void ColorPicker::_notification(int p_what) { if (!is_picking_color) { return; } + // This is only executed if previously is was checked, that the DisplayServer supports these functions. set_pick_color(DisplayServer::get_singleton()->screen_get_pixel(DisplayServer::get_singleton()->mouse_get_position())); } } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index dc586e86c931..436352fb41de 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -398,20 +398,8 @@ void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) { void PopupMenu::_parent_focused() { if (is_embedded()) { - Point2 mouse_pos_adjusted; - Window *window_parent = Object::cast_to(get_parent()->get_viewport()); - while (window_parent) { - if (!window_parent->is_embedded()) { - mouse_pos_adjusted += window_parent->get_position(); - break; - } - - window_parent = Object::cast_to(window_parent->get_parent()->get_viewport()); - } - Rect2 safe_area = get_embedder()->subwindow_get_popup_safe_rect(this); - Point2 pos = DisplayServer::get_singleton()->mouse_get_position() - mouse_pos_adjusted; - if (safe_area == Rect2i() || !safe_area.has_point(pos)) { + if (safe_area == Rect2i() || !safe_area.has_point(get_embedder_mouse_position())) { Popup::_parent_focused(); } else { grab_focus(); @@ -1127,7 +1115,7 @@ void PopupMenu::_notification(int p_what) { // Only used when using operating system windows. if (!activated_by_keyboard && !is_embedded() && autohide_areas.size()) { - Point2 mouse_pos = DisplayServer::get_singleton()->mouse_get_position(); + Point2 mouse_pos = get_embedder_mouse_position(); mouse_pos -= get_position(); for (const Rect2 &E : autohide_areas) { diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 5999b85988e3..ce8706683133 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1398,10 +1398,41 @@ Vector2 Viewport::get_mouse_position() const { return xform.affine_inverse().xform(DisplayServer::get_singleton()->mouse_get_position()); } else { // Fallback to Input for getting mouse position in case of emulated mouse. + // Reports wrong coordinates, when used in an unfocused native Window. return get_screen_transform_internal().affine_inverse().xform(Input::get_singleton()->get_mouse_position()); } } +Vector2 Viewport::get_embedder_mouse_position() const { + // Return the mouse position in the coordinate system of the Viewport, where this is embedded. + // If this is a non-embedded Window, return the mouse position of the DisplayServer, if it supports it. + ERR_READ_THREAD_GUARD_V(Vector2()); + + const Window *w = Object::cast_to(this); + if (w) { + Viewport *e = w->get_embedder(); + if (e) { + return e->get_mouse_position(); + } + // Viewport is a native Window. + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_MOUSE)) { + return DisplayServer::get_singleton()->mouse_get_position(); + } + // Fallback to Input for getting mouse position in case of emulated mouse. + // Reports wrong coordinates, when used in an unfocused native Window. + return Input::get_singleton()->get_mouse_position(); + } + + // This is a SubViewport. + Window *b = get_base_window(); + if (b) { + return b->get_embedder_mouse_position(); + } + + // Case that SubViewport is not directly attached to screen. + return gui.last_mouse_pos; +} + void Viewport::warp_mouse(const Vector2 &p_position) { ERR_MAIN_THREAD_GUARD; Transform2D xform = get_screen_transform_internal(); @@ -2556,6 +2587,10 @@ Window *Viewport::get_base_window() const { Viewport *v = const_cast(this); Window *w = Object::cast_to(v); while (!w) { + if (!Object::cast_to(v->get_parent())) { + // In this case there is no meaningful Window to return. + return nullptr; + } v = v->get_parent_viewport(); w = Object::cast_to(v); } diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 43a89c8a0b1b..4eb2fb8ea907 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -595,6 +595,7 @@ class Viewport : public Node { bool is_input_disabled() const; Vector2 get_mouse_position() const; + Vector2 get_embedder_mouse_position() const; void warp_mouse(const Vector2 &p_position); virtual void update_mouse_cursor_state();