From 12ba6f46066642efd02eac1becee660e1d4a5d79 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 13 Nov 2020 14:09:09 +0100 Subject: [PATCH] Fix PushFocusScopeID() + using shared stack. Renamed GetFocusScopeID() to GetFocusedFocusScope() - the two existing functions name are very error prone. --- imgui.cpp | 21 ++++++++------------- imgui.h | 5 ++++- imgui_internal.h | 4 +++- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 398e39000..488ccccb4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5962,7 +5962,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.NavLayerCurrent = ImGuiNavLayer_Main; window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext; window->DC.NavLayerActiveMaskNext = 0x00; - window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : 0; // -V595 window->DC.NavHideHighlightOneFrame = false; window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f); @@ -6030,12 +6029,12 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) SetCurrentWindow(window); } + window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : 0; // -V595 + PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true); // Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused) - if (first_begin_of_the_frame) - window->WriteAccessed = false; - + window->WriteAccessed = false; window->BeginCount++; g.NextWindowData.ClearFlags(); @@ -6651,14 +6650,11 @@ void ImGui::ActivateItem(ImGuiID id) g.NavNextActivateId = id; } -// FIXME: this is storing in same stack as IDStack, so Push/Pop mismatch will be reported there. Maybe play nice and a separate in-context stack. void ImGui::PushFocusScope(ImGuiID id) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - ImGuiID top_most_id = window->IDStack.back(); - window->IDStack.push_back(window->DC.NavFocusScopeIdCurrent); - window->IDStack.push_back(top_most_id); + g.FocusScopeStack.push_back(window->DC.NavFocusScopeIdCurrent); window->DC.NavFocusScopeIdCurrent = id; } @@ -6666,10 +6662,9 @@ void ImGui::PopFocusScope() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - window->DC.NavFocusScopeIdCurrent = window->IDStack.back(); - window->IDStack.pop_back(); - IM_ASSERT(window->IDStack.Size > 1); // Too many PopID or PopFocusScope (or could be popping in a wrong/different window?) - window->IDStack.pop_back(); + IM_ASSERT(g.FocusScopeStack.Size > 0); // Too many PopFocusScope() ? + window->DC.NavFocusScopeIdCurrent = g.FocusScopeStack.back(); + g.FocusScopeStack.pop_back(); } void ImGui::SetKeyboardFocusHere(int offset) @@ -6768,7 +6763,7 @@ ImGuiID ImGui::GetIDWithSeed(const char* str, const char* str_end, ImGuiID seed) void ImGui::PopID() { ImGuiWindow* window = GImGui->CurrentWindow; - IM_ASSERT(window->IDStack.Size > 1); // Too many PopID or PopFocusScope (or could be popping in a wrong/different window?) + IM_ASSERT(window->IDStack.Size > 1); // Too many PopID(), or could be popping in a wrong/different window? window->IDStack.pop_back(); } diff --git a/imgui.h b/imgui.h index b0a351388..75e045fae 100644 --- a/imgui.h +++ b/imgui.h @@ -291,7 +291,10 @@ namespace ImGui // - Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window. Child windows can embed their own child. // - For each independent axis of 'size': ==0.0f: use remaining host window size / >0.0f: fixed size / <0.0f: use remaining window size minus abs(size) / Each axis can use a different mode, e.g. ImVec2(0,400). // - BeginChild() returns false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting anything to the window. - // Always call a matching EndChild() for each BeginChild() call, regardless of its return value [as with Begin: this is due to legacy reason and inconsistent with most BeginXXX functions apart from the regular Begin() which behaves like BeginChild().] + // Always call a matching EndChild() for each BeginChild() call, regardless of its return value. + // [Important: due to legacy reason, this is inconsistent with most other functions such as BeginMenu/EndMenu, + // BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function + // returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.] IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0, 0), bool border = false, ImGuiWindowFlags flags = 0); IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0, 0), bool border = false, ImGuiWindowFlags flags = 0); IMGUI_API void EndChild(); diff --git a/imgui_internal.h b/imgui_internal.h index c4d267e58..26f47883f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1207,6 +1207,7 @@ struct ImGuiContext ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() ImVector StyleModifiers; // Stack for PushStyleVar()/PopStyleVar() ImVector FontStack; // Stack for PushFont()/PopFont() + ImVector FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope() ImVectorOpenPopupStack; // Which popups are open (persistent) ImVectorBeginPopupStack; // Which level of BeginPopup() we are in (reset every frame) @@ -1910,7 +1911,8 @@ namespace ImGui // patterns generally need to react (e.g. clear selection) when landing on an item of the set. IMGUI_API void PushFocusScope(ImGuiID id); IMGUI_API void PopFocusScope(); - inline ImGuiID GetFocusScopeID() { ImGuiContext& g = *GImGui; return g.NavFocusScopeId; } + inline ImGuiID GetFocusedFocusScope() { ImGuiContext& g = *GImGui; return g.NavFocusScopeId; } // Focus scope which is actually active + inline ImGuiID GetFocusScope() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.NavFocusScopeIdCurrent; } // Focus scope we are outputting into, set by PushFocusScope() // Inputs // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions.