From 64277e610161415f4291b522ed411b9e235ce8dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Tue, 30 Dec 2025 08:33:41 +0200 Subject: [PATCH] Make PopupMenu shrinking configurable. --- doc/classes/PopupMenu.xml | 6 ++++++ scene/gui/option_button.cpp | 1 + scene/gui/popup_menu.cpp | 26 +++++++++++++++++++++++++- scene/gui/popup_menu.h | 9 +++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml index 80c4b48f9f..036e45da39 100644 --- a/doc/classes/PopupMenu.xml +++ b/doc/classes/PopupMenu.xml @@ -660,6 +660,12 @@ If [code]true[/code], [MenuBar] will use native menu when supported. [b]Note:[/b] If [PopupMenu] is linked to [StatusIndicator], [MenuBar], or another [PopupMenu] item it can use native menu regardless of this property, use [method is_native_menu] to check it. + + If [code]true[/code], shrinks [PopupMenu] to minimum height when it's shown. + + + If [code]true[/code], shrinks [PopupMenu] to minimum width when it's shown. + Sets the delay time in seconds for the submenu item to popup on mouse hovering. If the popup menu is added as a child of another (acting as a submenu), it will inherit the delay time of the parent menu item. [b]Note:[/b] If the mouse is exiting a submenu item with an open submenu and enters a different submenu item, the submenu popup delay time is affected by the direction of the mouse movement toward the open submenu. If the mouse is moving toward the submenu, the open submenu will wait approximately [code]0.5[/code] seconds before closing, which then allows the hovered submenu item to open. This additional delay allows the mouse time to move to the open submenu across other menu items without prematurely closing. If the mouse is not moving toward the open submenu, for example in a downward direction, the open submenu will close immediately. diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index e8071584cb..fa2f561493 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -547,6 +547,7 @@ void OptionButton::show_popup() { rect = xform.xform(rect); } rect.size.height = 0; + popup->set_shrink_width(false); popup->popup(rect); } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index e1e939c23d..2ddbb11b85 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -3250,6 +3250,12 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("set_system_menu", "system_menu_id"), &PopupMenu::set_system_menu); ClassDB::bind_method(D_METHOD("get_system_menu"), &PopupMenu::get_system_menu); + ClassDB::bind_method(D_METHOD("set_shrink_height", "shrink"), &PopupMenu::set_shrink_height); + ClassDB::bind_method(D_METHOD("get_shrink_height"), &PopupMenu::get_shrink_height); + + ClassDB::bind_method(D_METHOD("set_shrink_width", "shrink"), &PopupMenu::set_shrink_width); + ClassDB::bind_method(D_METHOD("get_shrink_width"), &PopupMenu::get_shrink_width); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_item_selection"), "set_hide_on_item_selection", "is_hide_on_item_selection"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_checkable_item_selection"), "set_hide_on_checkable_item_selection", "is_hide_on_checkable_item_selection"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_on_state_item_selection"), "set_hide_on_state_item_selection", "is_hide_on_state_item_selection"); @@ -3257,6 +3263,8 @@ void PopupMenu::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_search"), "set_allow_search", "get_allow_search"); ADD_PROPERTY(PropertyInfo(Variant::INT, "system_menu_id", PROPERTY_HINT_ENUM, "None:0,Application Menu:2,Window Menu:3,Help Menu:4,Dock:5"), "set_system_menu", "get_system_menu"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "prefer_native_menu"), "set_prefer_native_menu", "is_prefer_native_menu"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shrink_height"), "set_shrink_height", "get_shrink_height"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shrink_width"), "set_shrink_width", "get_shrink_width"); ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "item_"); @@ -3376,6 +3384,21 @@ void PopupMenu::_popup_base(const Rect2i &p_bounds) { Popup::_popup_base(p_bounds); } } +void PopupMenu::set_shrink_height(bool p_shrink) { + shrink_height = p_shrink; +} + +bool PopupMenu::get_shrink_height() const { + return shrink_height; +} + +void PopupMenu::set_shrink_width(bool p_shrink) { + shrink_width = p_shrink; +} + +bool PopupMenu::get_shrink_width() const { + return shrink_width; +} void PopupMenu::_pre_popup() { real_t popup_scale = 1.0; @@ -3413,7 +3436,8 @@ void PopupMenu::_pre_popup() { } minsize.height = Math::ceil(minsize.height); // Ensures enough height at fractional content scales to prevent the v_scroll_bar from showing. set_min_size(minsize); // `height` is truncated here by the cast to Size2i for Window.min_size. - reset_size(); // Shrinkwraps to min size. + Size2i sz = get_size(); // Shrinkwraps to min size. + set_size(Vector2i(shrink_width ? 0 : sz.x, shrink_height ? 0 : sz.y)); } } diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index aff377b4a5..a600310ce4 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -241,6 +241,9 @@ class PopupMenu : public Popup { String _atr(int p_idx, const String &p_text) const; void _submenu_hidden(); + bool shrink_height = true; + bool shrink_width = true; + protected: virtual void _pre_popup() override; virtual Rect2i _popup_adjust_rect() const override; @@ -409,6 +412,12 @@ public: void set_allow_search(bool p_allow); bool get_allow_search() const; + void set_shrink_height(bool p_shrink); + bool get_shrink_height() const; + + void set_shrink_width(bool p_shrink); + bool get_shrink_width() const; + virtual void set_visible(bool p_visible) override; PopupMenu();