Docking: Fix crash when a dock node gets re-qualified as dockspace>floating>dockspace.. (#3203, #4295)

Which tends to happen when incorrectly calling DockBuilderAddNode() without ImGuiDockNodeFlags_Dockspace and using it as a Dockspace on the next frame after the floating window hosting the node has been automatically created.
This commit is contained in:
ocornut 2021-07-07 18:22:55 +02:00
parent cd4cc9ff0d
commit eb6f4b1a6a
2 changed files with 21 additions and 5 deletions

View File

@ -144,7 +144,10 @@ Docking+Viewports Branch:
- Docking: Clicking on the right-most close button of a docking node closes all windows. (#4186) - Docking: Clicking on the right-most close button of a docking node closes all windows. (#4186)
- Docking: Fix IsWindowAppearing() and ImGuiCond_Appearing on docked windows. (#4177, #3982, #1497, #1061) - Docking: Fix IsWindowAppearing() and ImGuiCond_Appearing on docked windows. (#4177, #3982, #1497, #1061)
- Docking: Fix crash issues using DockBuilderRemoveNode() in some situations. (#3111, #3179, #3203, #4295) [@hsimyu] - Docking: Fix crash using DockBuilderRemoveNode() in some situations. (#3111, #3179, #3203, #4295) [@hsimyu]
- Docking: Fix crash when a dock node gets re-qualified as dockspace>floating>dockspace, which tends to happen
when incorrectly calling DockBuilderAddNode() without ImGuiDockNodeFlags_Dockspace and using it as a Dockspace
on the next frame after the floating window hosting the node has been automatically created. (#3203, #4295)
- Docking: Reworked node flags saving/inheritance so that flags enforced by docked windows via the - Docking: Reworked node flags saving/inheritance so that flags enforced by docked windows via the
DockNodeFlagsOverrideSet mechanism are are not left in empty dockspace nodes once the windows gets undocked. DockNodeFlagsOverrideSet mechanism are are not left in empty dockspace nodes once the windows gets undocked.
(#4292, #3834, #3633, #3521, #3492, #3335, #2999, #2648) (#4292, #3834, #3633, #3521, #3492, #3335, #2999, #2648)

View File

@ -13520,6 +13520,20 @@ static void ImGui::DockNodeUpdateForRootNode(ImGuiDockNode* node)
} }
} }
static void DockNodeSetupHostWindow(ImGuiDockNode* node, ImGuiWindow* host_window)
{
// Remove ourselves from any previous different host window
// This can happen if a user mistakenly does (see #4295 for details):
// - N+0: DockBuilderAddNode(id, 0) // missing ImGuiDockNodeFlags_DockSpace
// - N+1: NewFrame() // will create floating host window for that node
// - N+1: DockSpace(id) // requalify node as dockspace, moving host window
if (node->HostWindow && node->HostWindow != host_window && node->HostWindow->DockNodeAsHost == node)
node->HostWindow->DockNodeAsHost = NULL;
host_window->DockNodeAsHost = node;
node->HostWindow = host_window;
}
static void ImGui::DockNodeUpdate(ImGuiDockNode* node) static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -13668,8 +13682,8 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
PopStyleVar(); PopStyleVar();
beginned_into_host_window = true; beginned_into_host_window = true;
node->HostWindow = host_window = g.CurrentWindow; host_window = g.CurrentWindow;
host_window->DockNodeAsHost = node; DockNodeSetupHostWindow(node, host_window);
host_window->DC.CursorPos = host_window->Pos; host_window->DC.CursorPos = host_window->Pos;
node->Pos = host_window->Pos; node->Pos = host_window->Pos;
node->Size = host_window->Size; node->Size = host_window->Size;
@ -14986,9 +15000,8 @@ ImGuiID ImGui::DockSpace(ImGuiID id, const ImVec2& size_arg, ImGuiDockNodeFlags
PopStyleVar(); PopStyleVar();
ImGuiWindow* host_window = g.CurrentWindow; ImGuiWindow* host_window = g.CurrentWindow;
host_window->DockNodeAsHost = node; DockNodeSetupHostWindow(node, host_window);
host_window->ChildId = window->GetID(title); host_window->ChildId = window->GetID(title);
node->HostWindow = host_window;
node->OnlyNodeWithWindows = NULL; node->OnlyNodeWithWindows = NULL;
IM_ASSERT(node->IsRootNode()); IM_ASSERT(node->IsRootNode());