|
|
@@ -6237,11 +6237,30 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
const ImGuiStyle& style = g.Style;
|
|
|
const ImGuiID id = window->GetID(label);
|
|
|
+ bool menu_is_open = IsPopupOpen(id);
|
|
|
|
|
|
- ImVec2 label_size = CalcTextSize(label, NULL, true);
|
|
|
+ // Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu)
|
|
|
+ ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus;
|
|
|
+ if (window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu))
|
|
|
+ flags |= ImGuiWindowFlags_ChildWindow;
|
|
|
|
|
|
+ // If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin().
|
|
|
+ // We are relying on a O(N) search - so O(N log N) over the frame - which seems like the most efficient for the expected small amount of BeginMenu() calls per frame.
|
|
|
+ // If somehow this is ever becoming a problem we can switch to use e.g. a ImGuiStorager mapping key to last frame used.
|
|
|
+ if (g.MenusIdSubmittedThisFrame.contains(id))
|
|
|
+ {
|
|
|
+ if (menu_is_open)
|
|
|
+ menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
|
|
|
+ else
|
|
|
+ g.NextWindowData.ClearFlags(); // we behave like Begin() and need to consume those values
|
|
|
+ return menu_is_open;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Tag menu as used. Next time BeginMenu() with same ID is called it will append to existing menu
|
|
|
+ g.MenusIdSubmittedThisFrame.push_back(id);
|
|
|
+
|
|
|
+ ImVec2 label_size = CalcTextSize(label, NULL, true);
|
|
|
bool pressed;
|
|
|
- bool menu_is_open = IsPopupOpen(id);
|
|
|
bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].OpenParentId == window->IDStack.back());
|
|
|
ImGuiWindow* backed_nav_window = g.NavWindow;
|
|
|
if (menuset_is_open)
|
|
|
@@ -6360,11 +6379,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
|
|
|
|
|
|
if (menu_is_open)
|
|
|
{
|
|
|
- // Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu)
|
|
|
SetNextWindowPos(popup_pos, ImGuiCond_Always);
|
|
|
- ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus;
|
|
|
- if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu))
|
|
|
- flags |= ImGuiWindowFlags_ChildWindow;
|
|
|
menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
|
|
|
}
|
|
|
else
|