From 615e9ae34537df5324df2f71253eafd887a848d1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 18 May 2020 15:08:47 +0200 Subject: [PATCH] Docking: Fix undocking (#3243), amend 7b3d3798 (#1738) --- imgui.cpp | 13 +++++++++---- imgui_widgets.cpp | 5 +++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 31b5e10e9..bec674135 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6796,9 +6796,14 @@ void ImGui::FocusWindow(ImGuiWindow* window) IM_ASSERT(window == NULL || window->RootWindow != NULL); ImGuiWindow* focus_front_window = window ? window->RootWindowDockStop : NULL; ImGuiWindow* display_front_window = window ? window->RootWindow : NULL; + ImGuiDockNode* dock_node = window ? window->DockNode : NULL; + bool active_id_window_is_dock_node_host = (g.ActiveIdWindow && dock_node && dock_node->HostWindow == g.ActiveIdWindow); - // Steal focus on active widgets - if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindowDockStop != focus_front_window) + // Steal active widgets. Some of the cases it triggers includes: + // - Focus a window while an InputText in another window is active, if focus happens before the old InputText can run. + // - When using Nav to activate menu items (due to timing of activating on press->new window appears->losing ActiveId) + // - Using dock host items (tab, collapse button) can trigger this before we redirect the ActiveIdWindow toward the child window. + if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindowDockStop != focus_front_window && !active_id_window_is_dock_node_host) ClearActiveID(); // Passing NULL allow to disable keyboard focus @@ -6807,8 +6812,8 @@ void ImGui::FocusWindow(ImGuiWindow* window) window->LastFrameJustFocused = g.FrameCount; // Select in dock node - if (window->DockNode && window->DockNode->TabBar) - window->DockNode->TabBar->SelectedTabId = window->DockNode->TabBar->NextSelectedTabId = window->ID; + if (dock_node && dock_node->TabBar) + dock_node->TabBar->SelectedTabId = dock_node->TabBar->NextSelectedTabId = window->ID; // Bring to front BringWindowToFocusFront(focus_front_window); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 74df48655..2c1c04e1d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7289,6 +7289,11 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, tab_bar->NextSelectedTabId = id; hovered |= (g.HoveredId == id); + // Transfer active id window so the active id is not owned by the dock host (as StartMouseMovingWindow() + // will only do it on the drag). This allows FocusWindow() to be more conservative in how it clears active id. + if (held && docked_window && g.ActiveId == id && g.ActiveIdIsJustActivated) + g.ActiveIdWindow = docked_window; + // Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered) if (!held) SetItemAllowOverlap();