From ec11acd2e8d34a59546eb505a8d83f3502ebcf48 Mon Sep 17 00:00:00 2001
From: Giganzo <158825920+Giganzo@users.noreply.github.com>
Date: Sun, 15 Mar 2026 13:30:28 +0100
Subject: [PATCH] Fix PopupMenu sizing with search bar
---
doc/classes/PopupMenu.xml | 3 +++
editor/themes/theme_classic.cpp | 1 +
editor/themes/theme_modern.cpp | 1 +
scene/gui/popup_menu.cpp | 18 ++++++++++++++----
scene/gui/popup_menu.h | 1 +
scene/theme/default_theme.cpp | 1 +
6 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index c2842dfbbb..fd5a5d7503 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -767,6 +767,9 @@
The size of the item text outline.
[b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended.
+
+ The vertical space between search bar and menu items.
+
The size of the labeled separator text outline.
diff --git a/editor/themes/theme_classic.cpp b/editor/themes/theme_classic.cpp
index e5dfe07549..03e06c5109 100644
--- a/editor/themes/theme_classic.cpp
+++ b/editor/themes/theme_classic.cpp
@@ -1130,6 +1130,7 @@ void ThemeClassic::populate_standard_styles(const Ref &p_theme, Edi
int v_sep = (p_config.enable_touch_optimizations ? 12 : p_config.forced_even_separation) * EDSCALE;
p_theme->set_constant("v_separation", "PopupMenu", v_sep);
+ p_theme->set_constant("search_bar_separation", "PopupMenu", v_sep);
p_theme->set_constant("outline_size", "PopupMenu", 0);
p_theme->set_constant("item_start_padding", "PopupMenu", p_config.separation_margin);
p_theme->set_constant("item_end_padding", "PopupMenu", p_config.separation_margin);
diff --git a/editor/themes/theme_modern.cpp b/editor/themes/theme_modern.cpp
index 3325a0e1f0..7eec575034 100644
--- a/editor/themes/theme_modern.cpp
+++ b/editor/themes/theme_modern.cpp
@@ -1106,6 +1106,7 @@ void ThemeModern::populate_standard_styles(const Ref &p_theme, Edit
p_theme->set_constant("h_separation", "PopupMenu", p_config.base_margin * 1.75 * EDSCALE);
int v_sep = (p_config.enable_touch_optimizations ? 12 : p_config.base_margin * 1.75) * EDSCALE;
p_theme->set_constant("v_separation", "PopupMenu", v_sep);
+ p_theme->set_constant("search_bar_separation", "PopupMenu", v_sep);
p_theme->set_constant("outline_size", "PopupMenu", 0);
p_theme->set_constant("item_start_padding", "PopupMenu", p_config.popup_margin);
p_theme->set_constant("item_end_padding", "PopupMenu", p_config.popup_margin);
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 67c1acd441..44e7e7229d 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -270,20 +270,28 @@ Size2 PopupMenu::_get_contents_minimum_size() const {
minsize.height += _get_item_height(i) + theme_cache.v_separation;
}
- minsize.width += theme_cache.item_start_padding + body_max_w + accel_max_w + theme_cache.item_end_padding;
+ body_max_w = theme_cache.item_start_padding + body_max_w + accel_max_w + theme_cache.item_end_padding;
const int check_w = MAX(theme_cache.checked->get_width(), theme_cache.radio_checked->get_width());
if (gutter_compact) {
- minsize.width += MAX(icon_max_w, check_w) + theme_cache.h_separation;
+ body_max_w += MAX(icon_max_w, check_w) + theme_cache.h_separation;
} else {
if (icon_max_w > 0) {
- minsize.width += icon_max_w + theme_cache.h_separation;
+ body_max_w += icon_max_w + theme_cache.h_separation;
}
if (has_check_gutter) {
- minsize.width += check_w + theme_cache.h_separation;
+ body_max_w += check_w + theme_cache.h_separation;
}
}
+ if (is_search_bar_enabled()) {
+ Size2 sb_min_size = search_bar->get_minimum_size();
+ minsize.width += MAX(body_max_w, sb_min_size.width);
+ minsize.height += sb_min_size.height + theme_cache.search_bar_separation;
+ } else {
+ minsize.width += body_max_w;
+ }
+
if (is_inside_tree()) {
int height_limit = get_usable_parent_rect().size.height;
if (minsize.height > height_limit) {
@@ -1400,6 +1408,7 @@ void PopupMenu::_notification(int p_what) {
case Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_THEME_CHANGED: {
search_bar->set_right_icon(get_theme_icon(SNAME("search")));
+ vbox_container->add_theme_constant_override(SNAME("separation"), theme_cache.search_bar_separation);
panel->add_theme_style_override(SceneStringName(panel), theme_cache.panel_style);
@@ -3426,6 +3435,7 @@ void PopupMenu::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, PopupMenu, v_separation);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, PopupMenu, h_separation);
+ BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, PopupMenu, search_bar_separation);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, PopupMenu, indent);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, PopupMenu, item_start_padding);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, PopupMenu, item_end_padding);
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index bd6a02c1b9..de541fe56b 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -201,6 +201,7 @@ class PopupMenu : public Popup {
int v_separation = 0;
int h_separation = 0;
+ int search_bar_separation = 0;
int indent = 0;
int item_start_padding = 0;
int item_end_padding = 0;
diff --git a/scene/theme/default_theme.cpp b/scene/theme/default_theme.cpp
index cf9645a429..1af9fb4e66 100644
--- a/scene/theme/default_theme.cpp
+++ b/scene/theme/default_theme.cpp
@@ -790,6 +790,7 @@ void fill_default_theme(Ref &theme, const Ref &default_font, const
theme->set_constant("indent", "PopupMenu", Math::round(10 * scale));
theme->set_constant("h_separation", "PopupMenu", Math::round(4 * scale));
theme->set_constant("v_separation", "PopupMenu", Math::round(4 * scale));
+ theme->set_constant("search_bar_separation", "PopupMenu", Math::round(4 * scale));
theme->set_constant("outline_size", "PopupMenu", 0);
theme->set_constant("separator_outline_size", "PopupMenu", 0);
theme->set_constant("item_start_padding", "PopupMenu", Math::round(2 * scale));