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
This commit is contained in:
ocornut 2023-05-23 16:26:52 +02:00
parent 52e19113f3
commit 47579f8a40
2 changed files with 24 additions and 18 deletions

View File

@ -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 // 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. // 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)) if (g.NavActivateId == id && !(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY))
{ {
FocusWindow(child_window); FocusWindow(child_window);
NavInitWindow(child_window, false); 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; g.ActiveIdSource = g.NavInputSource;
} }
return ret; return ret;
@ -7583,12 +7586,11 @@ void ImGui::SetItemDefaultFocus()
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
if (!window->Appearing) if (!window->Appearing)
return; 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; return;
g.NavInitRequest = false; g.NavInitRequest = false;
g.NavInitResultId = g.LastItemData.ID; NavApplyItemToResult(&g.NavInitResult);
g.NavInitResultRectRel = WindowRectAbsToRel(window, g.LastItemData.Rect);
NavUpdateAnyRequestFlag(); NavUpdateAnyRequestFlag();
// Scroll could be done in NavInitRequestApplyResult() via an opt-in flag (we however don't want regular init requests to scroll) // 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 // 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; 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; NavApplyItemToResult(&g.NavInitResult);
g.NavInitResultRectRel = WindowRectAbsToRel(window, nav_bb);
} }
if (candidate_for_nav_default_focus) 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()); SetNavID(0, g.NavLayer, window->NavRootFocusScopeId, ImRect());
g.NavInitRequest = true; g.NavInitRequest = true;
g.NavInitRequestFromMove = false; g.NavInitRequestFromMove = false;
g.NavInitResultId = 0; g.NavInitResult.ID = 0;
g.NavInitResultRectRel = ImRect();
NavUpdateAnyRequestFlag(); NavUpdateAnyRequestFlag();
} }
else else
@ -11226,12 +11226,12 @@ static void ImGui::NavUpdate()
g.NavInputSource = ImGuiInputSource_Keyboard; g.NavInputSource = ImGuiInputSource_Keyboard;
// Process navigation init request (select first/default focus) // Process navigation init request (select first/default focus)
if (g.NavInitResultId != 0) g.NavJustMovedToId = 0;
if (g.NavInitResult.ID != 0)
NavInitRequestApplyResult(); NavInitRequestApplyResult();
g.NavInitRequest = false; g.NavInitRequest = false;
g.NavInitRequestFromMove = false; g.NavInitRequestFromMove = false;
g.NavInitResultId = 0; g.NavInitResult.ID = 0;
g.NavJustMovedToId = 0;
// Process navigation move request // Process navigation move request
if (g.NavMoveSubmitted) if (g.NavMoveSubmitted)
@ -11371,10 +11371,18 @@ void ImGui::NavInitRequestApplyResult()
if (!g.NavWindow) if (!g.NavWindow)
return; 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) // 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. // 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); IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: ApplyResult: NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID, g.NavLayer, g.NavWindow->Name);
SetNavID(g.NavInitResultId, g.NavLayer, 0, g.NavInitResultRectRel); SetNavID(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel);
g.NavIdIsAlive = true; // Mark as alive from previous frame as we got a result g.NavIdIsAlive = true; // Mark as alive from previous frame as we got a result
if (g.NavInitRequestFromMove) if (g.NavInitRequestFromMove)
NavRestoreHighlightAfterMove(); NavRestoreHighlightAfterMove();
@ -11473,7 +11481,7 @@ void ImGui::NavUpdateCreateMoveRequest()
{ {
IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", window ? window->Name : "<NULL>", g.NavLayer); IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", window ? window->Name : "<NULL>", g.NavLayer);
g.NavInitRequest = g.NavInitRequestFromMove = true; g.NavInitRequest = g.NavInitRequestFromMove = true;
g.NavInitResultId = 0; g.NavInitResult.ID = 0;
g.NavDisableHighlight = false; g.NavDisableHighlight = false;
} }

View File

@ -1881,8 +1881,7 @@ struct ImGuiContext
bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd() bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd()
bool NavInitRequest; // Init request for appearing window to select first item bool NavInitRequest; // Init request for appearing window to select first item
bool NavInitRequestFromMove; bool NavInitRequestFromMove;
ImGuiID NavInitResultId; // Init request result (first item of the window, or one for which SetItemDefaultFocus() was called) ImGuiNavItemData NavInitResult; // 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)
bool NavMoveSubmitted; // Move request submitted, will process result on next NewFrame() bool NavMoveSubmitted; // Move request submitted, will process result on next NewFrame()
bool NavMoveScoringItems; // Move request submitted, still scoring incoming items bool NavMoveScoringItems; // Move request submitted, still scoring incoming items
bool NavMoveForwardToNextFrame; bool NavMoveForwardToNextFrame;
@ -2121,7 +2120,6 @@ struct ImGuiContext
NavAnyRequest = false; NavAnyRequest = false;
NavInitRequest = false; NavInitRequest = false;
NavInitRequestFromMove = false; NavInitRequestFromMove = false;
NavInitResultId = 0;
NavMoveSubmitted = false; NavMoveSubmitted = false;
NavMoveScoringItems = false; NavMoveScoringItems = false;
NavMoveForwardToNextFrame = false; NavMoveForwardToNextFrame = false;