mirror of
https://github.com/ocornut/imgui.git
synced 2024-11-27 16:29:02 +08:00
Nav: Child window is restored on focus when returning to layer 0 or refocusing. This is a little experimental and potentially error-prone right now. (#787, vaguely relate to ~#727) Ideally we should maintain a non-sorted last-focused list that include childs windows.
This commit is contained in:
parent
7b22a91578
commit
bdd868704f
1
TODO.txt
1
TODO.txt
@ -230,7 +230,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- font: (api breaking) removed "TTF" from symbol names. also because it now supports OTF.
|
||||
|
||||
- nav: integrate navigation branch into master. (#787)
|
||||
- nav: Menu/Esc on a menu restore layer 0 but lose child window position.
|
||||
- nav: Esc on a flattened child
|
||||
- nav: menus: allow pressing Menu to leave a sub-menu.
|
||||
- nav: integrate/design keyboard controls.
|
||||
|
46
imgui.cpp
46
imgui.cpp
@ -1919,6 +1919,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name)
|
||||
NavRootWindow = NULL;
|
||||
NavLastIds[0] = NavLastIds[1] = 0;
|
||||
NavRectRel[0] = NavRectRel[1] = ImRect();
|
||||
NavLastChildNavWindow = NULL;
|
||||
|
||||
FocusIdxAllCounter = FocusIdxTabCounter = -1;
|
||||
FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX;
|
||||
@ -1983,7 +1984,7 @@ static void SetNavID(ImGuiID id, int nav_layer)
|
||||
IM_ASSERT(g.NavWindow);
|
||||
IM_ASSERT(nav_layer == 0 || nav_layer == 1);
|
||||
g.NavId = id;
|
||||
g.NavWindow->NavLastIds[nav_layer] = g.NavId;
|
||||
g.NavWindow->NavLastIds[nav_layer] = id;
|
||||
}
|
||||
|
||||
static void SetNavIDAndMoveMouse(ImGuiID id, int nav_layer, const ImRect& rect_rel)
|
||||
@ -2248,10 +2249,22 @@ static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand)
|
||||
return new_best;
|
||||
}
|
||||
|
||||
// Call when we are expected to land on Layer 0 after FocusWindow()
|
||||
static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window)
|
||||
{
|
||||
ImGuiWindow* child_window = window->NavLastChildNavWindow;
|
||||
if (child_window == NULL)
|
||||
return window;
|
||||
window->NavLastChildNavWindow = NULL;
|
||||
return child_window;
|
||||
}
|
||||
|
||||
static void NavRestoreLayer(int layer)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
g.NavLayer = layer;
|
||||
if (layer == 0)
|
||||
g.NavWindow = NavRestoreLastChildNavWindow(g.NavWindow);
|
||||
if (layer == 0 && g.NavWindow->NavLastIds[0] != 0)
|
||||
SetNavIDAndMoveMouse(g.NavWindow->NavLastIds[0], layer, g.NavWindow->NavRectRel[0]);
|
||||
else
|
||||
@ -2819,6 +2832,7 @@ static void ImGui::NavUpdateWindowing()
|
||||
{
|
||||
g.NavDisableHighlight = false;
|
||||
g.NavDisableMouseHover = true;
|
||||
apply_focus_window = NavRestoreLastChildNavWindow(apply_focus_window);
|
||||
FocusWindow(apply_focus_window);
|
||||
if (apply_focus_window->NavLastIds[0] == 0)
|
||||
NavInitWindow(apply_focus_window, false);
|
||||
@ -2833,8 +2847,14 @@ static void ImGui::NavUpdateWindowing()
|
||||
// Apply menu/layer toggle
|
||||
if (apply_toggle_layer && g.NavWindow)
|
||||
{
|
||||
// FIXME-NAV: Iterate parent windows to find first one with an active menu layer, instead of aiming at root window immediately
|
||||
if ((g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) == 0 && (g.NavWindow->RootWindow->DC.NavLayerActiveMask & (1 << 1)) != 0)
|
||||
FocusWindow(g.NavWindow->RootWindow);
|
||||
{
|
||||
ImGuiWindow* old_nav_window = g.NavWindow;
|
||||
ImGuiWindow* new_nav_window = g.NavWindow->RootWindow;
|
||||
FocusWindow(new_nav_window);
|
||||
new_nav_window->NavLastChildNavWindow = old_nav_window;
|
||||
}
|
||||
g.NavDisableHighlight = false;
|
||||
g.NavDisableMouseHover = true;
|
||||
NavRestoreLayer((g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) ? (g.NavLayer ^ 1) : 0);
|
||||
@ -2945,6 +2965,12 @@ static void ImGui::NavUpdate()
|
||||
g.NavJustTabbedId = 0;
|
||||
IM_ASSERT(g.NavLayer == 0 || g.NavLayer == 1);
|
||||
|
||||
// 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 && g.NavWindow != g.NavWindow->RootWindow)
|
||||
g.NavWindow->RootWindow->NavLastChildNavWindow = g.NavWindow;
|
||||
if (g.NavWindow && g.NavWindow->NavLastChildNavWindow != NULL && g.NavLayer == 0)
|
||||
g.NavWindow->NavLastChildNavWindow = NULL;
|
||||
|
||||
NavUpdateWindowing();
|
||||
|
||||
// Set output flags for user application
|
||||
@ -4731,10 +4757,10 @@ static ImGuiWindow* GetFrontMostModalRootWindow()
|
||||
static void ClosePopupToLevel(int remaining)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (remaining > 0)
|
||||
ImGui::FocusWindow(g.OpenPopupStack[remaining-1].Window);
|
||||
else
|
||||
ImGui::FocusWindow(g.OpenPopupStack[0].ParentWindow);
|
||||
ImGuiWindow* focus_window = (remaining > 0) ? g.OpenPopupStack[remaining-1].Window : g.OpenPopupStack[0].ParentWindow;
|
||||
if (g.NavLayer == 0)
|
||||
focus_window = NavRestoreLastChildNavWindow(focus_window);
|
||||
ImGui::FocusWindow(focus_window);
|
||||
g.OpenPopupStack.resize(remaining);
|
||||
}
|
||||
|
||||
@ -6210,9 +6236,11 @@ void ImGui::FocusWindow(ImGuiWindow* window)
|
||||
g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId
|
||||
g.NavIdIsAlive = false;
|
||||
g.NavLayer = 0;
|
||||
g.NavWindow = window;
|
||||
if (window && g.NavDisableMouseHover)
|
||||
g.NavMousePosDirty = true;
|
||||
g.NavWindow = window;
|
||||
if (window && window->NavLastChildNavWindow != NULL)
|
||||
window->NavLastChildNavWindow = NULL;
|
||||
}
|
||||
|
||||
// Passing NULL allow to disable keyboard focus
|
||||
@ -6239,7 +6267,8 @@ void ImGui::FocusFrontMostActiveWindow(ImGuiWindow* ignore_window)
|
||||
for (int i = g.Windows.Size - 1; i >= 0; i--)
|
||||
if (g.Windows[i] != ignore_window && g.Windows[i]->WasActive && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow))
|
||||
{
|
||||
FocusWindow(g.Windows[i]);
|
||||
ImGuiWindow* focus_window = NavRestoreLastChildNavWindow(g.Windows[i]);
|
||||
FocusWindow(focus_window);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -12994,6 +13023,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, GetScrollMaxX(window), window->Scroll.y, GetScrollMaxY(window));
|
||||
ImGui::BulletText("Active: %d, WriteAccessed: %d", window->Active, window->WriteAccessed);
|
||||
ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask);
|
||||
ImGui::BulletText("NavLastChildNavWindow: %s", window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL");
|
||||
ImGui::BulletText("NavRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRectRel[0].Min.x, window->NavRectRel[0].Min.y, window->NavRectRel[0].Max.x, window->NavRectRel[0].Max.y);
|
||||
if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow");
|
||||
if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows");
|
||||
|
@ -940,6 +940,7 @@ struct IMGUI_API ImGuiWindow
|
||||
ImGuiWindow* RootNonPopupWindow; // Generally point to ourself. Used to display TitleBgActive color and for selecting which window to use for NavWindowing
|
||||
|
||||
ImGuiWindow* NavRootWindow; // Generally point to ourself. If we are a child window with the NavFlattened flag, point to a parent window.
|
||||
ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.)
|
||||
ImGuiID NavLastIds[2]; // Last known NavId for this window, per layer (0/1)
|
||||
ImRect NavRectRel[2]; // Reference rectangle, in window relative space
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user