Skip to content

Commit 8733ca4

Browse files
committed
Docking: Fixed single-frame node pos/size inconsistencies when window stop or start being submitted.
Fix 718e15c while preserving its intended property. Tested by "docking_window_appearing_layout". (#2109)
1 parent 6afcfe3 commit 8733ca4

File tree

3 files changed

+24
-20
lines changed

3 files changed

+24
-20
lines changed

docs/CHANGELOG.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ Docking+Viewports Branch:
159159
- Docking: Fixed a bug undocking windows docked into a non-visible or _KeepAliveOnly dockspace
160160
when unrelated windows submitted before the dockspace have dynamic visibility. (#4757)
161161
- Docking: Fixed incorrectly rounded tab bars for dock node that are not at the top of their dock tree.
162+
- Docking: Fixed single-frame node pos/size inconsistencies when window stop or start being submitted.
162163
- Viewports: Made it possible to explicitly assign ImGuiWindowClass::ParentViewportId to 0 in order
163164
to ensure a window is not parented. Previously this would use the global default (which might be 0,
164165
but not always as it would depend on io.ConfigViewportsNoDefaultParent). (#3152, #2871)

imgui.cpp

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12908,7 +12908,7 @@ namespace ImGui
1290812908
// ImGuiDockNode tree manipulations
1290912909
static void DockNodeTreeSplit(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImGuiAxis split_axis, int split_first_child, float split_ratio, ImGuiDockNode* new_node);
1291012910
static void DockNodeTreeMerge(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImGuiDockNode* merge_lead_child);
12911-
static void DockNodeTreeUpdatePosSize(ImGuiDockNode* node, ImVec2 pos, ImVec2 size, bool only_write_to_marked_nodes = false);
12911+
static void DockNodeTreeUpdatePosSize(ImGuiDockNode* node, ImVec2 pos, ImVec2 size, ImGuiDockNode* only_write_to_single_node = NULL);
1291212912
static void DockNodeTreeUpdateSplitter(ImGuiDockNode* node);
1291312913
static ImGuiDockNode* DockNodeTreeFindVisibleNodeByPos(ImGuiDockNode* node, ImVec2 pos);
1291412914
static ImGuiDockNode* DockNodeTreeFindFallbackLeafNode(ImGuiDockNode* node);
@@ -13604,7 +13604,6 @@ ImGuiDockNode::ImGuiDockNode(ImGuiID id)
1360413604
IsVisible = true;
1360513605
IsFocused = HasCloseButton = HasWindowMenuButton = HasCentralNodeChild = false;
1360613606
WantCloseAll = WantLockSizeOnce = WantMouseMove = WantHiddenTabBarUpdate = WantHiddenTabBarToggle = false;
13607-
MarkedForPosSizeWrite = false;
1360813607
}
1360913608

1361013609
ImGuiDockNode::~ImGuiDockNode()
@@ -14045,7 +14044,6 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
1404514044
ImGuiContext& g = *GImGui;
1404614045
IM_ASSERT(node->LastFrameActive != g.FrameCount);
1404714046
node->LastFrameAlive = g.FrameCount;
14048-
node->MarkedForPosSizeWrite = false;
1404914047

1405014048
node->CentralNode = node->OnlyNodeWithWindows = NULL;
1405114049
if (node->IsRootNode())
@@ -15153,11 +15151,11 @@ void ImGui::DockNodeTreeMerge(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImG
1515315151

1515415152
// Update Pos/Size for a node hierarchy (don't affect child Windows yet)
1515515153
// (Depth-first, Pre-Order)
15156-
void ImGui::DockNodeTreeUpdatePosSize(ImGuiDockNode* node, ImVec2 pos, ImVec2 size, bool only_write_to_marked_nodes)
15154+
void ImGui::DockNodeTreeUpdatePosSize(ImGuiDockNode* node, ImVec2 pos, ImVec2 size, ImGuiDockNode* only_write_to_single_node)
1515715155
{
1515815156
// During the regular dock node update we write to all nodes.
15159-
// 'only_write_to_marked_nodes' is only set when turning a node visible mid-frame and we need its size right-away.
15160-
const bool write_to_node = (only_write_to_marked_nodes == false) || (node->MarkedForPosSizeWrite);
15157+
// 'only_write_to_single_node' is only set when turning a node visible mid-frame and we need its size right-away.
15158+
const bool write_to_node = only_write_to_single_node == NULL || only_write_to_single_node == node;
1516115159
if (write_to_node)
1516215160
{
1516315161
node->Pos = pos;
@@ -15171,15 +15169,21 @@ void ImGui::DockNodeTreeUpdatePosSize(ImGuiDockNode* node, ImVec2 pos, ImVec2 si
1517115169
ImGuiDockNode* child_1 = node->ChildNodes[1];
1517215170
ImVec2 child_0_pos = pos, child_1_pos = pos;
1517315171
ImVec2 child_0_size = size, child_1_size = size;
15174-
if (child_0->IsVisible && child_1->IsVisible)
15172+
15173+
const bool child_0_is_toward_single_node = (only_write_to_single_node != NULL && DockNodeIsInHierarchyOf(only_write_to_single_node, child_0));
15174+
const bool child_1_is_toward_single_node = (only_write_to_single_node != NULL && DockNodeIsInHierarchyOf(only_write_to_single_node, child_1));
15175+
const bool child_0_is_or_will_be_visible = child_0->IsVisible || child_0_is_toward_single_node;
15176+
const bool child_1_is_or_will_be_visible = child_1->IsVisible || child_1_is_toward_single_node;
15177+
15178+
if (child_0_is_or_will_be_visible && child_1_is_or_will_be_visible)
1517515179
{
15180+
ImGuiContext& g = *GImGui;
1517615181
const float spacing = DOCKING_SPLITTER_SIZE;
1517715182
const ImGuiAxis axis = (ImGuiAxis)node->SplitAxis;
1517815183
const float size_avail = ImMax(size[axis] - spacing, 0.0f);
1517915184

1518015185
// Size allocation policy
1518115186
// 1) The first 0..WindowMinSize[axis]*2 are allocated evenly to both windows.
15182-
ImGuiContext& g = *GImGui;
1518315187
const float size_min_each = ImFloor(ImMin(size_avail, g.Style.WindowMinSize[axis] * 2.0f) * 0.5f);
1518415188

1518515189
// FIXME: Blocks 2) and 3) are essentially doing nearly the same thing.
@@ -15230,11 +15234,15 @@ void ImGui::DockNodeTreeUpdatePosSize(ImGuiDockNode* node, ImVec2 pos, ImVec2 si
1523015234

1523115235
child_1_pos[axis] += spacing + child_0_size[axis];
1523215236
}
15233-
child_0->WantLockSizeOnce = child_1->WantLockSizeOnce = false;
1523415237

15235-
if (child_0->IsVisible)
15238+
if (only_write_to_single_node == NULL)
15239+
child_0->WantLockSizeOnce = child_1->WantLockSizeOnce = false;
15240+
15241+
const bool child_0_recurse = only_write_to_single_node ? child_0_is_toward_single_node : child_0->IsVisible;
15242+
const bool child_1_recurse = only_write_to_single_node ? child_1_is_toward_single_node : child_1->IsVisible;
15243+
if (child_0_recurse)
1523615244
DockNodeTreeUpdatePosSize(child_0, child_0_pos, child_0_size);
15237-
if (child_1->IsVisible)
15245+
if (child_1_recurse)
1523815246
DockNodeTreeUpdatePosSize(child_1, child_1_pos, child_1_size);
1523915247
}
1524015248

@@ -16048,16 +16056,11 @@ static ImGuiDockNode* ImGui::DockContextBindNodeToWindow(ImGuiContext* ctx, ImGu
1604816056
if (!node->IsVisible)
1604916057
{
1605016058
ImGuiDockNode* ancestor_node = node;
16051-
while (!ancestor_node->IsVisible)
16052-
{
16053-
ancestor_node->IsVisible = true;
16054-
ancestor_node->MarkedForPosSizeWrite = true;
16055-
if (ancestor_node->ParentNode)
16056-
ancestor_node = ancestor_node->ParentNode;
16057-
}
16059+
while (!ancestor_node->IsVisible && ancestor_node->ParentNode)
16060+
ancestor_node = ancestor_node->ParentNode;
1605816061
IM_ASSERT(ancestor_node->Size.x > 0.0f && ancestor_node->Size.y > 0.0f);
1605916062
DockNodeUpdateHasCentralNodeChild(DockNodeGetRootNode(ancestor_node));
16060-
DockNodeTreeUpdatePosSize(ancestor_node, ancestor_node->Pos, ancestor_node->Size, true);
16063+
DockNodeTreeUpdatePosSize(ancestor_node, ancestor_node->Pos, ancestor_node->Size, node);
1606116064
}
1606216065

1606316066
// Add window to node

imgui_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1457,7 +1457,6 @@ struct IMGUI_API ImGuiDockNode
14571457
bool WantMouseMove :1; // After a node extraction we need to transition toward moving the newly created host window
14581458
bool WantHiddenTabBarUpdate :1;
14591459
bool WantHiddenTabBarToggle :1;
1460-
bool MarkedForPosSizeWrite :1; // Update by DockNodeTreeUpdatePosSize() write-filtering
14611460

14621461
ImGuiDockNode(ImGuiID id);
14631462
~ImGuiDockNode();
@@ -2837,6 +2836,7 @@ namespace ImGui
28372836
IMGUI_API bool DockNodeBeginAmendTabBar(ImGuiDockNode* node);
28382837
IMGUI_API void DockNodeEndAmendTabBar();
28392838
inline ImGuiDockNode* DockNodeGetRootNode(ImGuiDockNode* node) { while (node->ParentNode) node = node->ParentNode; return node; }
2839+
inline bool DockNodeIsInHierarchyOf(ImGuiDockNode* node, ImGuiDockNode* parent) { while (node) { if (node == parent) return true; node = node->ParentNode; } return false; }
28402840
inline int DockNodeGetDepth(const ImGuiDockNode* node) { int depth = 0; while (node->ParentNode) { node = node->ParentNode; depth++; } return depth; }
28412841
inline ImGuiID DockNodeGetWindowMenuButtonId(const ImGuiDockNode* node) { return ImHashStr("#COLLAPSE", 0, node->ID); }
28422842
inline ImGuiDockNode* GetWindowDockNode() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DockNode; }

0 commit comments

Comments
 (0)