From 47579f8a406eef3b63bd2c85588976c29ac731bd Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 23 May 2023 16:26:52 +0200 Subject: [PATCH] Nav: set NavJustMovedToXXX fields on NavInit result + BeginChild() clears ActiveId on N+1 on entering instead of waiting for ID to elapse on N+2. # Conflicts: # imgui_internal.h --- imgui.cpp | 38 +++++++++++++++++++++++--------------- imgui_internal.h | 4 +--- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c74abe6a6..d947a6567 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5322,11 +5322,14 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b // Process navigation-in immediately so NavInit can run on first frame // Can enter a child if (A) it has navigatable items or (B) it can be scrolled. + const ImGuiID temp_id_for_activation = (id + 1); + if (g.ActiveId == temp_id_for_activation) + ClearActiveID(); if (g.NavActivateId == id && !(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY)) { FocusWindow(child_window); NavInitWindow(child_window, false); - SetActiveID(id + 1, child_window); // Steal ActiveId with another arbitrary id so that key-press won't activate child item + SetActiveID(temp_id_for_activation, child_window); // Steal ActiveId with another arbitrary id so that key-press won't activate child item g.ActiveIdSource = g.NavInputSource; } return ret; @@ -7583,12 +7586,11 @@ void ImGui::SetItemDefaultFocus() ImGuiWindow* window = g.CurrentWindow; if (!window->Appearing) return; - if (g.NavWindow != window->RootWindowForNav || (!g.NavInitRequest && g.NavInitResultId == 0) || g.NavLayer != window->DC.NavLayerCurrent) + if (g.NavWindow != window->RootWindowForNav || (!g.NavInitRequest && g.NavInitResult.ID == 0) || g.NavLayer != window->DC.NavLayerCurrent) return; g.NavInitRequest = false; - g.NavInitResultId = g.LastItemData.ID; - g.NavInitResultRectRel = WindowRectAbsToRel(window, g.LastItemData.Rect); + NavApplyItemToResult(&g.NavInitResult); NavUpdateAnyRequestFlag(); // Scroll could be done in NavInitRequestApplyResult() via an opt-in flag (we however don't want regular init requests to scroll) @@ -10879,10 +10881,9 @@ static void ImGui::NavProcessItem() { // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback const bool candidate_for_nav_default_focus = (item_flags & ImGuiItemFlags_NoNavDefaultFocus) == 0; - if (candidate_for_nav_default_focus || g.NavInitResultId == 0) + if (candidate_for_nav_default_focus || g.NavInitResult.ID == 0) { - g.NavInitResultId = id; - g.NavInitResultRectRel = WindowRectAbsToRel(window, nav_bb); + NavApplyItemToResult(&g.NavInitResult); } if (candidate_for_nav_default_focus) { @@ -11140,8 +11141,7 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit) SetNavID(0, g.NavLayer, window->NavRootFocusScopeId, ImRect()); g.NavInitRequest = true; g.NavInitRequestFromMove = false; - g.NavInitResultId = 0; - g.NavInitResultRectRel = ImRect(); + g.NavInitResult.ID = 0; NavUpdateAnyRequestFlag(); } else @@ -11226,12 +11226,12 @@ static void ImGui::NavUpdate() g.NavInputSource = ImGuiInputSource_Keyboard; // Process navigation init request (select first/default focus) - if (g.NavInitResultId != 0) + g.NavJustMovedToId = 0; + if (g.NavInitResult.ID != 0) NavInitRequestApplyResult(); g.NavInitRequest = false; g.NavInitRequestFromMove = false; - g.NavInitResultId = 0; - g.NavJustMovedToId = 0; + g.NavInitResult.ID = 0; // Process navigation move request if (g.NavMoveSubmitted) @@ -11371,10 +11371,18 @@ void ImGui::NavInitRequestApplyResult() if (!g.NavWindow) return; + ImGuiNavItemData* result = &g.NavInitResult; + if (g.NavId != result->ID) + { + g.NavJustMovedToId = result->ID; + g.NavJustMovedToFocusScopeId = result->FocusScopeId; + g.NavJustMovedToKeyMods = 0; + } + // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called) // FIXME-NAV: On _NavFlattened windows, g.NavWindow will only be updated during subsequent frame. Not a problem currently. - IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: ApplyResult: NavID 0x%08X in Layer %d Window \"%s\"\n", g.NavInitResultId, g.NavLayer, g.NavWindow->Name); - SetNavID(g.NavInitResultId, g.NavLayer, 0, g.NavInitResultRectRel); + IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: ApplyResult: NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID, g.NavLayer, g.NavWindow->Name); + SetNavID(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel); g.NavIdIsAlive = true; // Mark as alive from previous frame as we got a result if (g.NavInitRequestFromMove) NavRestoreHighlightAfterMove(); @@ -11473,7 +11481,7 @@ void ImGui::NavUpdateCreateMoveRequest() { IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", window ? window->Name : "", g.NavLayer); g.NavInitRequest = g.NavInitRequestFromMove = true; - g.NavInitResultId = 0; + g.NavInitResult.ID = 0; g.NavDisableHighlight = false; } diff --git a/imgui_internal.h b/imgui_internal.h index 6da5a4750..75dae0cf2 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1881,8 +1881,7 @@ struct ImGuiContext bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd() bool NavInitRequest; // Init request for appearing window to select first item bool NavInitRequestFromMove; - ImGuiID NavInitResultId; // Init request result (first item of the window, or one for which SetItemDefaultFocus() was called) - ImRect NavInitResultRectRel; // Init request result rectangle (relative to parent window) + ImGuiNavItemData NavInitResult; // Init request result (first item of the window, or one for which SetItemDefaultFocus() was called) bool NavMoveSubmitted; // Move request submitted, will process result on next NewFrame() bool NavMoveScoringItems; // Move request submitted, still scoring incoming items bool NavMoveForwardToNextFrame; @@ -2121,7 +2120,6 @@ struct ImGuiContext NavAnyRequest = false; NavInitRequest = false; NavInitRequestFromMove = false; - NavInitResultId = 0; NavMoveSubmitted = false; NavMoveScoringItems = false; NavMoveForwardToNextFrame = false;