From e4733c5fc4e17fbd0767ec58790357e2d746e60b Mon Sep 17 00:00:00 2001 From: Hein-Pieter van Braam Date: Thu, 16 Aug 2018 21:44:18 +0200 Subject: [PATCH] Delay emitting pressed signals in PopupMenu When processing items we may actually delete the item we're processing in the callback for the signal. To avoid this, call the signal after we're done processing the items. But before hiding the popupmenu itself. Thanks to @reduz for writing the whole solution. This fixes #19842 (cherry picked from commit fa7eac8a0dfbd7271dcbdd398d4075c7f49d6836) --- scene/gui/popup_menu.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 1b486f783a7..289a9837f2a 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -979,10 +979,8 @@ void PopupMenu::activate_item(int p_item) { ERR_FAIL_INDEX(p_item, items.size()); ERR_FAIL_COND(items[p_item].separator); int id = items[p_item].ID >= 0 ? items[p_item].ID : p_item; - emit_signal("id_pressed", id); - emit_signal("index_pressed", p_item); - //hide all parent PopupMenue's + //hide all parent PopupMenus Node *next = get_parent(); PopupMenu *pop = Object::cast_to(next); while (pop) { @@ -1006,16 +1004,23 @@ void PopupMenu::activate_item(int p_item) { // Hides popup by default; unless otherwise specified // by using set_hide_on_item_selection and set_hide_on_checkable_item_selection + bool need_hide = true; + if (items[p_item].checkable_type) { if (!hide_on_checkable_item_selection) - return; + need_hide = false; } else if (0 < items[p_item].max_states) { if (!hide_on_multistate_item_selection) - return; + need_hide = false; } else if (!hide_on_item_selection) - return; + need_hide = false; - hide(); + emit_signal("id_pressed", id); + emit_signal("index_pressed", p_item); + + if (need_hide) { + hide(); + } } void PopupMenu::remove_item(int p_idx) {