From b9634e7c68d9d672ca174f66b9dba23960cb1f4a Mon Sep 17 00:00:00 2001 From: Mikael Hermansson Date: Thu, 23 Apr 2026 11:38:00 +0200 Subject: [PATCH] Fix `PopupMenu` input handling when scaled/padded --- scene/gui/popup_menu.cpp | 25 ++++++++++--------------- scene/gui/popup_menu.h | 3 +-- scene/main/viewport.cpp | 8 +------- 3 files changed, 12 insertions(+), 24 deletions(-) diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 9546607a43..721c73f840 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -1195,7 +1195,7 @@ void PopupMenu::_close_or_suspend() { if (this_submenu_index != -1) { // Is a submenu. PopupMenu *parent_popup = Object::cast_to(get_parent()); ERR_FAIL_NULL(parent_popup); - Point2 mouse_pos = is_embedded() ? parent_popup->get_mouse_position() : Point2(DisplayServer::get_singleton()->mouse_get_position() - parent_popup->get_position()); + Point2 mouse_pos = is_embedded() ? parent_popup->get_mouse_position() * parent_popup->get_content_scale_factor() : Point2(DisplayServer::get_singleton()->mouse_get_position() - parent_popup->get_position()); if (parent_popup->_get_mouse_over(mouse_pos) == this_submenu_index) { parent_popup->submenu_mouse_exited_ticks_msec = -1; parent_popup->mouse_movement_was_tested = false; @@ -2446,7 +2446,7 @@ void PopupMenu::_submenu_hidden() { queue_accessibility_update(); control->queue_redraw(); if (!activated_by_keyboard) { - Point2 mouse_pos = is_embedded() ? get_mouse_position() : Point2(DisplayServer::get_singleton()->mouse_get_position() - get_position()); + Point2 mouse_pos = is_embedded() ? get_mouse_position() * get_content_scale_factor() : Point2(DisplayServer::get_singleton()->mouse_get_position() - get_position()); _mouse_over_update(mouse_pos); } } @@ -3271,19 +3271,6 @@ bool PopupMenu::get_allow_search() const { return allow_search; } -String PopupMenu::get_tooltip(const Point2 &p_pos) const { - Point2 pos = p_pos; - // Adjust for the top style margin and search bar. - pos.y += scroll_container->get_global_position().y; - - int over = _get_mouse_over(pos); - if (over < 0 || over >= items.size()) { - return ""; - } - - return items[over].tooltip; -} - void PopupMenu::set_search_bar_enabled(bool p_enabled) { search_bar_enabled = p_enabled; _update_search_bar_visibility(); @@ -3837,3 +3824,11 @@ PopupMenu::PopupMenu() { PopupMenu::~PopupMenu() { unbind_global_menu(); } + +String PopupMenuItems::get_tooltip(const Point2 &p_pos) const { + int over = popup->_get_mouse_over(get_global_transform_with_canvas().xform(p_pos) * popup->get_content_scale_factor()); + if (over < 0 || over >= popup->items.size()) { + return ""; + } + return popup->items[over].tooltip; +} diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index 6a961858ec..ee9f490501 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -423,8 +423,6 @@ public: void clear(bool p_free_submenus = true); - virtual String get_tooltip(const Point2 &p_pos) const; - #ifdef TOOLS_ENABLED PackedStringArray get_configuration_warnings() const override; #endif @@ -469,4 +467,5 @@ public: virtual RID get_focused_accessibility_element() const override; virtual void gui_input(const Ref &p_event) override; + virtual String get_tooltip(const Point2 &p_pos) const override; }; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 9f424a59a5..0d46a199a7 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -44,7 +44,6 @@ STATIC_ASSERT_INCOMPLETE_TYPE(class, RenderingServer); #include "scene/gui/control.h" #include "scene/gui/label.h" #include "scene/gui/popup.h" -#include "scene/gui/popup_menu.h" #include "scene/gui/subviewport_container.h" #include "scene/main/canvas_layer.h" #include "scene/main/scene_tree.h" @@ -1567,14 +1566,9 @@ void Viewport::_gui_cancel_tooltip() { String Viewport::_gui_get_tooltip(Control *p_control, const Vector2 &p_pos, Control **r_tooltip_owner) { Vector2 pos = p_pos; String tooltip; - PopupMenu *menu = Object::cast_to(this); while (p_control) { - if (menu) { - tooltip = menu->get_tooltip(pos); - } else { - tooltip = p_control->get_tooltip(pos); - } + tooltip = p_control->get_tooltip(pos); if (r_tooltip_owner) { *r_tooltip_owner = p_control;