From ea075ed973edb7b40d3eeadb6a0360599104169c Mon Sep 17 00:00:00 2001 From: Ian Date: Sun, 10 Aug 2025 14:10:42 -0400 Subject: [PATCH 1/6] ImVector: skip memcpy in operator= if Data isn't initialized to play nice with -fsanitize=undefined. (#8874) --- docs/CHANGELOG.txt | 2 ++ imgui.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index def674c2c..42b36e269 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -89,6 +89,8 @@ Other Changes: - Misc: fixed building with IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION. (#8794) - Misc: removed more redundant inline static linkage from imgui_internal.h to facilitate using in C++ modules. (#8813, #8682, #8358) [@stripe2933] +- Misc: ImVector: skip memcpy in operator= if `Data` isn't initialized in order + to play nice with -fsanitize=undefined. (#8874) [@i25e] - CI: Added SDL3 builds to MacOS and Windows. (#8819, #8778) [@scribam] - CI: Updated Windows CI to use a more recent SDL2. (#8819, #8778) [@scribam] - Examples: SDL3+Metal: added SDL3+Metal example. (#8827, #8825) [@shi-yan] diff --git a/imgui.h b/imgui.h index e490658f1..3112184fc 100644 --- a/imgui.h +++ b/imgui.h @@ -2181,7 +2181,7 @@ struct ImVector // Constructors, destructor inline ImVector() { Size = Capacity = 0; Data = NULL; } inline ImVector(const ImVector& src) { Size = Capacity = 0; Data = NULL; operator=(src); } - inline ImVector& operator=(const ImVector& src) { clear(); resize(src.Size); if (src.Data) memcpy(Data, src.Data, (size_t)Size * sizeof(T)); return *this; } + inline ImVector& operator=(const ImVector& src) { clear(); resize(src.Size); if (Data && src.Data) memcpy(Data, src.Data, (size_t)Size * sizeof(T)); return *this; } inline ~ImVector() { if (Data) IM_FREE(Data); } // Important: does not destruct anything inline void clear() { if (Data) { Size = Capacity = 0; IM_FREE(Data); Data = NULL; } } // Important: does not destruct anything From 47c41483bd8936e7a58db25ebd5671ff98b3c32d Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 11 Aug 2025 10:47:55 +0200 Subject: [PATCH 2/6] Tables, Nav: fixed navigation within scrolling tables when item boundaries goes beyond columns limits. (#8816, #2221) Amend 00d3f9295e5caf417886572266bebb490ad3577b. --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 3 ++- imgui_tables.cpp | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 42b36e269..aa0b1db9e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -81,6 +81,9 @@ Other Changes: - Tabs: fixed tab bar underline not drawing below scroll buttons, when they are enabled (minor regression from 1.90). (#6820, #4859, #5022, #5239) - Tabs: made scrolling buttons never keyboard/gamepad navigation candidates. +- Nav, Tables: fixed navigation within scrolling tables when item boundaries + goes beyond columns limits. The fix done in 1.89.6 didn't work correctly + on scrolling windows. (#8816, #2221) - Nav: fixed a bug where GamepadMenu button couldn't toggle between main and menu layers while navigating a Modal window. (#8834) - Error Handling: minor improvements to error handling for TableGetSortSpecs() diff --git a/imgui.cpp b/imgui.cpp index 4b2936d9c..6f9a77497 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -24,7 +24,7 @@ // For first-time users having issues compiling/linking/running: // please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above. // Everything else should be asked in 'Issues'! We are building a database of cross-linked knowledge there. -// Since 1.92, we encourage font loading question to also be posted in 'Issues'. +// Since 1.92, we encourage font loading questions to also be posted in 'Issues'. // Copyright (c) 2014-2025 Omar Cornut // Developed by Omar Cornut and every direct or indirect contributors to the GitHub. @@ -13746,6 +13746,7 @@ void ImGui::NavUpdateCreateMoveRequest() } } + // Prepare scoring rectangle. // For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items) ImRect scoring_rect; if (window != NULL) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index a1504853b..2816707cf 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -542,7 +542,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG // Make table current g.CurrentTable = table; - outer_window->DC.NavIsScrollPushableX = false; // Shortcut for NavUpdateCurrentWindowIsScrollPushableX(); + inner_window->DC.NavIsScrollPushableX = false; // Shortcut for NavUpdateCurrentWindowIsScrollPushableX(); outer_window->DC.CurrentTableIdx = table_idx; if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly. inner_window->DC.CurrentTableIdx = table_idx; From 1c57dc21c26bc6e4b57715d32f50650b305dc02c Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 11 Aug 2025 11:01:13 +0200 Subject: [PATCH 3/6] Misc: fixes zealous MSVC static analyzer warnings + make GetInputSourceName(), GetMouseSourceName() a little more tolerant. (#8876) --- imgui.cpp | 9 +++++++-- imgui_draw.cpp | 3 ++- imgui_widgets.cpp | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6f9a77497..cc5abfc3d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10175,13 +10175,17 @@ void ImGui::SetNextFrameWantCaptureMouse(bool want_capture_mouse) static const char* GetInputSourceName(ImGuiInputSource source) { const char* input_source_names[] = { "None", "Mouse", "Keyboard", "Gamepad" }; - IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT && source >= 0 && source < ImGuiInputSource_COUNT); + IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT); + if (source < 0 || source >= ImGuiInputSource_COUNT) + return "Unknown"; return input_source_names[source]; } static const char* GetMouseSourceName(ImGuiMouseSource source) { const char* mouse_source_names[] = { "Mouse", "TouchScreen", "Pen" }; - IM_ASSERT(IM_ARRAYSIZE(mouse_source_names) == ImGuiMouseSource_COUNT && source >= 0 && source < ImGuiMouseSource_COUNT); + IM_ASSERT(IM_ARRAYSIZE(mouse_source_names) == ImGuiMouseSource_COUNT); + if (source < 0 || source >= ImGuiMouseSource_COUNT) + return "Unknown"; return mouse_source_names[source]; } static void DebugPrintInputEvent(const char* prefix, const ImGuiInputEvent* e) @@ -14157,6 +14161,7 @@ static void ImGui::NavUpdateWindowingApplyFocus(ImGuiWindow* apply_focus_window) SetNavCursorVisibleAfterMove(); ClosePopupsOverWindow(apply_focus_window, false); FocusWindow(apply_focus_window, ImGuiFocusRequestFlags_RestoreFocusedChild); + IM_ASSERT(g.NavWindow != NULL); apply_focus_window = g.NavWindow; if (apply_focus_window->NavLastIds[0] == 0) NavInitWindow(apply_focus_window, false); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 8109ca6e0..a0afce188 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3363,7 +3363,7 @@ void ImFontAtlasBuildMain(ImFontAtlas* atlas) { IM_ASSERT(!atlas->Locked && "Cannot modify a locked ImFontAtlas!"); if (atlas->TexData && atlas->TexData->Format != atlas->TexDesiredFormat) - ImFontAtlasBuildClear(atlas); + ImFontAtlasBuildClear(atlas); if (atlas->Builder == NULL) ImFontAtlasBuildInit(atlas); @@ -4372,6 +4372,7 @@ ImTextureRect* ImFontAtlasPackGetRectSafe(ImFontAtlas* atlas, ImFontAtlasRectId if (atlas->Builder == NULL) ImFontAtlasBuildInit(atlas); ImFontAtlasBuilder* builder = (ImFontAtlasBuilder*)atlas->Builder; + IM_MSVC_WARNING_SUPPRESS(28182); // Static Analysis false positive "warning C28182: Dereferencing NULL pointer 'builder'" if (index_idx >= builder->RectsIndex.Size) return NULL; ImFontAtlasRectEntry* index_entry = &builder->RectsIndex[index_idx]; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 946ac74e2..12ff71385 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -8883,6 +8883,7 @@ void ImGui::EndMenuBar() PopClipRect(); PopID(); + IM_MSVC_WARNING_SUPPRESS(6011); // Static Analysis false positive "warning C6011: Dereferencing NULL pointer 'window'" window->DC.MenuBarOffset.x = window->DC.CursorPos.x - window->Pos.x; // Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos. // FIXME: Extremely confusing, cleanup by (a) working on WorkRect stack system (b) not using a Group confusingly here. From 50115596dccd152309079359339088cfbd4c4cef Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 11 Aug 2025 12:29:13 +0200 Subject: [PATCH 4/6] Demo: About Box: include IMGUI_ENABLE_TEST_ENGINE in Config/Build info. --- imgui_demo.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index eb15dcd1e..3fd05ba0e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -8099,6 +8099,9 @@ void ImGui::ShowAboutWindow(bool* p_open) ImGui::Separator(); ImGui::Text("sizeof(size_t): %d, sizeof(ImDrawIdx): %d, sizeof(ImDrawVert): %d", (int)sizeof(size_t), (int)sizeof(ImDrawIdx), (int)sizeof(ImDrawVert)); ImGui::Text("define: __cplusplus=%d", (int)__cplusplus); +#ifdef IMGUI_ENABLE_TEST_ENGINE + ImGui::Text("define: IMGUI_ENABLE_TEST_ENGINE"); +#endif #ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS"); #endif From 8239a0e0c4c7f670f38a87ad2649222571d6e5b3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 11 Aug 2025 15:17:02 +0200 Subject: [PATCH 5/6] Nav, Tables: fix NavIsScrollPushableX logic clamping value stored in NavApplyItemToResult(), which would break scrolling. (#8816, #2221) Amend 47c4148. --- imgui.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index cc5abfc3d..c67340edd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1291,7 +1291,7 @@ static float NavUpdatePageUpPageDown(); static inline void NavUpdateAnyRequestFlag(); static void NavUpdateCreateWrappingRequest(); static void NavEndFrame(); -static bool NavScoreItem(ImGuiNavItemData* result); +static bool NavScoreItem(ImGuiNavItemData* result, const ImRect& nav_bb); static void NavApplyItemToResult(ImGuiNavItemData* result); static void NavProcessItem(); static void NavProcessItemForTabbingRequest(ImGuiID id, ImGuiItemFlags item_flags, ImGuiNavMoveFlags move_flags); @@ -12870,7 +12870,7 @@ static float inline NavScoreItemDistInterval(float cand_min, float cand_max, flo } // Scoring function for keyboard/gamepad directional navigation. Based on https://gist.github.com/rygorous/6981057 -static bool ImGui::NavScoreItem(ImGuiNavItemData* result) +static bool ImGui::NavScoreItem(ImGuiNavItemData* result, const ImRect& nav_bb) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -12878,7 +12878,7 @@ static bool ImGui::NavScoreItem(ImGuiNavItemData* result) return false; // FIXME: Those are not good variables names - ImRect cand = g.LastItemData.NavRect; // Current item nav rectangle + ImRect cand = nav_bb; // Current item nav rectangle const ImRect curr = g.NavScoringRect; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width) g.NavScoringDebugCount++; @@ -13045,13 +13045,13 @@ static void ImGui::NavProcessItem() const ImGuiID id = g.LastItemData.ID; const ImGuiItemFlags item_flags = g.LastItemData.ItemFlags; - // When inside a container that isn't scrollable with Left<>Right, clip NavRect accordingly (#2221) + // When inside a container that isn't scrollable with Left<>Right, clip NavRect accordingly (#2221, #8816) + ImRect nav_bb = g.LastItemData.NavRect; if (window->DC.NavIsScrollPushableX == false) { - g.LastItemData.NavRect.Min.x = ImClamp(g.LastItemData.NavRect.Min.x, window->ClipRect.Min.x, window->ClipRect.Max.x); - g.LastItemData.NavRect.Max.x = ImClamp(g.LastItemData.NavRect.Max.x, window->ClipRect.Min.x, window->ClipRect.Max.x); + nav_bb.Min.x = ImClamp(nav_bb.Min.x, window->ClipRect.Min.x, window->ClipRect.Max.x); + nav_bb.Max.x = ImClamp(nav_bb.Max.x, window->ClipRect.Min.x, window->ClipRect.Max.x); } - const ImRect nav_bb = g.LastItemData.NavRect; // Process Init Request if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent && (item_flags & ImGuiItemFlags_Disabled) == 0) @@ -13083,14 +13083,14 @@ static void ImGui::NavProcessItem() else if (g.NavId != id || (g.NavMoveFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) { ImGuiNavItemData* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther; - if (NavScoreItem(result)) + if (NavScoreItem(result, nav_bb)) 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)) + if (NavScoreItem(&g.NavMoveResultLocalVisible, nav_bb)) NavApplyItemToResult(&g.NavMoveResultLocalVisible); } } From 5a6fa33b882c1c88c6cd91356ae740640ceaef88 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 11 Aug 2025 15:36:54 +0200 Subject: [PATCH 6/6] Fixed an inconsistency between IsItemHovered() and internal hovering check, where IsItemHovered() would return true if mouse was first clicked on the background of a non-moveable window. (#8877) --- docs/CHANGELOG.txt | 6 ++++++ imgui.cpp | 4 +--- imgui.h | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index aa0b1db9e..cd78ff878 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -49,6 +49,12 @@ Breaking Changes: Other Changes: +- Fixed an inconsistency between IsItemHovered() and internal hovering check, + where IsItemHovered() would return true to mouse was first clicked on the + background of a non-moveable window then moved over the item or button. + Note that while it is consistent with other logic, there is a possibility + that some third-party code may accidentally relied on this. + (#8877) [@achabense, @ocornut] - Fonts: fixed an issue when a font using MergeMode has a reference size specified but the target font doesn't. Usually either all fonts should have a reference size (only required when specifying e.g. GlyphOffset), diff --git a/imgui.cpp b/imgui.cpp index c67340edd..cef058b45 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4656,7 +4656,6 @@ static ImGuiHoveredFlags ApplyHoverFlagsForTooltip(ImGuiHoveredFlags user_flags, } // This is roughly matching the behavior of internal-facing ItemHoverable() -// - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered() // - this should work even for non-interactive items that have no ID, so we cannot use LastItemId bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) { @@ -4698,8 +4697,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) const ImGuiID id = g.LastItemData.ID; if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0) if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap) - if (g.ActiveId != window->MoveId) - return false; + return false; // Test if interactions on this window are blocked by an active popup or modal. // The ImGuiHoveredFlags_AllowWhenBlockedByPopup flag will be tested here. diff --git a/imgui.h b/imgui.h index 3112184fc..95a8001d5 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.92.2 WIP" -#define IMGUI_VERSION_NUM 19214 +#define IMGUI_VERSION_NUM 19215 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198