diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b21cf97e7e0b4..d3ecf9da26bd4 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,6 +54,7 @@ Other Changes: - Backends: Metal: Fixed a crash when clipping rect larger than framebuffer is submitted via a direct unclipped PushClipRect() call. (#4464) - Backends: All renderers: Normalize clipping rect handling across backends. (#4464) +- Popups: Windows created from within a popup/modal will no longer close that popup/modal. (#4317) [@rokups] ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index d37315a956990..af6cb1e644c57 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3879,7 +3879,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags() // Modal windows prevents mouse from hovering behind them. ImGuiWindow* modal_window = GetTopMostPopupModal(); - if (modal_window && g.HoveredWindow && !IsWindowChildOf(g.HoveredWindow->RootWindow, modal_window)) + if (modal_window && g.HoveredWindow && !IsWindowChildOfBeginStack(g.HoveredWindow->RootWindow, modal_window)) clear_hovered_windows = true; // Disabled mouse? @@ -5843,7 +5843,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Update ->RootWindow and others pointers (before any possible call to FocusWindow) if (first_begin_of_the_frame) + { UpdateWindowParentAndRootLinks(window, flags, parent_window); + window->ParentWindowInBeginStack = parent_window_in_stack; + } // Process SetNextWindow***() calls // (FIXME: Consider splitting the HasXXX flags into X/Y components @@ -6094,7 +6097,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) bool want_focus = false; if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing)) { - if (flags & ImGuiWindowFlags_Popup) + ImGuiWindow* modal = GetTopMostPopupModal(); + if (modal != NULL && !IsWindowChildOfBeginStack(window, modal)) + want_focus = false; + else if (flags & ImGuiWindowFlags_Popup) want_focus = true; else if ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) == 0) want_focus = true; @@ -6697,6 +6703,19 @@ bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent) return false; } +bool ImGui::IsWindowChildOfBeginStack(ImGuiWindow* window, ImGuiWindow* potential_parent) +{ + if (window->RootWindow == potential_parent) + return true; + while (window != NULL) + { + if (window == potential_parent) + return true; + window = window->ParentWindowInBeginStack; + } + return false; +} + bool ImGui::IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below) { ImGuiContext& g = *GImGui; @@ -8285,7 +8304,7 @@ void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to bool ref_window_is_descendent_of_popup = false; for (int n = popup_count_to_keep; n < g.OpenPopupStack.Size; n++) if (ImGuiWindow* popup_window = g.OpenPopupStack[n].Window) - if (popup_window->RootWindow == ref_window->RootWindow) + if (IsWindowChildOfBeginStack(ref_window, popup_window)) { ref_window_is_descendent_of_popup = true; break; diff --git a/imgui_internal.h b/imgui_internal.h index 017e8de3df508..4c9829a2d2577 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1943,6 +1943,7 @@ struct IMGUI_API ImGuiWindow ImDrawList* DrawList; // == &DrawListInst (for backward compatibility reason with code using imgui_internal.h we keep this a pointer) ImDrawList DrawListInst; ImGuiWindow* ParentWindow; // If we are a child _or_ popup window, this is pointing to our parent. Otherwise NULL. + ImGuiWindow* ParentWindowInBeginStack; ImGuiWindow* RootWindow; // Point to ourself or first ancestor that is not a child window == Top-level window. ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active. ImGuiWindow* RootWindowForNav; // Point to ourself or first ancestor which doesn't have the NavFlattened flag. @@ -2330,6 +2331,7 @@ namespace ImGui IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window); IMGUI_API ImVec2 CalcWindowNextAutoFitSize(ImGuiWindow* window); IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); + IMGUI_API bool IsWindowChildOfBeginStack(ImGuiWindow* window, ImGuiWindow* potential_parent); IMGUI_API bool IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below); IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window); IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0);