Shortcut()/SetShortcutRouting(): focus route testing now use ParentWindowForFocusRoute. Automatically set on child-window, manually configurable otherwise. (#6798, #2637, #456)

This commit is contained in:
ocornut 2024-01-15 14:18:10 +01:00
parent 4b20a0217e
commit e0c8c80ada
2 changed files with 15 additions and 12 deletions

View File

@ -6432,13 +6432,18 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
{
UpdateWindowParentAndRootLinks(window, flags, parent_window);
window->ParentWindowInBeginStack = parent_window_in_stack;
// There's little point to expose a flag to set this: because the interesting cases won't be using parent_window_in_stack,
// e.g. linking a tool window in a standalone viewport to a document window, regardless of their Begin() stack parenting. (#6798)
window->ParentWindowForFocusRoute = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window_in_stack : NULL;
}
// Add to focus scope stack
// We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
if ((flags & ImGuiWindowFlags_NavFlattened) == 0)
PushFocusScope(window->ID);
window->NavRootFocusScopeId = g.CurrentFocusScopeId;
// We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
g.CurrentWindow = NULL;
// Add to popup stack
@ -8325,25 +8330,19 @@ static int CalcRoutingScore(ImGuiWindow* location, ImGuiID owner_id, ImGuiInputF
if (owner_id != 0 && g.ActiveId == owner_id)
return 1;
// Early out when not in focus stack
if (focused == NULL || focused->RootWindow != location->RootWindow)
return 255;
// Score based on distance to focused window (lower is better)
// Assuming both windows are submitting a routing request,
// - When Window....... is focused -> Window scores 3 (best), Window/ChildB scores 255 (no match)
// - When Window/ChildB is focused -> Window scores 4, Window/ChildB scores 3 (best)
// Assuming only WindowA is submitting a routing request,
// - When Window/ChildB is focused -> Window scores 4 (best), Window/ChildB doesn't have a score.
for (int next_score = 3; focused != NULL; next_score++)
{
// FIXME: This could be later abstracted as a focus path
for (int next_score = 3; focused != NULL; next_score++, focused = focused->ParentWindowForFocusRoute)
if (focused == location)
{
IM_ASSERT(next_score < 255);
return next_score;
}
focused = (focused->RootWindow != focused) ? focused->ParentWindow : NULL; // FIXME: This could be later abstracted as a focus path
}
return 255;
}
@ -10780,6 +10779,8 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags flags)
if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display)
EndPopup();
//g.CurrentWindow->FocusRouteParentWindow = g.CurrentWindow->ParentWindowInBeginStack;
return is_open;
}
@ -14995,9 +14996,10 @@ void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label)
for (int layer = 0; layer < ImGuiNavLayer_COUNT; layer++)
BulletText("NavPreferredScoringPosRel[%d] = {%.1f,%.1f)", layer, (pr[layer].x == FLT_MAX ? -99999.0f : pr[layer].x), (pr[layer].y == FLT_MAX ? -99999.0f : pr[layer].y)); // Display as 99999.0f so it looks neater.
BulletText("NavLayersActiveMask: %X, NavLastChildNavWindow: %s", window->DC.NavLayersActiveMask, window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL");
if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow, "RootWindow"); }
if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow, "ParentWindow"); }
if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows, "ChildWindows"); }
if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow, "RootWindow"); }
if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow, "ParentWindow"); }
if (window->ParentWindowForFocusRoute != NULL) { DebugNodeWindow(window->ParentWindowForFocusRoute, "ParentWindowForFocusRoute"); }
if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows, "ChildWindows"); }
if (window->ColumnsStorage.Size > 0 && TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size))
{
for (ImGuiOldColumns& columns : window->ColumnsStorage)

View File

@ -2538,6 +2538,7 @@ struct IMGUI_API ImGuiWindow
ImGuiWindow* RootWindowPopupTree; // Point to ourself or first ancestor that is not a child window. Cross through popups parent<>child.
ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active.
ImGuiWindow* RootWindowForNav; // Point to ourself or first ancestor which doesn't have the NavFlattened flag.
ImGuiWindow* ParentWindowForFocusRoute; // Set to manual link a window to its logical parent so that Shortcut() chain are honoerd (e.g. Tool linked to Document)
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[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1)