Combo: Fixed not reusing windows optimally when used inside a popup stack.

This commit is contained in:
ocornut 2024-02-09 15:23:43 +01:00
parent 5cdc4a2a41
commit 70aa717a8e
4 changed files with 11 additions and 7 deletions

View File

@ -66,6 +66,7 @@ Other changes:
the effect would be very disastrous in term of confusion, as reopening would steal focus). the effect would be very disastrous in term of confusion, as reopening would steal focus).
- Popups: Slight change to popup closing logic (e.g. after focusing another window) which skipped - Popups: Slight change to popup closing logic (e.g. after focusing another window) which skipped
over popups that are also child windows. over popups that are also child windows.
- Combo: Fixed not reusing windows optimally when used inside a popup stack.
- Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. - Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect.
- Debug Tools: Debug Log: Added "Input Routing" logging. - Debug Tools: Debug Log: Added "Input Routing" logging.
- Debug Tools: Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266) [@Peter0x44] - Debug Tools: Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266) [@Peter0x44]

View File

@ -6434,7 +6434,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window_stack_data.StackSizesOnBegin.SetToContextState(&g); window_stack_data.StackSizesOnBegin.SetToContextState(&g);
g.CurrentWindowStack.push_back(window_stack_data); g.CurrentWindowStack.push_back(window_stack_data);
if (flags & ImGuiWindowFlags_ChildMenu) if (flags & ImGuiWindowFlags_ChildMenu)
g.BeginMenuCount++; g.BeginMenuDepth++;
// Update ->RootWindow and others pointers (before any possible call to FocusWindow) // Update ->RootWindow and others pointers (before any possible call to FocusWindow)
if (first_begin_of_the_frame) if (first_begin_of_the_frame)
@ -7106,7 +7106,7 @@ void ImGui::End()
// Pop from window stack // Pop from window stack
g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup; g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup;
if (window->Flags & ImGuiWindowFlags_ChildMenu) if (window->Flags & ImGuiWindowFlags_ChildMenu)
g.BeginMenuCount--; g.BeginMenuDepth--;
if (window->Flags & ImGuiWindowFlags_Popup) if (window->Flags & ImGuiWindowFlags_Popup)
g.BeginPopupStack.pop_back(); g.BeginPopupStack.pop_back();
g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithContextState(&g); g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithContextState(&g);
@ -10926,7 +10926,7 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags flags)
char name[20]; char name[20];
if (flags & ImGuiWindowFlags_ChildMenu) if (flags & ImGuiWindowFlags_ChildMenu)
ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginMenuCount); // Recycle windows based on depth ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginMenuDepth); // Recycle windows based on depth
else else
ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame

View File

@ -2028,8 +2028,6 @@ struct ImGuiContext
ImVector<ImGuiPopupData> BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame) ImVector<ImGuiPopupData> BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame)
ImVector<ImGuiNavTreeNodeData> NavTreeNodeStack; // Stack for TreeNode() when a NavLeft requested is emitted. ImVector<ImGuiNavTreeNodeData> NavTreeNodeStack; // Stack for TreeNode() when a NavLeft requested is emitted.
int BeginMenuCount;
// Viewports // Viewports
ImVector<ImGuiViewportP*> Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData. ImVector<ImGuiViewportP*> Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData.
@ -2154,6 +2152,8 @@ struct ImGuiContext
ImGuiInputTextDeactivatedState InputTextDeactivatedState; ImGuiInputTextDeactivatedState InputTextDeactivatedState;
ImFont InputTextPasswordFont; ImFont InputTextPasswordFont;
ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc. ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc.
int BeginMenuDepth;
int BeginComboDepth;
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
ImGuiID ColorEditCurrentID; // Set temporarily while inside of the parent-most ColorEdit4/ColorPicker4 (because they call each others). ImGuiID ColorEditCurrentID; // Set temporarily while inside of the parent-most ColorEdit4/ColorPicker4 (because they call each others).
ImGuiID ColorEditSavedID; // ID we are saving/restoring HS for ImGuiID ColorEditSavedID; // ID we are saving/restoring HS for
@ -2307,7 +2307,6 @@ struct ImGuiContext
CurrentFocusScopeId = 0; CurrentFocusScopeId = 0;
CurrentItemFlags = ImGuiItemFlags_None; CurrentItemFlags = ImGuiItemFlags_None;
DebugShowGroupRects = false; DebugShowGroupRects = false;
BeginMenuCount = 0;
NavWindow = NULL; NavWindow = NULL;
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0; NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
@ -2371,6 +2370,7 @@ struct ImGuiContext
MouseStationaryTimer = 0.0f; MouseStationaryTimer = 0.0f;
TempInputId = 0; TempInputId = 0;
BeginMenuDepth = BeginComboDepth = 0;
ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_; ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
ColorEditCurrentID = ColorEditSavedID = 0; ColorEditCurrentID = ColorEditSavedID = 0;
ColorEditSavedHue = ColorEditSavedSat = 0.0f; ColorEditSavedHue = ColorEditSavedSat = 0.0f;

View File

@ -1784,7 +1784,7 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags
// This is essentially a specialized version of BeginPopupEx() // This is essentially a specialized version of BeginPopupEx()
char name[16]; char name[16];
ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginComboDepth); // Recycle windows based on depth
// Set position given a custom constraint (peak into expected window size so we can position it) // Set position given a custom constraint (peak into expected window size so we can position it)
// FIXME: This might be easier to express with an hypothetical SetNextWindowPosConstraints() function? // FIXME: This might be easier to express with an hypothetical SetNextWindowPosConstraints() function?
@ -1811,12 +1811,15 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags
IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above
return false; return false;
} }
g.BeginComboDepth++;
return true; return true;
} }
void ImGui::EndCombo() void ImGui::EndCombo()
{ {
ImGuiContext& g = *GImGui;
EndPopup(); EndPopup();
g.BeginComboDepth--;
} }
// Call directly after the BeginCombo/EndCombo block. The preview is designed to only host non-interactive elements // Call directly after the BeginCombo/EndCombo block. The preview is designed to only host non-interactive elements