Viewports: fixed an issue inferring Z-order when attempting to merge a viewport back in the the main/hosting viewport. (#8948)

This commit is contained in:
ocornut
2025-09-22 15:31:23 +02:00
parent 1ad9de5aae
commit dfe308bc53
2 changed files with 19 additions and 7 deletions

View File

@@ -54,6 +54,11 @@ Docking+Viewports Branch:
- Nav: fixed a crash that could occur when opening a popup following the processing
of a global shortcut while no windows were focused (the fix done in 1.92.3 was
incomplete for docking branch).
- Viewports: fixed an issue inferring Z-order when attempting to merge a viewport
back in the the main/hosting viewport. (#8948)
Note that for GLFW/SDL2/OSX backends, which do not support honoring ParentViewportID.
setting io.ConfigViewportsNoDefaultParent=true will align imgui's expectation with
what the backend does.
- Viewports: DestroyContext() does not call DestroyPlatformWindows() anymore at
it assumed to be unnecessary as backensd should have done it and we check that
backends have been shutdown since 1.90.4. Changed into asserts. (#7175, #8945)

View File

@@ -16326,6 +16326,15 @@ static bool ImGui::GetWindowAlwaysWantOwnViewport(ImGuiWindow* window)
return false;
}
// Heuristic, see #8948: depends on how backends handle OS-level parenting.
static bool IsViewportAbove(ImGuiViewportP* potential_above, ImGuiViewportP* potential_below)
{
if (potential_above->LastFocusedStampCount > potential_below->LastFocusedStampCount || potential_above->ParentViewportId == potential_below->ID) // FIXME: Should follow the ParentViewportId list.
return true;
return false;
}
static bool ImGui::UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* viewport)
{
ImGuiContext& g = *GImGui;
@@ -16340,14 +16349,12 @@ static bool ImGui::UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImG
if (GetWindowAlwaysWantOwnViewport(window))
return false;
// FIXME: Can't use g.WindowsFocusOrder[] for root windows only as we care about Z order. If we maintained a DisplayOrder along with FocusOrder we could..
for (ImGuiWindow* window_behind : g.Windows)
for (ImGuiViewportP* viewport_2 : g.Viewports)
{
if (window_behind == window)
break;
if (window_behind->WasActive && window_behind->ViewportOwned && !(window_behind->Flags & ImGuiWindowFlags_ChildWindow))
if (window_behind->Viewport->GetMainRect().Overlaps(window->Rect()))
return false;
if (viewport_2 == viewport || viewport_2 == window->Viewport)
continue;
if (IsViewportAbove(viewport_2, viewport) && viewport_2->GetMainRect().Overlaps(window->Rect()))
return false;
}
// Move to the existing viewport, Move child/hosted windows as well (FIXME-OPT: iterate child)