diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp
index 62c0cbfcd..f722cbd31 100644
--- a/backends/imgui_impl_sdl2.cpp
+++ b/backends/imgui_impl_sdl2.cpp
@@ -26,6 +26,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
+// 2024-09-09: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190)
// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn
// - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn
@@ -124,7 +125,9 @@
#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6)
#define SDL_HAS_DISPLAY_EVENT SDL_VERSION_ATLEAST(2,0,9)
#define SDL_HAS_SHOW_WINDOW_ACTIVATION_HINT SDL_VERSION_ATLEAST(2,0,18)
-#if !SDL_HAS_VULKAN
+#if SDL_HAS_VULKAN
+extern "C" { extern DECLSPEC void SDLCALL SDL_Vulkan_GetDrawableSize(SDL_Window* window, int* w, int* h); }
+#elif
static const Uint32 SDL_WINDOW_VULKAN = 0x10000000;
#endif
@@ -895,6 +898,10 @@ void ImGui_ImplSDL2_NewFrame()
w = h = 0;
if (bd->Renderer != nullptr)
SDL_GetRendererOutputSize(bd->Renderer, &display_w, &display_h);
+#if SDL_HAS_VULKAN
+ else if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_VULKAN)
+ SDL_Vulkan_GetDrawableSize(bd->Window, &display_w, &display_h);
+#endif
else
SDL_GL_GetDrawableSize(bd->Window, &display_w, &display_h);
io.DisplaySize = ImVec2((float)w, (float)h);
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 6ea6ce862..16a96e733 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,9 +43,29 @@ Breaking changes:
Other changes:
+- Added io.ConfigDebugHighlightIdConflicts debug feature! (#7961, #7669)
+ THIS DETECTS THE MOST COMMON USER ERROR BY FIRST-TIME DEAR IMGUI PROGRAMMERS!
+ - The tool detects when multiple items are sharing the same identifier, due to not
+ using PushID/PopID in loops, or not using ID stack facilities such as "##" suffixes.
+ Very frequently it happens when using empty "" labels.
+ - When hovering an item with a conflicting ID, all visible items with the same ID will
+ be highlighted and an explanatory tooltip is made visible.
+ - The feature may be disabled and is exposed in Demo->Tools menu.
+ - I've been wanting to add this tool for a long time, but was stalled by finding a way to
+ not make it spammy + make it practically zero cost. After @pthom made various proposals to
+ solve the same problem (thanks for pushing me!), I decided it was time to finish it.
+ - Added ImGuiItemFlags_AllowDuplicateId to use with PushItemFlag/PopItemFlag() if for some
+ reason you intend to have duplicate identifiers.
+ - (#74, #96, #480, #501, #647, #654, #719, #843, #894, #1057, #1173, #1390, #1414, #1556, #1768,
+ #2041, #2116, #2330, #2475, #2562, #2667, #2807, #2885, #3102, #3375, #3526, #3964, #4008,
+ #4070, #4158, #4172, #4199, #4375, #4395, #4471, #4548, #4612, #4631, #4657, #4796, #5210,
+ #5303, #5360, #5393, #5533, #5692, #5707, #5729, #5773, #5787, #5884, #6046, #6093, #6186,
+ #6223, #6364, #6387, #6567, #6692, #6724, #6939, #6984, #7246, #7270, #7375, #7421, #7434,
+ #7472, #7581, #7724, #7926, #7937 and probably more..)
- Nav: pressing any keyboard key while holding Alt disable toggling nav layer on Alt release. (#4439)
- InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow.
- TextLinkOpenURL(): modified tooltip to display a verb "Open 'xxxx'". (#7885, #7660)
+- Backends: SDL2: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190) [@scribam]
-----------------------------------------------------------------------
VERSION 1.91.1 (Released 2024-09-04)
diff --git a/docs/FAQ.md b/docs/FAQ.md
index d53a5a099..4e2a42576 100644
--- a/docs/FAQ.md
+++ b/docs/FAQ.md
@@ -204,10 +204,11 @@ ctx->RSSetScissorRects(1, &r);
### Q: How can I have multiple widgets with the same label?
### Q: How can I have multiple windows with the same label?
-**USING THE SAME LABEL+ID IS THE MOST COMMON USER MISTAKE:**
+**USING THE SAME LABEL+ID IS THE MOST COMMON USER MISTAKE!**
+
**USING AN EMPTY LABEL IS THE SAME AS USING THE SAME LABEL AS YOUR PARENT WIDGET!**
+ |
ImGui::Begin("Incorrect!");
diff --git a/imgui.cpp b/imgui.cpp
index 353e2b8cf..8fece262c 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1434,6 +1434,8 @@ ImGuiIO::ImGuiIO()
ConfigWindowsResizeFromEdges = true;
ConfigWindowsMoveFromTitleBarOnly = false;
ConfigMemoryCompactTimer = 60.0f;
+ ConfigDebugIsDebuggerPresent = false;
+ ConfigDebugHighlightIdConflicts = true;
ConfigDebugBeginReturnValueOnce = false;
ConfigDebugBeginReturnValueLoop = false;
@@ -4386,6 +4388,17 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
+
+ // Detect ID conflicts
+#ifndef IMGUI_DISABLE_DEBUG_TOOLS
+ if (id != 0 && g.HoveredIdPreviousFrame == id && (item_flags & ImGuiItemFlags_AllowDuplicateId) == 0)
+ {
+ g.HoveredIdPreviousFrameItemCount++;
+ if (g.DebugDrawIdConflicts == id)
+ window->DrawList->AddRect(bb.Min - ImVec2(1,1), bb.Max + ImVec2(1,1), IM_COL32(255, 0, 0, 255), 0.0f, ImDrawFlags_None, 2.0f);
+ }
+#endif
+
if (g.HoveredWindow != window)
return false;
if (!IsMouseHoveringRect(bb.Min, bb.Max))
@@ -5004,6 +5017,11 @@ void ImGui::NewFrame()
if (g.DragDropActive && g.DragDropPayload.SourceId == g.ActiveId)
KeepAliveID(g.DragDropPayload.SourceId);
+ // [DEBUG]
+ g.DebugDrawIdConflicts = 0;
+ if (g.IO.ConfigDebugHighlightIdConflicts && g.HoveredIdPreviousFrameItemCount > 1)
+ g.DebugDrawIdConflicts = g.HoveredIdPreviousFrame;
+
// Update HoveredId data
if (!g.HoveredIdPreviousFrame)
g.HoveredIdTimer = 0.0f;
@@ -5014,6 +5032,7 @@ void ImGui::NewFrame()
if (g.HoveredId && g.ActiveId != g.HoveredId)
g.HoveredIdNotActiveTimer += g.IO.DeltaTime;
g.HoveredIdPreviousFrame = g.HoveredId;
+ g.HoveredIdPreviousFrameItemCount = 0;
g.HoveredId = 0;
g.HoveredIdAllowOverlap = false;
g.HoveredIdIsDisabled = false;
@@ -5463,6 +5482,29 @@ void ImGui::EndFrame()
return;
IM_ASSERT(g.WithinFrameScope && "Forgot to call ImGui::NewFrame()?");
+#ifndef IMGUI_DISABLE_DEBUG_TOOLS
+ if (g.DebugDrawIdConflicts != 0)
+ {
+ PushStyleColor(ImGuiCol_PopupBg, ImLerp(g.Style.Colors[ImGuiCol_PopupBg], ImVec4(1.0f, 0.0f, 0.0f, 1.0f), 0.10f));
+ if (g.DebugItemPickerActive == false && BeginTooltipEx(ImGuiTooltipFlags_OverridePrevious, ImGuiWindowFlags_None))
+ {
+ SeparatorText("MESSAGE FROM DEAR IMGUI");
+ Text("Programmer error: %d visible items with conflicting ID!", g.HoveredIdPreviousFrameItemCount);
+ BulletText("Code should use PushID()/PopID() in loops, or append \"##xx\" to same-label identifiers!");
+ BulletText("Empty label e.g. Button(\"\") == same ID as parent widget/node. Use Button(\"##xx\") instead!");
+ BulletText("Press F1 to open \"FAQ -> About the ID Stack System\" and read details.");
+ BulletText("Press CTRL+P to activate Item Picker and debug-break in item call-stack.");
+ BulletText("Set io.ConfigDebugDetectIdConflicts=false to disable this warning in non-programmers builds.");
+ EndTooltip();
+ }
+ PopStyleColor();
+ if (Shortcut(ImGuiMod_Ctrl | ImGuiKey_P, ImGuiInputFlags_RouteGlobal))
+ DebugStartItemPicker();
+ if (Shortcut(ImGuiKey_F1, ImGuiInputFlags_RouteGlobal) && g.PlatformIO.Platform_OpenInShellFn != NULL)
+ g.PlatformIO.Platform_OpenInShellFn(&g, "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage");
+ }
+#endif
+
CallContextHooks(&g, ImGuiContextHookType_EndFramePre);
ErrorCheckEndFrameSanityChecks();
diff --git a/imgui.h b/imgui.h
index 0b3294b50..85d201eee 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.91.2 WIP"
-#define IMGUI_VERSION_NUM 19112
+#define IMGUI_VERSION_NUM 19113
#define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch
#define IMGUI_HAS_DOCK // Docking WIP branch
@@ -1174,6 +1174,7 @@ enum ImGuiItemFlags_
ImGuiItemFlags_NoNavDefaultFocus = 1 << 2, // false // Disable item being a candidate for default focus (e.g. used by title bar items).
ImGuiItemFlags_ButtonRepeat = 1 << 3, // false // Any button-like behavior will have repeat mode enabled (based on io.KeyRepeatDelay and io.KeyRepeatRate values). Note that you can also call IsItemActive() after any button to tell if it is being held.
ImGuiItemFlags_AutoClosePopups = 1 << 4, // true // MenuItem()/Selectable() automatically close their parent popup window.
+ ImGuiItemFlags_AllowDuplicateId = 1 << 5, // false // Allow submitting an item with the same identifier as an item already submitted this frame without triggering a warning tooltip if io.ConfigDebugHighlightIdConflicts is set.
};
// Flags for ImGui::InputText()
@@ -2309,6 +2310,7 @@ struct ImGuiIO
const char* LogFilename; // = "imgui_log.txt"// Path to .log file (default parameter to ImGui::LogToFile when no file is specified).
void* UserData; // = NULL // Store your own data.
+ // Font system
ImFontAtlas*Fonts; // |