Skip to content

Commit

Permalink
Error Handling: Fixed bugs recovering from within a table that create…
Browse files Browse the repository at this point in the history
…d a child window, and from nested child windows. (ocornut#1651)
  • Loading branch information
ocornut authored and matthew-mccall committed Jan 1, 2025
1 parent 0617487 commit 7789d72
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 11 deletions.
2 changes: 2 additions & 0 deletions docs/CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ Breaking changes:

Other changes:

- Error Handling: Fixed bugs recovering from within a table that created
a child window, and from nested child windows. (#1651)
- InputText: Fixed a bug where character replacements performed from a callback
were not applied when pasting from clipbard. (#8229)
- InputText: Fixed issue when activating a ReadOnly field when the underlying
Expand Down
29 changes: 19 additions & 10 deletions imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3884,7 +3884,8 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
Time = 0.0f;
FrameCount = 0;
FrameCountEnded = FrameCountRendered = -1;
WithinFrameScope = WithinFrameScopeWithImplicitWindow = WithinEndChild = false;
WithinEndChildID = 0;
WithinFrameScope = WithinFrameScopeWithImplicitWindow = false;
GcCompactAll = false;
TestEngineHookItems = false;
TestEngine = NULL;
Expand Down Expand Up @@ -6106,10 +6107,10 @@ void ImGui::EndChild()
ImGuiContext& g = *GImGui;
ImGuiWindow* child_window = g.CurrentWindow;

IM_ASSERT(g.WithinEndChild == false);
const ImGuiID backup_within_end_child_id = g.WithinEndChildID;
IM_ASSERT(child_window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() calls

g.WithinEndChild = true;
g.WithinEndChildID = child_window->ID;
ImVec2 child_size = child_window->Size;
End();
if (child_window->BeginCount == 1)
Expand Down Expand Up @@ -6141,7 +6142,7 @@ void ImGui::EndChild()
if (g.HoveredWindow == child_window)
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
}
g.WithinEndChild = false;
g.WithinEndChildID = backup_within_end_child_id;
g.LogLinePosY = -FLT_MAX; // To enforce a carriage return
}

Expand Down Expand Up @@ -7773,7 +7774,7 @@ void ImGui::End()

// Error checking: verify that user doesn't directly call End() on a child window.
if (window->Flags & ImGuiWindowFlags_ChildWindow)
IM_ASSERT_USER_ERROR(g.WithinEndChild, "Must call EndChild() and not End()!");
IM_ASSERT_USER_ERROR(g.WithinEndChildID == window->ID, "Must call EndChild() and not End()!");

// Close anything that is open
if (window->DC.CurrentColumns)
Expand Down Expand Up @@ -10485,8 +10486,16 @@ void ImGui::ErrorRecoveryTryToRecoverState(const ImGuiErrorRecoveryState* state_
ImGuiWindow* window = g.CurrentWindow;
if (window->Flags & ImGuiWindowFlags_ChildWindow)
{
IM_ASSERT_USER_ERROR(0, "Missing EndChild()");
EndChild();
if (g.CurrentTable != NULL && g.CurrentTable->InnerWindow == g.CurrentWindow)
{
IM_ASSERT_USER_ERROR(0, "Missing EndTable()");
EndTable();
}
else
{
IM_ASSERT_USER_ERROR(0, "Missing EndChild()");
EndChild();
}
}
else
{
Expand Down Expand Up @@ -11921,11 +11930,11 @@ void ImGui::EndPopup()
NavMoveRequestTryWrapping(window, ImGuiNavMoveFlags_LoopY);

// Child-popups don't need to be laid out
IM_ASSERT(g.WithinEndChild == false);
const ImGuiID backup_within_end_child_id = g.WithinEndChildID;
if (window->Flags & ImGuiWindowFlags_ChildWindow)
g.WithinEndChild = true;
g.WithinEndChildID = window->ID;
End();
g.WithinEndChild = false;
g.WithinEndChildID = backup_within_end_child_id;
}

// Helper to open a popup if mouse button is released over the item
Expand Down
2 changes: 1 addition & 1 deletion imgui_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -2045,9 +2045,9 @@ struct ImGuiContext
int FrameCount;
int FrameCountEnded;
int FrameCountRendered;
ImGuiID WithinEndChildID; // Set within EndChild()
bool WithinFrameScope; // Set by NewFrame(), cleared by EndFrame()
bool WithinFrameScopeWithImplicitWindow; // Set by NewFrame(), cleared by EndFrame() when the implicit debug window has been pushed
bool WithinEndChild; // Set within EndChild()
bool GcCompactAll; // Request full GC
bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log()
void* TestEngine; // Test engine user data
Expand Down

0 comments on commit 7789d72

Please sign in to comment.