From 0d08927dae557cd537416661d932b19dc6f040db Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 14 Jan 2026 14:59:39 +0100 Subject: [PATCH] Error handling: Improve error handling and recovery for EndMenu()/EndCombo(). (#1651, #9165, #8499) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 2 +- imgui_widgets.cpp | 18 +++++++++++++++--- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 76d922194..0645eff90 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -173,6 +173,8 @@ Other Changes: (which mimicks what's done internally in the ItemHoverable() function). (#9138) - Fixed tooltip placement being affected for a frame when located over an item activated by SetNextItemShortcut(). (#9138) +- Error Handling: + - Improve error handling and recovery for EndMenu()/EndCombo(). (#1651, #9165, #8499) - Debug Tools: - Debug Log: fixed incorrectly printing characters in IO log when submitting non-ASCII values to io.AddInputCharacter(). (#9099) diff --git a/imgui.cpp b/imgui.cpp index b1948d665..2a63f26e7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12455,7 +12455,7 @@ void ImGui::EndPopup() ImGuiWindow* window = g.CurrentWindow; if ((window->Flags & ImGuiWindowFlags_Popup) == 0 || g.BeginPopupStack.Size == 0) { - IM_ASSERT_USER_ERROR(0, "Calling EndPopup() too many times or in wrong window!"); + IM_ASSERT_USER_ERROR(0, "Calling EndPopup() in wrong window!"); return; } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 4244c0be3..3b6ee2156 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2053,8 +2053,15 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags void ImGui::EndCombo() { ImGuiContext& g = *GImGui; - EndPopup(); g.BeginComboDepth--; + char name[16]; + ImFormatString(name, IM_COUNTOF(name), "##Combo_%02d", g.BeginComboDepth); // FIXME: Move those to helpers? + if (strcmp(g.CurrentWindow->Name, name) != 0) + { + IM_ASSERT_USER_ERROR(0, "Calling EndCombo() in wrong window!"); + return; + } + EndPopup(); } // Call directly after the BeginCombo/EndCombo block. The preview is designed to only host non-interactive elements @@ -9399,7 +9406,12 @@ void ImGui::EndMenu() // Nav: When a left move request our menu failed, close ourselves. ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginMenu()/EndMenu() calls + + if ((window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) != (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) + { + IM_ASSERT_USER_ERROR(0, "Calling EndMenu() in wrong window!"); + return; + } ImGuiWindow* parent_window = window->ParentWindow; // Should always be != NULL is we passed assert. if (window->BeginCount == window->BeginCountPreviousFrame) if (g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet()) @@ -10343,7 +10355,7 @@ bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags f ImGuiTabBar* tab_bar = g.CurrentTabBar; if (tab_bar == NULL) { - IM_ASSERT_USER_ERROR(tab_bar, "Needs to be called between BeginTabBar() and EndTabBar()!"); + IM_ASSERT_USER_ERROR(tab_bar != NULL, "Needs to be called between BeginTabBar() and EndTabBar()!"); return false; } IM_ASSERT((flags & ImGuiTabItemFlags_Button) == 0); // BeginTabItem() Can't be used with button flags, use TabItemButton() instead!