diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 052915d2f0aca..aeabd2dbe9bc6 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -146,6 +146,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 8f9a4f0cb28b8..66c4ce0e0f834 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3886,7 +3886,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? @@ -5861,7 +5861,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 @@ -6112,7 +6115,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; @@ -6749,6 +6755,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; @@ -8415,7 +8434,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 3373db061dc3f..f101c438530c9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1994,6 +1994,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 _or_ docked 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. Doesn't cross through popups/dock nodes. ImGuiWindow* RootWindowPopupTree; // Point to ourself or first ancestor that is not a child window. Cross through popups parent<>child. ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active. @@ -2382,6 +2383,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);