From 6692c6ed14d63d7b65a32d320c953a9195aa997e Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Tue, 27 Jul 2021 16:47:18 +0300 Subject: [PATCH] Popups: Fix popups being closed by newly appearing windows. (#4317) * Popups/modals now remain open when new windows are created from within popup/modal begin stack. * Modals are not closed when new window appears behind active modal. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 22 +++++++++++++++++++--- imgui_internal.h | 1 + 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a3de7b033a117..13399664da16b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -181,6 +181,7 @@ Other Changes: - Backends: OSX: Use mach_absolute_time as CFAbsoluteTimeGetCurrent can jump backwards. (#4557, #4563) [@lfnoise] - Backends: All renderers: Normalize clipping rect handling across backends. (#4464) - Examples: Added SDL + SDL_Renderer example in "examples/example_sdl_sdlrenderer/" folder. (#3926) [@1bsyl] +- 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 4366aef16b76a..e72fae690a0be 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3910,7 +3910,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, true)) + if (modal_window && g.HoveredWindow && !IsWindowChildOfBeginStack(g.HoveredWindow->RootWindow, modal_window)) clear_hovered_windows = true; // Disabled mouse? @@ -6200,7 +6200,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; @@ -6810,6 +6813,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; @@ -8492,7 +8508,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 d56204d3f79a8..be883366664c9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2418,6 +2418,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, bool popup_hierarchy); + 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);