diff --git a/docs/TODO.txt b/docs/TODO.txt index d2f0da50c..cb7e6be77 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -113,6 +113,8 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - layout: (R&D) local multi-pass layout mode. - layout: (R&D) bind authored layout data (created by an off-line tool), items fetch their pos/size at submission, self-optimize data structures to stable linear access. + - tables: see https://github.com/ocornut/imgui/issues/2957#issuecomment-569726095 + - group: BeginGroup() needs a border option. (~#1496) - group: IsHovered() after EndGroup() covers whole AABB rather than the intersection of individual items. Is that desirable? - group: merge deactivation/activation within same group (fwd WasEdited flag). (#2550) diff --git a/imgui.cpp b/imgui.cpp index 5af94ddcc..51f3d9baf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6784,16 +6784,13 @@ void ImGui::FocusWindow(ImGuiWindow* window) if (g.NavWindow != window) { - IMGUI_DEBUG_LOG_FOCUS("[focus] FocusWindow(\"%s\")\n", window ? window->Name : ""); - g.NavWindow = window; + SetNavWindow(window); if (window && g.NavDisableMouseHover) g.NavMousePosDirty = true; g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId + g.NavLayer = ImGuiNavLayer_Main; g.NavFocusScopeId = 0; g.NavIdIsAlive = false; - g.NavLayer = ImGuiNavLayer_Main; - g.NavInitRequest = g.NavMoveSubmitted = g.NavMoveScoringItems = false; - NavUpdateAnyRequestFlag(); } // Close popups if any @@ -7387,8 +7384,7 @@ void ImGui::SetKeyboardFocusHere(int offset) ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(offset >= -1); // -1 is allowed but not below - g.NavWindow = window; - g.NavInitRequest = g.NavMoveSubmitted = g.NavMoveScoringItems = false; + SetNavWindow(window); ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY; NavMoveRequestSubmit(ImGuiDir_None, offset < 0 ? ImGuiDir_Up : ImGuiDir_Down, ImGuiNavMoveFlags_Tabbing | ImGuiNavMoveFlags_FocusApi, scroll_flags); // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable. @@ -9561,8 +9557,22 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window) // [SECTION] KEYBOARD/GAMEPAD NAVIGATION //----------------------------------------------------------------------------- -// FIXME-NAV: The existence of SetNavID vs SetFocusID properly needs to be clarified/reworked. -// In our terminology those should be interchangeable. Those two functions are merely a legacy artifact, so at minimum naming should be clarified. +// FIXME-NAV: The existence of SetNavID vs SetFocusID vs FocusWindow() needs to be clarified/reworked. +// In our terminology those should be interchangeable, yet right now this is super confusing. +// Those two functions are merely a legacy artifact, so at minimum naming should be clarified. + +void ImGui::SetNavWindow(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + if (g.NavWindow != window) + { + IMGUI_DEBUG_LOG_FOCUS("[focus] SetNavWindow(\"%s\")\n", window ? window->Name : ""); + g.NavWindow = window; + } + g.NavInitRequest = g.NavMoveSubmitted = g.NavMoveScoringItems = false; + NavUpdateAnyRequestFlag(); +} + void ImGui::SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel) { ImGuiContext& g = *GImGui; @@ -9580,15 +9590,12 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) ImGuiContext& g = *GImGui; IM_ASSERT(id != 0); + if (g.NavWindow != window) + SetNavWindow(window); + // Assume that SetFocusID() is called in the context where its window->DC.NavLayerCurrent and window->DC.NavFocusScopeIdCurrent are valid. // Note that window may be != g.CurrentWindow (e.g. SetFocusID call in InputTextEx for multi-line text) const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent; - if (g.NavWindow != window) - { - g.NavWindow = window; - g.NavInitRequest = g.NavMoveSubmitted = g.NavMoveScoringItems = false; - NavUpdateAnyRequestFlag(); - } g.NavId = id; g.NavLayer = nav_layer; g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent; @@ -9837,11 +9844,7 @@ static void ImGui::NavProcessItem() if (g.NavId == id) { if (g.NavWindow != window) - { - g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window. - g.NavInitRequest = g.NavMoveSubmitted = g.NavMoveScoringItems = false; - NavUpdateAnyRequestFlag(); - } + SetNavWindow(window); // Always refresh g.NavWindow, because some operations such as FocusItem() may not have a window. g.NavLayer = window->DC.NavLayerCurrent; g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent; g.NavIdIsAlive = true; @@ -9990,7 +9993,12 @@ void ImGui::NavRestoreLayer(ImGuiNavLayer layer) { ImGuiContext& g = *GImGui; if (layer == ImGuiNavLayer_Main) + { + ImGuiWindow* prev_nav_window = g.NavWindow; g.NavWindow = NavRestoreLastChildNavWindow(g.NavWindow); // FIXME-NAV: Should clear ongoing nav requests? + if (prev_nav_window) + IMGUI_DEBUG_LOG_FOCUS("[focus] NavRestoreLayer: from \"%s\" to SetNavWindow(\"%s\")\n", prev_nav_window->Name, g.NavWindow->Name); + } ImGuiWindow* window = g.NavWindow; if (window->NavLastIds[layer] != 0) { @@ -10527,7 +10535,11 @@ void ImGui::NavMoveRequestApplyResult() } } - g.NavWindow = result->Window; + if (g.NavWindow != result->Window) + { + IMGUI_DEBUG_LOG_FOCUS("[focus] NavMoveRequest: SetNavWindow(\"%s\")\n", result->Window->Name); + g.NavWindow = result->Window; + } if (g.ActiveId != result->ID) ClearActiveID(); if (g.NavId != result->ID) diff --git a/imgui_internal.h b/imgui_internal.h index f627ad7d0..0bee386d5 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2671,6 +2671,7 @@ namespace ImGui IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiNavReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f); IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate); IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. + IMGUI_API void SetNavWindow(ImGuiWindow* window); IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel); // Focus Scope (WIP)