Docking: Revised undocking logic to reduce accidental whole-node undocking:

Amend bb2aa5e77.
Revert to normal threshold in StartMouseMovingWindowOrNode().
Added tooltip when hovering the collapse/window menu button.
features/sdl_renderer3_multiviewports
ocornut ago%!(EXTRA string=2 years)
parent 4521dec85d
commit 51d1a72e9b
  1. 8
      docs/CHANGELOG.txt
  2. 28
      imgui.cpp
  3. 3
      imgui_internal.h
  4. 2
      imgui_widgets.cpp

@ -157,6 +157,14 @@ Docking+Viewports Branch:
- Viewports: Fixed window inner clipping rectangle off by one when window is located on a monitor
with negative coordinates. While it is expected that other small issues with arise from this
situation, at the moment we are fixing the most noticeable one. (#6861, #2884) [@Vuhdo, @alektron]
- Docking: revised undocking to reduce accidental whole-node undocking:
- cannot undock a whole node by dragging from empty space in tab-bar.
- can undock whole node by dragging from window/collapse menu button.
- can undock single window by dragging from its tab.
- can still move (but not undock) whole node or whole hierarchy when node is part of a
floating hierarchy.
- added tooltip when hovering the collapse/window menu button, to faciliate understanding
that whole dock node may be undocked or grabbed from here.
- Docking: Fixed an issue leading to incorrect restoration of selected tab in dock nodes that
don't carry the currently focused window. (#2304)
- Docking: added ImGuiDockNodeFlags_NoUndocking. (#2999, #6823, #6780, #3492)

@ -3657,7 +3657,8 @@ static const ImGuiLocEntry GLocalizationEntriesEnUS[] =
{ ImGuiLocKey_WindowingPopup, "(Popup)" },
{ ImGuiLocKey_WindowingUntitled, "(Untitled)" },
{ ImGuiLocKey_DockingHideTabBar, "Hide tab bar###HideTabBar" },
{ ImGuiLocKey_DockingHoldShiftToDock, "Hold SHIFT to enable Docking window."},
{ ImGuiLocKey_DockingHoldShiftToDock, "Hold SHIFT to enable Docking window." },
{ ImGuiLocKey_DockingDragToUndockOrMoveNode,"Click and drag to move or undock whole node." },
};
void ImGui::Initialize()
@ -4489,26 +4490,23 @@ void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
g.MovingWindow = window;
}
// We use 'undock_floating_node == false' when dragging from title bar to allow moving groups of floating nodes without undocking them.
// - undock_floating_node == true: when dragging from a floating node within a hierarchy, always undock the node.
// - undock_floating_node == false: when dragging from a floating node within a hierarchy, move root window.
void ImGui::StartMouseMovingWindowOrNode(ImGuiWindow* window, ImGuiDockNode* node, bool undock_floating_node)
// We use 'undock == false' when dragging from title bar to allow moving groups of floating nodes without undocking them.
void ImGui::StartMouseMovingWindowOrNode(ImGuiWindow* window, ImGuiDockNode* node, bool undock)
{
ImGuiContext& g = *GImGui;
bool can_undock_node = false;
if (node != NULL && node->VisibleWindow && (node->VisibleWindow->Flags & ImGuiWindowFlags_NoMove) == 0 && (node->MergedFlags & ImGuiDockNodeFlags_NoUndocking) == 0)
if (undock && node != NULL && node->VisibleWindow && (node->VisibleWindow->Flags & ImGuiWindowFlags_NoMove) == 0 && (node->MergedFlags & ImGuiDockNodeFlags_NoUndocking) == 0)
{
// Can undock if:
// - part of a floating node hierarchy with more than one visible node (if only one is visible, we'll just move the whole hierarchy)
// - part of a dockspace node hierarchy (trivia: undocking from a fixed/central node will create a new node and copy windows)
// - part of a hierarchy with more than one visible node (if only one is visible, we'll just move the root window)
// - part of a dockspace node hierarchy: so we can undock the last single visible node too (trivia: undocking from a fixed/central node will create a new node and copy windows)
ImGuiDockNode* root_node = DockNodeGetRootNode(node);
if (root_node->OnlyNodeWithWindows != node || root_node->CentralNode != NULL) // -V1051 PVS-Studio thinks node should be root_node and is wrong about that.
if (undock_floating_node || root_node->IsDockSpace())
can_undock_node = true;
can_undock_node = true;
}
const bool clicked = IsMouseClicked(0);
const bool dragging = IsMouseDragging(0, g.IO.MouseDragThreshold * 1.70f);
const bool dragging = IsMouseDragging(0);
if (can_undock_node && dragging)
DockContextQueueUndockNode(&g, node); // Will lead to DockNodeStartMouseMovingWindow() -> StartMouseMovingWindow() being called next frame
else if (!can_undock_node && (clicked || dragging) && g.MovingWindow != window)
@ -6445,7 +6443,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
if (ButtonBehavior(r, unhide_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren))
node->WantHiddenTabBarToggle = true;
else if (held && IsMouseDragging(0))
StartMouseMovingWindowOrNode(window, node, true);
StartMouseMovingWindowOrNode(window, node, true); // Undock from tab-bar triangle = same as window/collapse menu button
// FIXME-DOCK: Ideally we'd use ImGuiCol_TitleBgActive/ImGuiCol_TitleBg here, but neither is guaranteed to be visible enough at this sort of size..
ImU32 col = GetColorU32(((held && hovered) || (node->IsFocused && !hovered)) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
@ -16887,6 +16885,8 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
OpenPopup("#WindowMenu");
if (IsItemActive())
focus_tab_id = tab_bar->SelectedTabId;
if (IsItemHovered(ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_DelayNormal) && g.HoveredIdTimer > 0.5f)
SetTooltip("%s", LocalizeGetMsg(ImGuiLocKey_DockingDragToUndockOrMoveNode));
}
// If multiple tabs are appearing on the same frame, sort them based on their persistent DockOrder value
@ -17015,7 +17015,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
ImGuiID title_bar_id = host_window->GetID("#TITLEBAR");
if (g.HoveredId == 0 || g.HoveredId == title_bar_id || g.ActiveId == title_bar_id)
{
// AllowItem mode required for appending into dock node tab bar,
// AllowOverlap mode required for appending into dock node tab bar,
// otherwise dragging window will steal HoveredId and amended tabs cannot get them.
bool held;
KeepAliveID(title_bar_id);
@ -17031,7 +17031,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
// Forward moving request to selected window
if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
StartMouseMovingWindowOrNode(tab->Window ? tab->Window : node->HostWindow, node, false);
StartMouseMovingWindowOrNode(tab->Window ? tab->Window : node->HostWindow, node, false); // Undock from tab bar empty space
}
}

@ -1929,6 +1929,7 @@ enum ImGuiLocKey : int
ImGuiLocKey_WindowingUntitled,
ImGuiLocKey_DockingHideTabBar,
ImGuiLocKey_DockingHoldShiftToDock,
ImGuiLocKey_DockingDragToUndockOrMoveNode,
ImGuiLocKey_COUNT
};
@ -3162,7 +3163,7 @@ namespace ImGui
IMGUI_API void UpdateInputEvents(bool trickle_fast_inputs);
IMGUI_API void UpdateHoveredWindowAndCaptureFlags();
IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window);
IMGUI_API void StartMouseMovingWindowOrNode(ImGuiWindow* window, ImGuiDockNode* node, bool undock_floating_node);
IMGUI_API void StartMouseMovingWindowOrNode(ImGuiWindow* window, ImGuiDockNode* node, bool undock);
IMGUI_API void UpdateMouseMovingWindowNewFrame();
IMGUI_API void UpdateMouseMovingWindowEndFrame();

@ -862,7 +862,7 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos, ImGuiDockNode* dock_no
// Switch to moving the window after mouse is moved beyond the initial drag threshold
if (IsItemActive() && IsMouseDragging(0))
StartMouseMovingWindowOrNode(window, dock_node, true);
StartMouseMovingWindowOrNode(window, dock_node, true); // Undock from window/collapse menu button
return pressed;
}

Loading…
Cancel
Save