From fa178f42350598f853f2ec36b5aeb231e0e08c75 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 30 Jan 2025 14:30:14 +0100 Subject: [PATCH] Error Handling: Recovery from missing EndMenuBar() call. (#1651) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 5 +++++ imgui_widgets.cpp | 9 +++++---- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index be448d16f..99333efda 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -71,6 +71,7 @@ Other changes: scrollbar when using thick border sizes. (#8267, #7887) - Windows: Fixed IsItemXXXX() functions not working on append-version of EndChild(). (#8350) Also made some of the fields accessible after BeginChild() to match Begin() logic. +- Error Handling: Recovery from missing EndMenuBar() call. (#1651) - Tables, Menus: Fixed using BeginTable() in menu layer (any menu bar). (#8355) It previously overrode the current layer back to main layer, which caused an issue with MainMenuBar attempted to release focus when leaving the menu layer. diff --git a/imgui.cpp b/imgui.cpp index 5223ed76c..dffd37b45 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10301,6 +10301,11 @@ void ImGui::ErrorRecoveryTryToRecoverWindowState(const ImGuiErrorRecoveryStat IM_ASSERT_USER_ERROR(0, "Missing EndMultiSelect()"); EndMultiSelect(); } + if (window->DC.MenuBarAppending) //-V1044 + { + IM_ASSERT_USER_ERROR(0, "Missing EndMenuBar()"); + EndMenuBar(); + } while (window->DC.TreeDepth > state_in->SizeOfTreeStack) //-V1044 { IM_ASSERT_USER_ERROR(0, "Missing TreePop()"); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index dccb7a535..9335da9fd 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -8657,6 +8657,10 @@ void ImGui::EndMenuBar() return; ImGuiContext& g = *GImGui; + IM_MSVC_WARNING_SUPPRESS(6011); // Static Analysis false positive "warning C6011: Dereferencing NULL pointer 'window'" + IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar); + IM_ASSERT(window->DC.MenuBarAppending); + // Nav: When a move request within one of our child menu failed, capture the request to navigate among our siblings. if (NavMoveRequestButNoResultYet() && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) { @@ -8683,9 +8687,6 @@ void ImGui::EndMenuBar() } } - IM_MSVC_WARNING_SUPPRESS(6011); // Static Analysis false positive "warning C6011: Dereferencing NULL pointer 'window'" - IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar); - IM_ASSERT(window->DC.MenuBarAppending); PopClipRect(); PopID(); window->DC.MenuBarOffset.x = window->DC.CursorPos.x - window->Pos.x; // Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos. @@ -8764,11 +8765,11 @@ bool ImGui::BeginMainMenuBar() void ImGui::EndMainMenuBar() { + ImGuiContext& g = *GImGui; EndMenuBar(); // When the user has left the menu layer (typically: closed menus through activation of an item), we restore focus to the previous window // FIXME: With this strategy we won't be able to restore a NULL focus. - ImGuiContext& g = *GImGui; if (g.CurrentWindow == g.NavWindow && g.NavLayer == ImGuiNavLayer_Main && !g.NavAnyRequest && g.ActiveId == 0) FocusTopMostWindowUnderOne(g.NavWindow, NULL, NULL, ImGuiFocusRequestFlags_UnlessBelowModal | ImGuiFocusRequestFlags_RestoreFocusedChild);