From fbe78b1a3a71b90bfaed656a0cfff29886f11f7c Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 6 Oct 2021 18:16:43 +0200 Subject: [PATCH 1/9] Stack Tool: Docs (#4631) + also prevent Metrics window from displaying twice. --- docs/CHANGELOG.txt | 2 +- docs/FAQ.md | 14 ++++++++++---- imgui.cpp | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 63a6e344..7fd044c2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -42,7 +42,7 @@ Breaking Changes: Other Changes: -- Debug: Stack Tool: Added "Stack Tool" available in "Demo->Examples->Stack Tool", "Metrics->Tools", +- Debug: Stack Tool: Added "Stack Tool" available in "Demo->Tools->Stack Tool", "Metrics->Tools", or by calling the ShowStackToolWindow() function. The tool run queries on hovered id to display details about individual components that were hashed to create an ID. It helps understanding the ID stack system and debugging potential ID collisions. (#4631) [@ocornut, @rokups] diff --git a/docs/FAQ.md b/docs/FAQ.md index ec90ed46..479bce06 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -23,7 +23,7 @@ or view this file with any Markdown viewer. | [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) | | [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries) | | **Q&A: Usage** | -| **[Why is my widget not reacting when I click on it?
How can I have widgets with an empty label?
How can I have multiple widgets with the same label?](#q-why-is-my-widget-not-reacting-when-i-click-on-it)** | +| **[About the ID Stack system..
Why is my widget not reacting when I click on it?
How can I have widgets with an empty label?
How can I have multiple widgets with the same label?](#q-about-the-id-stack-system)** | | [How can I display an image? What is ImTextureID, how does it work?](#q-how-can-i-display-an-image-what-is-imtextureid-how-does-it-work)| | [How can I use my own math types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-math-types-instead-of-imvec2imvec4) | | [How can I interact with standard C++ types (such as std::string and std::vector)?](#q-how-can-i-interact-with-standard-c-types-such-as-stdstring-and-stdvector) | @@ -186,17 +186,23 @@ Refer to rendering backends in the [examples/](https://github.com/ocornut/imgui/ # Q&A: Usage +### Q: About the ID Stack system... ### Q: Why is my widget not reacting when I click on it? ### Q: How can I have widgets with an empty label? ### Q: How can I have multiple widgets with the same label? A primer on labels and the ID Stack... -Dear ImGui internally need to uniquely identify UI elements. +Dear ImGui internally needs to uniquely identify UI elements. Elements that are typically not clickable (such as calls to the Text functions) don't need an ID. Interactive widgets (such as calls to Button buttons) need a unique ID. -Unique ID are used internally to track active widgets and occasionally associate state to widgets. -Unique ID are implicitly built from the hash of multiple elements that identify the "path" to the UI element. + +**Unique ID are used internally to track active widgets and occasionally associate state to widgets.
+Unique ID are implicitly built from the hash of multiple elements that identify the "path" to the UI element.** + +Since Dear ImGui 1.85 you can use `Demo>Tools>Stack Tool` or call `ImGui::ShowStackToolWindow()`. The tool display intermediate values leading to the creation of a unique ID, making things easier to debug and understand. + +![Stack tool](https://user-images.githubusercontent.com/8225057/136235657-a0ea5665-dcd1-423f-9be6-dc3f8ced8f12.png) - Unique ID are often derived from a string label and at minimum scoped within their host window: ```cpp diff --git a/imgui.cpp b/imgui.cpp index eaa96969..3a5cb95c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11205,7 +11205,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) if (cfg->ShowStackTool) ShowStackToolWindow(&cfg->ShowStackTool); - if (!Begin("Dear ImGui Metrics/Debugger", p_open)) + if (!Begin("Dear ImGui Metrics/Debugger", p_open) || GetCurrentWindow()->BeginCount > 1) { End(); return; From 31d033c9d8d64fb9047cdcd731890f1fb5f85db2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 6 Oct 2021 18:33:01 +0200 Subject: [PATCH 2/9] Nav: refactor SetKeyboardFocusHere() into using Nav facility. Fix it for clipped items. (#343, #4079, #2352, #432) + Removed references to counter used by previous implementation of SetKeyboardFocus functions (the TabStop ones will be removed after) --- docs/CHANGELOG.txt | 7 ++++ imgui.cpp | 96 +++++++++++++++++++++++++++++++++------------- imgui.h | 2 +- imgui_internal.h | 28 +++++++------- imgui_widgets.cpp | 37 ++++++++++-------- 5 files changed, 113 insertions(+), 57 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7fd044c2..6c3b9a32 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -57,6 +57,13 @@ Other Changes: - TextUnformatted: Accept null ranges including (NULL,NULL) without asserting, in order to conform to common idioms (e.g. passing .data(), .data() + .size() from a null string). (#3615) - Disabled: Added assert guard for mismatching BeginDisabled()/EndDisabled() blocks. (#211) +- Nav: Fixed using SetKeyboardFocusHere() on non-visible/clipped items. It now works and will scroll + toward the item. When called during a frame where the parent window is appearing, scrolling will + aim to center the item in the window. When calling during a frame where the parent window is already + visible, scrolling will aim to scroll as little as possible to make the item visible. We will later + expose scroll functions and flags in public API to select those behaviors. (#343, #4079, #2352) +- Nav: Fixed using SetKeyboardFocusHere() from activating a different item on the next frame if + submitted items have changed during that frame. (#432) - Nav: Fixed toggling menu layer with Alt or exiting menu layer with Esc not moving mouse when the NavEnableSetMousePos config flag is set. - Nav: Fixed a few widgets from not setting reference keyboard/gamepad navigation ID when diff --git a/imgui.cpp b/imgui.cpp index 3a5cb95c..ffda92e3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3303,7 +3303,6 @@ void ImGui::ItemInputable(ImGuiWindow* window, ImGuiID id) // Increment counters // FIXME: ImGuiItemFlags_Disabled should disable more. const bool is_tab_stop = (g.LastItemData.InFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0; - window->DC.FocusCounterRegular++; if (is_tab_stop) { window->DC.FocusCounterTabStop++; @@ -3322,11 +3321,6 @@ void ImGui::ItemInputable(ImGuiWindow* window, ImGuiID id) // Handle focus requests if (g.TabFocusRequestCurrWindow == window) { - if (window->DC.FocusCounterRegular == g.TabFocusRequestCurrCounterRegular) - { - g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_FocusedByCode; - return; - } if (is_tab_stop && window->DC.FocusCounterTabStop == g.TabFocusRequestCurrCounterTabStop) { g.NavJustTabbedId = id; // FIXME-NAV: aim to eventually set in NavUpdate() once we finish the refactor @@ -3843,7 +3837,6 @@ void ImGui::UpdateTabFocus() // - Note that SetKeyboardFocusHere() sets the Next fields mid-frame. To be consistent we also // manipulate the Next fields here even though they will be turned into Curr fields below. g.TabFocusRequestNextWindow = g.NavWindow; - g.TabFocusRequestNextCounterRegular = INT_MAX; if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX) g.TabFocusRequestNextCounterTabStop = g.NavIdTabCounter + (g.IO.KeyShift ? -1 : 0); else @@ -3852,17 +3845,15 @@ void ImGui::UpdateTabFocus() // Turn queued focus request into current one g.TabFocusRequestCurrWindow = NULL; - g.TabFocusRequestCurrCounterRegular = g.TabFocusRequestCurrCounterTabStop = INT_MAX; + g.TabFocusRequestCurrCounterTabStop = INT_MAX; if (g.TabFocusRequestNextWindow != NULL) { ImGuiWindow* window = g.TabFocusRequestNextWindow; g.TabFocusRequestCurrWindow = window; - if (g.TabFocusRequestNextCounterRegular != INT_MAX && window->DC.FocusCounterRegular != -1) - g.TabFocusRequestCurrCounterRegular = ImModPositive(g.TabFocusRequestNextCounterRegular, window->DC.FocusCounterRegular + 1); if (g.TabFocusRequestNextCounterTabStop != INT_MAX && window->DC.FocusCounterTabStop != -1) g.TabFocusRequestCurrCounterTabStop = ImModPositive(g.TabFocusRequestNextCounterTabStop, window->DC.FocusCounterTabStop + 1); g.TabFocusRequestNextWindow = NULL; - g.TabFocusRequestNextCounterRegular = g.TabFocusRequestNextCounterTabStop = INT_MAX; + g.TabFocusRequestNextCounterTabStop = INT_MAX; } g.NavIdTabCounter = INT_MAX; @@ -6316,7 +6307,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.CurrentColumns = NULL; window->DC.LayoutType = ImGuiLayoutType_Vertical; window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical; - window->DC.FocusCounterRegular = window->DC.FocusCounterTabStop = -1; + window->DC.FocusCounterTabStop = -1; window->DC.ItemWidth = window->ItemWidthDefault; window->DC.TextWrapPos = -1.0f; // disabled @@ -7082,12 +7073,16 @@ void ImGui::PopFocusScope() void ImGui::SetKeyboardFocusHere(int offset) { - IM_ASSERT(offset >= -1); // -1 is allowed but not below ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - g.TabFocusRequestNextWindow = window; - g.TabFocusRequestNextCounterRegular = window->DC.FocusCounterRegular + 1 + offset; - g.TabFocusRequestNextCounterTabStop = INT_MAX; + IM_ASSERT(offset >= -1); // -1 is allowed but not below + g.NavWindow = window; + ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY; + NavMoveRequestSubmit(ImGuiDir_None, ImGuiDir_None, ImGuiNavMoveFlags_Tabbing, scroll_flags); // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable. + if (offset == -1) + NavMoveRequestResolveWithLastItem(); + else + g.NavTabbingInputableRemaining = offset + 1; } void ImGui::SetItemDefaultFocus() @@ -8980,6 +8975,7 @@ static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result) result->Window = window; result->ID = g.LastItemData.ID; result->FocusScopeId = window->DC.NavFocusScopeIdCurrent; + result->InFlags = g.LastItemData.InFlags; result->RectRel = ImRect(g.LastItemData.NavRect.Min - window->Pos, g.LastItemData.NavRect.Max - window->Pos); } @@ -9014,18 +9010,30 @@ static void ImGui::NavProcessItem() // FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRect + scoring from a rect wrapped according to current wrapping policy) if (g.NavMoveScoringItems) { + if (item_flags & ImGuiItemFlags_Inputable) + g.NavTabbingInputableRemaining--; + if ((g.NavId != id || (g.NavMoveFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & (ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNav))) { ImGuiNavItemData* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther; - if (NavScoreItem(result)) - NavApplyItemToResult(result); - // Features like PageUp/PageDown need to maintain a separate score for the visible set of items. - const float VISIBLE_RATIO = 0.70f; - if ((g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb)) - if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO) - if (NavScoreItem(&g.NavMoveResultLocalVisible)) - NavApplyItemToResult(&g.NavMoveResultLocalVisible); + if (g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing) + { + if (g.NavTabbingInputableRemaining == 0) + NavMoveRequestResolveWithLastItem(); + } + else + { + if (NavScoreItem(result)) + NavApplyItemToResult(result); + + // Features like PageUp/PageDown need to maintain a separate score for the visible set of items. + const float VISIBLE_RATIO = 0.70f; + if ((g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb)) + if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO) + if (NavScoreItem(&g.NavMoveResultLocalVisible)) + NavApplyItemToResult(&g.NavMoveResultLocalVisible); + } } } @@ -9051,6 +9059,10 @@ void ImGui::NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavM { ImGuiContext& g = *GImGui; IM_ASSERT(g.NavWindow != NULL); + + if (move_flags & ImGuiNavMoveFlags_Tabbing) + move_flags |= ImGuiNavMoveFlags_AllowCurrentNavId; + g.NavMoveSubmitted = g.NavMoveScoringItems = true; g.NavMoveDir = move_dir; g.NavMoveDirForDebug = move_dir; @@ -9059,12 +9071,21 @@ void ImGui::NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavM g.NavMoveScrollFlags = scroll_flags; g.NavMoveForwardToNextFrame = false; g.NavMoveKeyMods = g.IO.KeyMods; + g.NavTabbingInputableRemaining = 0; g.NavMoveResultLocal.Clear(); g.NavMoveResultLocalVisible.Clear(); g.NavMoveResultOther.Clear(); NavUpdateAnyRequestFlag(); } +void ImGui::NavMoveRequestResolveWithLastItem() +{ + ImGuiContext& g = *GImGui; + g.NavMoveScoringItems = false; // Ensure request doesn't need more processing + NavApplyItemToResult(&g.NavMoveResultLocal); + NavUpdateAnyRequestFlag(); +} + void ImGui::NavMoveRequestCancel() { ImGuiContext& g = *GImGui; @@ -9284,6 +9305,7 @@ static void ImGui::NavUpdate() // Process navigation move request if (g.NavMoveSubmitted) NavMoveRequestApplyResult(); + g.NavTabbingInputableRemaining = 0; g.NavMoveSubmitted = g.NavMoveScoringItems = false; // Apply application mouse position movement, after we had a chance to process move request result. @@ -9535,7 +9557,9 @@ void ImGui::NavMoveRequestApplyResult() // In a situation when there is no results but NavId != 0, re-enable the Navigation highlight (because g.NavId is not considered as a possible result) if (result == NULL) { - if (g.NavId != 0) + if (g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing) + g.NavMoveFlags |= ImGuiNavMoveFlags_DontSetNavHighlight; + if (g.NavId != 0 && (g.NavMoveFlags & ImGuiNavMoveFlags_DontSetNavHighlight) == 0) { g.NavDisableHighlight = false; g.NavDisableMouseHover = true; @@ -9590,9 +9614,27 @@ void ImGui::NavMoveRequestApplyResult() IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: result 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); + // Tabbing: Activates Inputable or Focus non-Inputable + if ((g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing) && (result->InFlags & ImGuiItemFlags_Inputable)) + { + g.NavNextActivateId = result->ID; + g.NavNextActivateFlags = ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState; + g.NavMoveFlags |= ImGuiNavMoveFlags_DontSetNavHighlight; + } + + // Activate + if (g.NavMoveFlags & ImGuiNavMoveFlags_Activate) + { + g.NavNextActivateId = result->ID; + g.NavNextActivateFlags = ImGuiActivateFlags_None; + } + // Enable nav highlight - g.NavDisableHighlight = false; - g.NavDisableMouseHover = g.NavMousePosDirty = true; + if ((g.NavMoveFlags & ImGuiNavMoveFlags_DontSetNavHighlight) == 0) + { + g.NavDisableHighlight = false; + g.NavDisableMouseHover = g.NavMousePosDirty = true; + } } // Process NavCancel input (to close a popup, get back to parent, clear focus) diff --git a/imgui.h b/imgui.h index f66fd95b..246e8e28 100644 --- a/imgui.h +++ b/imgui.h @@ -64,7 +64,7 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) #define IMGUI_VERSION "1.85 WIP" -#define IMGUI_VERSION_NUM 18419 +#define IMGUI_VERSION_NUM 18420 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE diff --git a/imgui_internal.h b/imgui_internal.h index 1149da65..d1a8258d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -759,9 +759,7 @@ enum ImGuiItemStatusFlags_ ImGuiItemStatusFlags_HasDeactivated = 1 << 5, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag. ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set. ImGuiItemStatusFlags_HoveredWindow = 1 << 7, // Override the HoveredWindow test to allow cross-window hover testing. - ImGuiItemStatusFlags_FocusedByCode = 1 << 8, // Set when the Focusable item just got focused from code. - ImGuiItemStatusFlags_FocusedByTabbing = 1 << 9, // Set when the Focusable item just got focused by Tabbing. - ImGuiItemStatusFlags_Focused = ImGuiItemStatusFlags_FocusedByCode | ImGuiItemStatusFlags_FocusedByTabbing + ImGuiItemStatusFlags_FocusedByTabbing = 1 << 8 // Set when the Focusable item just got focused by Tabbing (FIXME: to be removed soon) #ifdef IMGUI_ENABLE_TEST_ENGINE , // [imgui_tests only] @@ -1219,7 +1217,10 @@ enum ImGuiNavMoveFlags_ ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisible that only comprise elements that are already fully visible (used by PageUp/PageDown) ImGuiNavMoveFlags_ScrollToEdgeY = 1 << 6, // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword, probably unnecessary ImGuiNavMoveFlags_Forwarded = 1 << 7, - ImGuiNavMoveFlags_DebugNoResult = 1 << 8 + ImGuiNavMoveFlags_DebugNoResult = 1 << 8, // Dummy scoring for debug purpose, don't apply result + ImGuiNavMoveFlags_Tabbing = 1 << 9, // == Focus + Activate if item is Inputable + DontChangeNavHighlight + ImGuiNavMoveFlags_Activate = 1 << 10, + ImGuiNavMoveFlags_DontSetNavHighlight = 1 << 11 // Do not alter the visible state of keyboard vs mouse nav highlight }; enum ImGuiNavLayer @@ -1235,12 +1236,13 @@ struct ImGuiNavItemData ImGuiID ID; // Init,Move // Best candidate item ID ImGuiID FocusScopeId; // Init,Move // Best candidate focus scope ID ImRect RectRel; // Init,Move // Best candidate bounding box in window relative space + ImGuiItemFlags InFlags; // ????,Move // Best candidate item flags float DistBox; // Move // Best candidate box distance to current NavId float DistCenter; // Move // Best candidate center distance to current NavId float DistAxial; // Move // Best candidate axial distance to current NavId ImGuiNavItemData() { Clear(); } - void Clear() { Window = NULL; ID = FocusScopeId = 0; RectRel = ImRect(); DistBox = DistCenter = DistAxial = FLT_MAX; } + void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; DistBox = DistCenter = DistAxial = FLT_MAX; } }; //----------------------------------------------------------------------------- @@ -1582,6 +1584,7 @@ struct ImGuiContext ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename? ImRect NavScoringRect; // Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring. int NavScoringDebugCount; // Metrics for debugging + int NavTabbingInputableRemaining; // >0 when counting items for tabbing ImGuiNavItemData NavMoveResultLocal; // Best move request candidate within NavWindow ImGuiNavItemData NavMoveResultLocalVisible; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag) ImGuiNavItemData NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag) @@ -1597,9 +1600,7 @@ struct ImGuiContext // Legacy Focus/Tabbing system (older than Nav, active even if Nav is disabled, misnamed. FIXME-NAV: This needs a redesign!) ImGuiWindow* TabFocusRequestCurrWindow; // ImGuiWindow* TabFocusRequestNextWindow; // - int TabFocusRequestCurrCounterRegular; // Any item being requested for focus, stored as an index (we on layout to be stable between the frame pressing TAB and the next frame, semi-ouch) int TabFocusRequestCurrCounterTabStop; // Tab item being requested for focus, stored as an index - int TabFocusRequestNextCounterRegular; // Stored for next frame int TabFocusRequestNextCounterTabStop; // " bool TabFocusPressed; // Set in NewFrame() when user pressed Tab @@ -1787,14 +1788,15 @@ struct ImGuiContext NavMoveKeyMods = ImGuiKeyModFlags_None; NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None; NavScoringDebugCount = 0; + NavTabbingInputableRemaining = 0; NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL; NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f; NavWindowingToggleLayer = false; TabFocusRequestCurrWindow = TabFocusRequestNextWindow = NULL; - TabFocusRequestCurrCounterRegular = TabFocusRequestCurrCounterTabStop = INT_MAX; - TabFocusRequestNextCounterRegular = TabFocusRequestNextCounterTabStop = INT_MAX; + TabFocusRequestCurrCounterTabStop = INT_MAX; + TabFocusRequestNextCounterTabStop = INT_MAX; TabFocusPressed = false; DimBgRatio = 0.0f; @@ -1901,7 +1903,6 @@ struct IMGUI_API ImGuiWindowTempData int CurrentTableIdx; // Current table index (into g.Tables) ImGuiLayoutType LayoutType; ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin() - int FocusCounterRegular; // (Legacy Focus/Tabbing system) Sequential counter, start at -1 and increase when ImGuiItemFlags_Inputable (FIXME-NAV: Needs redesign) int FocusCounterTabStop; // (Legacy Focus/Tabbing system) Same, but only count widgets which you can Tab through. // Local parameters stacks @@ -2478,9 +2479,9 @@ namespace ImGui #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // Currently refactoring focus/nav/tabbing system // If you have old/custom copy-and-pasted widgets that used FocusableItemRegister(): - // (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool focused = FocusableItemRegister(...)' - // (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0' - // (New) IMGUI_VERSION_NUM >= 18411: using 'ItemAdd(..., ImGuiItemAddFlags_Inputable)' and 'bool focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0' + // (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)' + // (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0' + // (New) IMGUI_VERSION_NUM >= 18413: using 'ItemAdd(..., ImGuiItemFlags_Inputable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_FocusedTabbing) != 0 || g.NavActivateInputId == id' (WIP) // Widget code are simplified as there's no need to call FocusableItemUnregister() while managing the transition from regular widget to TempInputText() inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) { IM_ASSERT(0); IM_UNUSED(window); IM_UNUSED(id); return false; } // -> pass ImGuiItemAddFlags_Inputable flag to ItemAdd() inline void FocusableItemUnregister(ImGuiWindow* window) { IM_ASSERT(0); IM_UNUSED(window); } // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem @@ -2522,6 +2523,7 @@ namespace ImGui IMGUI_API bool NavMoveRequestButNoResultYet(); IMGUI_API void NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags); IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags); + IMGUI_API void NavMoveRequestResolveWithLastItem(); IMGUI_API void NavMoveRequestCancel(); IMGUI_API void NavMoveRequestApplyResult(); IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c4f1ceb5..af62ccd4 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2407,17 +2407,17 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); if (!temp_input_is_active) { - const bool focus_requested = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0; + const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0; const bool clicked = (hovered && g.IO.MouseClicked[0]); const bool double_clicked = (hovered && g.IO.MouseDoubleClicked[0]); - if (focus_requested || clicked || double_clicked || g.NavActivateId == id || g.NavActivateInputId == id) + if (input_requested_by_tabbing || clicked || double_clicked || g.NavActivateId == id || g.NavActivateInputId == id) { SetActiveID(id, window); SetFocusID(id, window); FocusWindow(window); g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); if (temp_input_allowed) - if (focus_requested || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavActivateInputId == id) + if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavActivateInputId == id) temp_input_is_active = true; } @@ -3025,15 +3025,15 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); if (!temp_input_is_active) { - const bool focus_requested = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0; + const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0; const bool clicked = (hovered && g.IO.MouseClicked[0]); - if (focus_requested || clicked || g.NavActivateId == id || g.NavActivateInputId == id) + if (input_requested_by_tabbing || clicked || g.NavActivateId == id || g.NavActivateInputId == id) { SetActiveID(id, window); SetFocusID(id, window); FocusWindow(window); g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); - if (temp_input_allowed && (focus_requested || (clicked && g.IO.KeyCtrl) || g.NavActivateInputId == id)) + if (temp_input_allowed && (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || g.NavActivateInputId == id)) temp_input_is_active = true; } } @@ -4024,21 +4024,19 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // We are only allowed to access the state if we are already the active widget. ImGuiInputTextState* state = GetInputTextState(id); - const bool focus_requested_by_code = (item_status_flags & ImGuiItemStatusFlags_FocusedByCode) != 0; - const bool focus_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0; + const bool input_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0; + const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard)); const bool user_clicked = hovered && io.MouseClicked[0]; - const bool user_nav_input_start = (g.ActiveId != id) && (g.NavActivateInputId == id || g.NavActivateId == id); const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y); const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == GetWindowScrollbarID(draw_window, ImGuiAxis_Y); - bool clear_active_id = false; - bool select_all = (g.ActiveId != id) && ((flags & ImGuiInputTextFlags_AutoSelectAll) != 0 || user_nav_input_start) && (!is_multiline); + bool select_all = false; float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX; const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline); - const bool init_make_active = (user_clicked || user_scroll_finish || user_nav_input_start || focus_requested_by_code || focus_requested_by_tabbing); + const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav || input_requested_by_tabbing); const bool init_state = (init_make_active || user_scroll_active); if ((init_state && g.ActiveId != id) || init_changed_specs) { @@ -4074,13 +4072,20 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ state->ID = id; state->ScrollX = 0.0f; stb_textedit_initialize_state(&state->Stb, !is_multiline); - if (!is_multiline && focus_requested_by_code) + } + + if (!is_multiline) + { + if (flags & ImGuiInputTextFlags_AutoSelectAll) + select_all = true; + if (input_requested_by_nav && (!recycle_state || !(g.NavActivateFlags & ImGuiActivateFlags_TryToPreserveState))) + select_all = true; + if (input_requested_by_tabbing || (user_clicked && io.KeyCtrl)) select_all = true; } + if (flags & ImGuiInputTextFlags_AlwaysOverwrite) state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863) - if (!is_multiline && (focus_requested_by_tabbing || (user_clicked && io.KeyCtrl))) - select_all = true; } if (g.ActiveId != id && init_make_active) @@ -4214,7 +4219,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // We ignore CTRL inputs, but need to allow ALT+CTRL as some keyboards (e.g. German) use AltGR (which _is_ Alt+Ctrl) to input certain characters. if (io.InputQueueCharacters.Size > 0) { - if (!ignore_char_inputs && !is_readonly && !user_nav_input_start) + if (!ignore_char_inputs && !is_readonly && !input_requested_by_nav) for (int n = 0; n < io.InputQueueCharacters.Size; n++) { // Insert character if they pass filtering From 30a6873a44a0d2d2c833d9edfa247f16a71657e3 Mon Sep 17 00:00:00 2001 From: Basil Fierz Date: Thu, 7 Oct 2021 14:58:09 +0200 Subject: [PATCH 3/9] Backends: WebGPU: Fix missing initialization of local variable (#4634) --- backends/imgui_impl_wgpu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 20b6bb22..2f621ed8 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -270,7 +270,7 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(uint32_ spirv_desc.codeSize = binary_data_size; spirv_desc.code = binary_data; - WGPUShaderModuleDescriptor desc; + WGPUShaderModuleDescriptor desc = {}; desc.nextInChain = reinterpret_cast(&spirv_desc); WGPUProgrammableStageDescriptor stage_desc = {}; From dde31030e9fea67a848180f328986f2db79464f7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 Oct 2021 15:07:43 +0200 Subject: [PATCH 4/9] Backends: SDL_Renderer: use SDL_RenderIsClipEnabled() to pass NULL to SDL_RenderSetClipRect (#3926, #4582, #4633) --- backends/imgui_impl_sdlrenderer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_sdlrenderer.cpp b/backends/imgui_impl_sdlrenderer.cpp index ff163113..bfc2b676 100644 --- a/backends/imgui_impl_sdlrenderer.cpp +++ b/backends/imgui_impl_sdlrenderer.cpp @@ -120,9 +120,11 @@ void ImGui_ImplSDLRenderer_RenderDrawData(ImDrawData* draw_data) struct BackupSDLRendererState { SDL_Rect Viewport; + bool ClipEnabled; SDL_Rect ClipRect; }; BackupSDLRendererState old = {}; + old.ClipEnabled = SDL_RenderIsClipEnabled(bd->SDLRenderer); SDL_RenderGetViewport(bd->SDLRenderer, &old.Viewport); SDL_RenderGetClipRect(bd->SDLRenderer, &old.ClipRect); @@ -183,7 +185,7 @@ void ImGui_ImplSDLRenderer_RenderDrawData(ImDrawData* draw_data) // Restore modified SDL_Renderer state SDL_RenderSetViewport(bd->SDLRenderer, &old.Viewport); - SDL_RenderSetClipRect(bd->SDLRenderer, &old.ClipRect); + SDL_RenderSetClipRect(bd->SDLRenderer, old.ClipEnabled ? &old.ClipRect : NULL); } // Called by Init/NewFrame/Shutdown From ec6ca06898d380142c77b3e73da06e5c082a0f60 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 8 Oct 2021 13:00:47 +0200 Subject: [PATCH 5/9] InputText: Fixed selection rectangle appearing one frame late when selecting all. --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6c3b9a32..8ed1a40e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,6 +54,7 @@ Other Changes: - InputTextMultiline: Fixed label size not being included into window contents rect unless the whole widget is clipped. - InputText: Allow activating/cancelling/validating input with gamepad nav events. (#2321, #4552) +- InputText: Fixed selection rectangle appearing one frame late when selecting all. - TextUnformatted: Accept null ranges including (NULL,NULL) without asserting, in order to conform to common idioms (e.g. passing .data(), .data() + .size() from a null string). (#3615) - Disabled: Added assert guard for mismatching BeginDisabled()/EndDisabled() blocks. (#211) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index af62ccd4..585820cb 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4118,7 +4118,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Lock the decision of whether we are going to take the path displaying the cursor or selection const bool render_cursor = (g.ActiveId == id) || (state && user_scroll_active); - bool render_selection = state && state->HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor); + bool render_selection = state && (state->HasSelection() || select_all) && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor); bool value_changed = false; bool enter_pressed = false; From 44f801186fd9e8e9c3ed87358eadae0f19032c85 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 Oct 2021 18:25:29 +0200 Subject: [PATCH 6/9] SetItemDefaultFocus() use ScrollToRectEx(), don't tab when Alt is held either, TabItemEx() uses ItemAdd's extra_flags, misc comments. --- docs/TODO.txt | 3 +-- imgui.cpp | 27 ++++++++++++++++----------- imgui_internal.h | 2 +- imgui_widgets.cpp | 8 ++------ 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/TODO.txt b/docs/TODO.txt index dff2d24d..95a9326f 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -326,6 +326,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - nav: some features such as PageUp/Down/Home/End should probably work without ImGuiConfigFlags_NavEnableKeyboard? (where do we draw the line?) - nav: configuration flag to disable global shortcuts (currently only CTRL-Tab) ? ! nav: never clear NavId on some setup (e.g. gamepad centric) + - nav: scroll up/down if possible when move request fails - nav: there's currently no way to completely clear focus with the keyboard. depending on patterns used by the application to dispatch inputs, it may be desirable. - nav: code to focus child-window on restoring NavId appears to have issue: e.g. when focus change is implicit because of window closure. - nav: Home/End behavior when navigable item is not fully visible at the edge of scrolling? should be backtrack to keep item into view? @@ -353,8 +354,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - nav/windowing: when CTRL-Tab/windowing is active, the HoveredWindow detection doesn't take account of the window display re-ordering. - nav/windowing: Resizing window will currently fail with certain types of resizing constraints/callback applied - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622) - - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame) - - focus: unable to use SetKeyboardFocusHere() on clipped widgets. (#787, #343) - inputs: we need an explicit flag about whether the imgui window is focused, to be able to distinguish focused key releases vs alt-tabbing all release behaviors. - inputs: rework IO system to be able to pass actual ordered/timestamped events. use an event queue? (~#335, #71) diff --git a/imgui.cpp b/imgui.cpp index ffda92e3..efabebc2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3829,7 +3829,10 @@ void ImGui::UpdateTabFocus() ImGuiContext& g = *GImGui; // Pressing TAB activate widget focus - g.TabFocusPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && !IsActiveIdUsingKey(ImGuiKey_Tab)); + g.TabFocusPressed = false; + if (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) + if (!g.IO.KeyCtrl && !g.IO.KeyAlt && IsKeyPressedMap(ImGuiKey_Tab) && !IsActiveIdUsingKey(ImGuiKey_Tab)) + g.TabFocusPressed = true; if (g.ActiveId == 0 && g.TabFocusPressed) { // - This path is only taken when no widget are active/tabbed-into yet. @@ -7091,15 +7094,17 @@ 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) - { - g.NavInitRequest = false; - g.NavInitResultId = g.LastItemData.ID; - g.NavInitResultRectRel = ImRect(g.LastItemData.Rect.Min - window->Pos, g.LastItemData.Rect.Max - window->Pos); - NavUpdateAnyRequestFlag(); - if (!IsItemVisible()) - SetScrollHereY(); - } + if (g.NavWindow != window->RootWindowForNav || (!g.NavInitRequest && g.NavInitResultId == 0) || g.NavLayer != window->DC.NavLayerCurrent) + return; + + g.NavInitRequest = false; + g.NavInitResultId = g.LastItemData.ID; + g.NavInitResultRectRel = ImRect(g.LastItemData.Rect.Min - window->Pos, g.LastItemData.Rect.Max - window->Pos); + NavUpdateAnyRequestFlag(); + + // Scroll could be done in NavInitRequestApplyResult() via a opt-in flag (we however don't want regular init requests to scroll) + if (!IsItemVisible()) + ScrollToRectEx(window, g.LastItemData.Rect, ImGuiScrollFlags_None); } void ImGui::SetStateStorage(ImGuiStorage* tree) @@ -9323,7 +9328,7 @@ static void ImGui::NavUpdate() } g.NavIdIsAlive = false; g.NavJustTabbedId = 0; - IM_ASSERT(g.NavLayer == 0 || g.NavLayer == 1); + IM_ASSERT(g.NavLayer == ImGuiNavLayer_Main || g.NavLayer == ImGuiNavLayer_Menu); // Store our return window (for returning from Menu Layer to Main Layer) and clear it as soon as we step back in our own Layer 0 if (g.NavWindow) diff --git a/imgui_internal.h b/imgui_internal.h index d1a8258d..291fcaec 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -744,7 +744,7 @@ enum ImGuiItemFlags_ ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // Disable MenuItem/Selectable() automatically closing their popup window ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets) ImGuiItemFlags_ReadOnly = 1 << 7, // false // [ALPHA] Allow hovering interactions but underlying value is not changed. - ImGuiItemFlags_Inputable = 1 << 8 // false // [WIP] Auto-activate item when focused. Currently only used and supported by a few items before it becomes a generic feature. + ImGuiItemFlags_Inputable = 1 << 8 // false // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature. }; // Storage for LastItem data diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 585820cb..c138b8cf 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7879,9 +7879,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); if (p_open && !*p_open) { - PushItemFlag(ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus, true); - ItemAdd(ImRect(), id); - PopItemFlag(); + ItemAdd(ImRect(), id, NULL, ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus); return false; } @@ -7948,9 +7946,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, // and then gets submitted again, the tabs will have 'tab_appearing=true' but 'tab_is_new=false'. if (tab_appearing && (!tab_bar_appearing || tab_is_new)) { - PushItemFlag(ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus, true); - ItemAdd(ImRect(), id); - PopItemFlag(); + ItemAdd(ImRect(), id, NULL, ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus); if (is_tab_button) return false; return tab_contents_visible; From ba5c105c0194e667f80194c7bc8f0f5c78eaa8a9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 11 Oct 2021 11:37:31 +0200 Subject: [PATCH 7/9] Menus: Fixed an assertion happening in some situations when closing nested menus (broken in 1.83). (#4640) Broken since 936f5322 Weirdly chain-reaction caused by the fact following #4640 repro, the SourceWindow assignment in OpenPopupEx() picks Menu_04 before its closure. Value of SourceWindow since bda2cde6 #2517 --- docs/CHANGELOG.txt | 6 ++++-- imgui.cpp | 15 +++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8ed1a40e..19d4c1fb 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -86,9 +86,11 @@ Other Changes: RGB<>HSV round trips every frames. [@rokups] - ColorPicker4: Fixed picker being unable to select exact 1.0f color when dragging toward the edges of the SV square (previously picked 0.999989986f). (#3517) [@rokups] -- Menus: Fixed vertical alignments of MenuItem() calls within a menu bar. (broken in 1.84). (#4538) -- Menus: Adjust closing logic to accomodate for varying font size and dpi. +- Menus: Fixed vertical alignments of MenuItem() calls within a menu bar (broken in 1.84). (#4538) +- Menus: Improve closing logic when moving diagonally in empty between between parent and child menus to + accomodate for varying font size and dpi. - Menus: Fixed crash when navigating left inside a child window inside a sub-menu. (#4510). +- Menus: Fixed an assertion happening in some situations when closing nested menus (broken in 1.83). (#4640) - Drag and Drop: Fixed using BeginDragDropSource() inside a BeginChild() that returned false. (#4515) - PlotHistogram: Fixed zero-line position when manually specifying min<0 and max>0. (#4349) [@filippocrocchini] - Misc: Added asserts for missing PopItemFlag() calls. diff --git a/imgui.cpp b/imgui.cpp index efabebc2..38fcb930 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6551,8 +6551,18 @@ void ImGui::FocusWindow(ImGuiWindow* window) void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window) { ImGuiContext& g = *GImGui; - - const int start_idx = ((under_this_window != NULL) ? FindWindowFocusIndex(under_this_window) : g.WindowsFocusOrder.Size) - 1; + int start_idx = g.WindowsFocusOrder.Size - 1; + if (under_this_window != NULL) + { + // Aim at root window behind us, if we are in a child window that's our own root (see #4640) + int offset = -1; + while (under_this_window->Flags & ImGuiWindowFlags_ChildWindow) + { + under_this_window = under_this_window->ParentWindow; + offset = 0; + } + start_idx = FindWindowFocusIndex(under_this_window) + offset; + } for (int i = start_idx; i >= 0; i--) { // We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user. @@ -9838,6 +9848,7 @@ static int ImGui::FindWindowFocusIndex(ImGuiWindow* window) ImGuiContext& g = *GImGui; IM_UNUSED(g); int order = window->FocusOrder; + IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) == 0); IM_ASSERT(g.WindowsFocusOrder[order] == window); return order; } From 75c54e63844d262b1005865eba370ad487808b1f Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 11 Oct 2021 14:40:42 +0200 Subject: [PATCH 8/9] Nav: Fixed vertical scoring offset when wrapping on Y in a decorated window. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 19d4c1fb..cd9a40cf 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -74,6 +74,7 @@ Other Changes: the PressedOnClick/PressedOnDoubleClick/PressedOnRelease button policy. - Nav: Fixed an issue with losing focus on docked windows when pressing Alt while keyboard navigation is disabled. (#4547, #4439) [@PathogenDavid] +- Nav: Fixed vertical scoring offset when wrapping on Y in a decorated window. - Nav: Improve scrolling behavior when navigating to an item larger than view. - TreePush(): removed unnecessary/inconsistent legacy behavior where passing a NULL value to the TreePush(const char*) and TreePush(const void*) functions would use an hardcoded replacement. diff --git a/imgui.cpp b/imgui.cpp index 38fcb930..de0fb746 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9814,10 +9814,11 @@ static void ImGui::NavEndFrame() } do_forward = true; } + const float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight(); if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY))) { bb_rel.Min.y = bb_rel.Max.y = - ImMax(window->SizeFull.y, window->ContentSize.y + window->WindowPadding.y * 2.0f) - window->Scroll.y; + ImMax(window->SizeFull.y, window->ContentSize.y + window->WindowPadding.y * 2.0f) - window->Scroll.y + decoration_up_height; if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(-bb_rel.GetWidth()); @@ -9827,7 +9828,7 @@ static void ImGui::NavEndFrame() } if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY))) { - bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y; + bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y + decoration_up_height; if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(+bb_rel.GetWidth()); From 55d35d8387c15bf0cfd71861df67af8cfbda7456 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 11 Oct 2021 19:03:37 +0200 Subject: [PATCH 9/9] Version 1.85 --- docs/CHANGELOG.txt | 16 +++++++++++----- imgui.cpp | 6 +++--- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 2 +- 8 files changed, 22 insertions(+), 16 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index cd9a40cf..0bb5855f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -31,14 +31,20 @@ HOW TO UPDATE? - Please report any issue! ----------------------------------------------------------------------- - VERSION 1.85 WIP (In Progress) + VERSION 1.85 (Released 2021-10-12) ----------------------------------------------------------------------- +This is the last release officially supporting C++03 and Visual Studio 2008/2010. (#4537) +We expect that the next release will require a subset of the C++11 language (VS 2012~, GCC 4.8.1, Clang 3.3). +We may use some C++11 language features but we will not use any C++ library headers. +If you are stuck on ancient compiler you may need to stay at this version onward. + Breaking Changes: - Removed GetWindowContentRegionWidth() function. keep inline redirection helper. Can use 'GetWindowContentRegionMax().x - GetWindowContentRegionMin().x' instead but it's not very useful in practice, and the only use of it in the demo was illfit. + Using 'GetContentRegionAvail().x' is generally a better choice. Other Changes: @@ -66,7 +72,7 @@ Other Changes: - Nav: Fixed using SetKeyboardFocusHere() from activating a different item on the next frame if submitted items have changed during that frame. (#432) - Nav: Fixed toggling menu layer with Alt or exiting menu layer with Esc not moving mouse when - the NavEnableSetMousePos config flag is set. + the ImGuiConfigFlags_NavEnableSetMousePos config flag is set. - Nav: Fixed a few widgets from not setting reference keyboard/gamepad navigation ID when activated with mouse. More specifically: BeginTabItem(), the scrolling arrows of BeginTabBar(), the arrow section of TreeNode(), the +/- buttons of InputInt()/InputFloat(), Selectable() with @@ -77,9 +83,9 @@ Other Changes: - Nav: Fixed vertical scoring offset when wrapping on Y in a decorated window. - Nav: Improve scrolling behavior when navigating to an item larger than view. - TreePush(): removed unnecessary/inconsistent legacy behavior where passing a NULL value to - the TreePush(const char*) and TreePush(const void*) functions would use an hardcoded replacement. + the TreePush(const char*) and TreePush(const void*) functions would use an hard-coded replacement. The only situation where that change would make a meaningful difference is TreePush((const char*)NULL) - (_explicitely_ casting a null pointer to const char*), which is unlikely and will now crash. + (_explicitly_ casting a null pointer to const char*), which is unlikely and will now crash. You may replace it with anything else. - ColorEdit4: Fixed not being able to change hue when saturation is 0. (#4014) [@rokups] - ColorEdit4: Fixed hue resetting to 0 when it is set to 255. [@rokups] @@ -89,7 +95,7 @@ Other Changes: of the SV square (previously picked 0.999989986f). (#3517) [@rokups] - Menus: Fixed vertical alignments of MenuItem() calls within a menu bar (broken in 1.84). (#4538) - Menus: Improve closing logic when moving diagonally in empty between between parent and child menus to - accomodate for varying font size and dpi. + accommodate for varying font size and dpi. - Menus: Fixed crash when navigating left inside a child window inside a sub-menu. (#4510). - Menus: Fixed an assertion happening in some situations when closing nested menus (broken in 1.83). (#4640) - Drag and Drop: Fixed using BeginDragDropSource() inside a BeginChild() that returned false. (#4515) diff --git a/imgui.cpp b/imgui.cpp index de0fb746..e6f206e7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.85 WIP +// dear imgui, v1.85 // (main code and documentation) // Help: @@ -380,7 +380,7 @@ CODE When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. - - 2021/08/23 (1.85) - removed GetWindowContentRegionWidth() function. keep inline redirection helper. can use 'GetWindowContentRegionMax().x - GetWindowContentRegionMin().x' instead. + - 2021/08/23 (1.85) - removed GetWindowContentRegionWidth() function. keep inline redirection helper. can use 'GetWindowContentRegionMax().x - GetWindowContentRegionMin().x' instead for generally 'GetContentRegionAvail().x' is more useful. - 2021/07/26 (1.84) - commented out redirecting functions/enums names that were marked obsolete in 1.67 and 1.69 (March 2019): - ImGui::GetOverlayDrawList() -> use ImGui::GetForegroundDrawList() - ImFont::GlyphRangesBuilder -> use ImFontGlyphRangesBuilder @@ -9849,7 +9849,7 @@ static int ImGui::FindWindowFocusIndex(ImGuiWindow* window) ImGuiContext& g = *GImGui; IM_UNUSED(g); int order = window->FocusOrder; - IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) == 0); + IM_ASSERT(window->RootWindow == window); // No child window (not testing _ChildWindow because of docking) IM_ASSERT(g.WindowsFocusOrder[order] == window); return order; } diff --git a/imgui.h b/imgui.h index 246e8e28..f2606398 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.85 WIP +// dear imgui, v1.85 // (headers) // Help: @@ -63,8 +63,8 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) -#define IMGUI_VERSION "1.85 WIP" -#define IMGUI_VERSION_NUM 18420 +#define IMGUI_VERSION "1.85" +#define IMGUI_VERSION_NUM 18500 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 69779574..d4bac484 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.85 WIP +// dear imgui, v1.85 // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 0abc75f3..30b100bb 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.85 WIP +// dear imgui, v1.85 // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 291fcaec..fa5dec3e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.85 WIP +// dear imgui, v1.85 // (internal structures/api) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! diff --git a/imgui_tables.cpp b/imgui_tables.cpp index f9ed5ce2..56056ae3 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.85 WIP +// dear imgui, v1.85 // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c138b8cf..7da069b6 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.85 WIP +// dear imgui, v1.85 // (widgets code) /*