Docking: Fixed focus restore lagging by a frame when a tab stops being submitted. (#2109) Building on a little build of technical debt there, should transition toward a more general docking-agnostic system (#2304)

This commit is contained in:
omar 2019-03-28 18:43:27 +01:00
parent 5af385ea78
commit 9bf6509c6e
4 changed files with 32 additions and 7 deletions

View File

@ -9,6 +9,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- doc/test: checklist app to verify binding/integration of imgui (test inputs, rendering, callback, etc.).
- doc/tips: tips of the day: website? applet in imgui_club?
- window: preserve/restore relative focus ordering (persistent or not) (#2304) -> also see docking reference to same #.
- window: calling SetNextWindowSize() every frame with <= 0 doesn't do anything, may be useful to allow (particularly when used for a single axis). (#690)
- window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list. perhaps a lightweight explicit cleanup pass.
- window: auto-fit feedback loop when user relies on any dynamic layout (window width multiplier, column) appears weird to end-user. clarify.
@ -130,6 +131,8 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- splitter/separator: formalize the splitter idiom into an official api (we want to handle n-way split) (#319)
- dock: merge docking branch (#2109)
- dock: B: ordering currently held in tab bar should be implicitly held by windows themselves (also see #2304)
- dock: B- tab bar: the order/focus restoring code could be part of TabBar and not DockNode? (#8)
- dock: B~ rework code to be able to lazily create tab bar instance in a single place. The _Unsorted tab flag could be replacing a trailing-counter in DockNode?
- dock: B~ fully track windows/settings reference in dock nodes. perhaps find a representation that allows facilitate use of dock builder functions.
- dock: B~ Unreal style document system (requires low-level controls of dockspace serialization fork/copy/delete). this is mostly working but the DockBuilderXXX api are not exposed/finished.
@ -148,7 +151,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- dock: B- dpi: look at interaction with the hi-dpi and multi-dpi stuff.
- dock: B- tab bar: appearing on first frame with a dumb layout would do less harm that not appearing? (when behind dynamic branch) or store titles + render in EndTabBar()
- dock: B- tab bar: make selected tab always shows its full title?
- dock: B- tab bar: the order/focus restoring code could be part of TabBar and not DockNode? (#8)
- dock: B- nav: design interactions so nav controls can dock/undock
- dock: B- dockspace: flag to lock the dock tree and/or sizes (ImGuiDockNodeFlags_Locked?)
- dock: B- reintroduce collapsing a floating dock node. also collapsing a docked dock node!

View File

@ -1040,7 +1040,7 @@ static float NavUpdatePageUpPageDown(int allowed_dir_flags);
static inline void NavUpdateAnyRequestFlag();
static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, ImGuiID id);
static ImVec2 NavCalcPreferredRefPos();
static void NavSaveLastChildNavWindow(ImGuiWindow* nav_window);
static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window);
// Misc
@ -8143,7 +8143,9 @@ void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags mov
}
}
static void ImGui::NavSaveLastChildNavWindow(ImGuiWindow* nav_window)
// FIXME: This could be replaced by updating a frame number in each window when (window == NavWindow) and (NavLayer == 0).
// This way we could find the last focused window among our children. It would be much less confusing this way?
static void ImGui::NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window)
{
ImGuiWindow* parent_window = nav_window;
while (parent_window && (parent_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (parent_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
@ -8152,10 +8154,16 @@ static void ImGui::NavSaveLastChildNavWindow(ImGuiWindow* nav_window)
parent_window->NavLastChildNavWindow = nav_window;
}
// Call when we are expected to land on Layer 0 after FocusWindow()
// Restore the last focused child.
// Call when we are expected to land on the Main Layer (0) after FocusWindow()
static ImGuiWindow* ImGui::NavRestoreLastChildNavWindow(ImGuiWindow* window)
{
return window->NavLastChildNavWindow ? window->NavLastChildNavWindow : window;
if (window->NavLastChildNavWindow && window->NavLastChildNavWindow->WasActive)
return window->NavLastChildNavWindow;
if (window->DockNodeAsHost && window->DockNodeAsHost->TabBar)
if (ImGuiTabItem* tab = TabBarFindMostRecentlySelectedTabForActiveWindow(window->DockNodeAsHost->TabBar))
return tab->Window;
return window;
}
static void NavRestoreLayer(ImGuiNavLayer layer)
@ -8380,7 +8388,7 @@ static void ImGui::NavUpdate()
// Store our return window (for returning from Layer 1 to Layer 0) and clear it as soon as we step back in our own Layer 0
if (g.NavWindow)
NavSaveLastChildNavWindow(g.NavWindow);
NavSaveLastChildNavWindowIntoParent(g.NavWindow);
if (g.NavWindow && g.NavWindow->NavLastChildNavWindow != NULL && g.NavLayer == 0)
g.NavWindow->NavLastChildNavWindow = NULL;
@ -8833,7 +8841,7 @@ static void ImGui::NavUpdateWindowing()
// Move to parent menu if necessary
ImGuiWindow* new_nav_window = g.NavWindow;
while (new_nav_window->ParentWindow
&& (new_nav_window->DC.NavLayerActiveMask & (1 << 1)) == 0
&& (new_nav_window->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) == 0
&& (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0
&& (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
new_nav_window = new_nav_window->ParentWindow;

View File

@ -1707,6 +1707,7 @@ namespace ImGui
// Tab Bars
IMGUI_API bool BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags, ImGuiDockNode* dock_node);
IMGUI_API ImGuiTabItem* TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id);
IMGUI_API ImGuiTabItem* TabBarFindMostRecentlySelectedTabForActiveWindow(ImGuiTabBar* tab_bar);
IMGUI_API void TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiTabItemFlags tab_flags, ImGuiWindow* window);
IMGUI_API void TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id);
IMGUI_API void TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);

View File

@ -6455,6 +6455,20 @@ ImGuiTabItem* ImGui::TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id)
return NULL;
}
// FIXME: See references to #2304 in TODO.txt
ImGuiTabItem* ImGui::TabBarFindMostRecentlySelectedTabForActiveWindow(ImGuiTabBar* tab_bar)
{
ImGuiTabItem* most_recently_selected_tab = NULL;
for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
{
ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
if (most_recently_selected_tab == NULL || most_recently_selected_tab->LastFrameSelected < tab->LastFrameSelected)
if (tab->Window && tab->Window->WasActive)
most_recently_selected_tab = tab;
}
return most_recently_selected_tab;
}
// The purpose of this call is to register tab in advance so we can control their order at the time they appear.
// Otherwise calling this is unnecessary as tabs are appending as needed by the BeginTabItem() function.
void ImGui::TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiTabItemFlags tab_flags, ImGuiWindow* window)