diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index bb83fcf56189..f548e785dbc6 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -184,6 +184,7 @@ Docking+Viewports Branch: - Docking, Style: Docked windows honor display their border properly. (#2522) - Docking: Fixed incorrectly rounded tab bars for dock node that are not at the top of their dock tree. - Docking: Fixed single-frame node pos/size inconsistencies when window stop or start being submitted. +- Docking: Prevent docking any window created above a popup/modal. (#4317) - Viewports: Made it possible to explicitly assign ImGuiWindowClass::ParentViewportId to 0 in order to ensure a window is not parented. Previously this would use the global default (which might be 0, but not always as it would depend on io.ConfigViewportsNoDefaultParent). (#3152, #2871) diff --git a/imgui.cpp b/imgui.cpp index 45418b4ddc48..8a51bfd8e0e0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -14897,12 +14897,23 @@ static bool DockNodeIsDropAllowedOne(ImGuiWindow* payload, ImGuiWindow* host_win return false; } + // Prevent docking any window created above a popup + // Technically we should support it (e.g. in the case of a long-lived modal window that had fancy docking features), + // by e.g. adding a 'if (!ImGui::IsWindowWithinBeginStackOf(host_window, popup_window))' test. + // But it would requires more work on our end because the dock host windows is technically created in NewFrame() + // and our ->ParentXXX and ->RootXXX pointers inside windows are currently mislading or lacking. + ImGuiContext& g = *GImGui; + for (int i = g.OpenPopupStack.Size - 1; i >= 0; i--) + if (ImGuiWindow* popup_window = g.OpenPopupStack[i].Window) + if (ImGui::IsWindowWithinBeginStackOf(payload, popup_window)) // Payload is created from within a popup begin stack. + return false; + return true; } static bool ImGui::DockNodeIsDropAllowed(ImGuiWindow* host_window, ImGuiWindow* root_payload) { - if (root_payload->DockNodeAsHost && root_payload->DockNodeAsHost->IsSplitNode()) + if (root_payload->DockNodeAsHost && root_payload->DockNodeAsHost->IsSplitNode()) // FIXME-DOCK: Missing filtering return true; const int payload_count = root_payload->DockNodeAsHost ? root_payload->DockNodeAsHost->Windows.Size : 1;