From a735a8c0844c9278a1d97a12774c279c19f7ad62 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 1 Sep 2021 12:07:17 +0200 Subject: [PATCH] Nav: storing NavRect in LastItemData. Fix race condition where framed items (Rect != NavRect) calling SetFocusID() would store the wrong NavRectRel until next frame (haven't dugged in the possible side-effects of that race condition) --- imgui.cpp | 5 +++-- imgui_internal.h | 1 + imgui_widgets.cpp | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 196aa7b3..19fe3079 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7498,6 +7498,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu // (DisplayRect is left untouched, made valid when ImGuiItemStatusFlags_HasDisplayRect is set) g.LastItemData.ID = id; g.LastItemData.Rect = bb; + g.LastItemData.NavRect = nav_bb_arg ? *nav_bb_arg : bb; g.LastItemData.InFlags = g.CurrentItemFlags; g.LastItemData.StatusFlags = ImGuiItemStatusFlags_None; @@ -7517,7 +7518,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu if (g.NavId == id || g.NavAnyRequest) if (g.NavWindow->RootWindowForNav == window->RootWindowForNav) if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened)) - NavProcessItem(window, id, nav_bb_arg ? *nav_bb_arg : bb); + NavProcessItem(window, id, g.LastItemData.NavRect); // [DEBUG] Item Picker tool, when enabling the "extended" version we perform the check in ItemAdd() #ifdef IMGUI_DEBUG_TOOL_ITEM_PICKER_EX @@ -8710,7 +8711,7 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent; window->NavLastIds[nav_layer] = id; if (g.LastItemData.ID == id) - window->NavRectRel[nav_layer] = ImRect(g.LastItemData.Rect.Min - window->Pos, g.LastItemData.Rect.Max - window->Pos); + window->NavRectRel[nav_layer] = ImRect(g.LastItemData.NavRect.Min - window->Pos, g.LastItemData.NavRect.Max - window->Pos); if (g.ActiveIdSource == ImGuiInputSource_Nav) g.NavDisableMouseHover = true; diff --git a/imgui_internal.h b/imgui_internal.h index 94522e2c..ac58b6c7 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1124,6 +1124,7 @@ struct ImGuiLastItemData ImGuiItemFlags InFlags; // See ImGuiItemFlags_ ImGuiItemStatusFlags StatusFlags; // See ImGuiItemStatusFlags_ ImRect Rect; // Full rectangle + ImRect NavRect; // Navigation scoring rectangle (not displayed) ImRect DisplayRect; // Display rectangle (only if ImGuiItemStatusFlags_HasDisplayRect is set) ImGuiLastItemData() { memset(this, 0, sizeof(*this)); } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c933344b..10ea9cfb 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6206,7 +6206,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl { if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent) { - SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, ImRect(bb.Min - window->Pos, bb.Max - window->Pos)); + SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, ImRect(bb.Min - window->Pos, bb.Max - window->Pos)); // (bb == NavRect) g.NavDisableHighlight = true; } }