From 2128e2f44b7ecd0250cfd47921e03d87e4506f4c Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Oct 2025 12:16:48 +0200 Subject: [PATCH 01/50] Style: added ImGuiCol_UnsavedMarker. (#8983) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 3 ++- imgui.h | 1 + imgui_draw.cpp | 3 +++ imgui_widgets.cpp | 4 ++-- 5 files changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 66846d00e..bc6fd0063 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -64,6 +64,8 @@ Other Changes: The grip is not visible before hovering to reduce clutter. - InputText: fixed single-line InputText() not applying fine character clipping properly (regression in 1.92.3). (#8967) [@Cyphall] +- Style: added ImGuiCol_UnsavedMarker, color of the unsaved document marker when + using ImGuiWindowFlags_UnsavedDocument/ImGuiTabItemFlags_UnsavedDocument. (#8983) - IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers() helpers to null all handlers. (#8945, #2769) - Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode, diff --git a/imgui.cpp b/imgui.cpp index 8928335aa..6b501f343 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3693,6 +3693,7 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx) case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; case ImGuiCol_TreeLines: return "TreeLines"; case ImGuiCol_DragDropTarget: return "DragDropTarget"; + case ImGuiCol_UnsavedMarker: return "UnsavedMarker"; case ImGuiCol_NavCursor: return "NavCursor"; case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight"; case ImGuiCol_NavWindowingDimBg: return "NavWindowingDimBg"; @@ -7169,7 +7170,7 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl marker_pos.y = (layout_r.Min.y + layout_r.Max.y) * 0.5f; if (marker_pos.x > layout_r.Min.x) { - RenderBullet(window->DrawList, marker_pos, GetColorU32(ImGuiCol_Text)); + RenderBullet(window->DrawList, marker_pos, GetColorU32(ImGuiCol_UnsavedMarker)); clip_r.Max.x = ImMin(clip_r.Max.x, marker_pos.x - (int)(marker_size_x * 0.5f)); } } diff --git a/imgui.h b/imgui.h index b006023a2..9589fa561 100644 --- a/imgui.h +++ b/imgui.h @@ -1774,6 +1774,7 @@ enum ImGuiCol_ ImGuiCol_TextSelectedBg, // Selected text inside an InputText ImGuiCol_TreeLines, // Tree node hierarchy outlines when using ImGuiTreeNodeFlags_DrawLines ImGuiCol_DragDropTarget, // Rectangle highlighting a drop target + ImGuiCol_UnsavedMarker, // Unsaved Document marker (in window title and tabs) ImGuiCol_NavCursor, // Color of keyboard/gamepad navigation cursor/rectangle, when visible ImGuiCol_NavWindowingHighlight, // Highlight window when using CTRL+TAB ImGuiCol_NavWindowingDimBg, // Darken/colorize entire screen behind the CTRL+TAB window list, when active diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 082af59ac..a2c616012 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -240,6 +240,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst) colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border]; colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); + colors[ImGuiCol_UnsavedMarker] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); colors[ImGuiCol_NavCursor] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); @@ -305,6 +306,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst) colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border]; colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); + colors[ImGuiCol_UnsavedMarker] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); colors[ImGuiCol_NavCursor] = colors[ImGuiCol_HeaderHovered]; colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); @@ -371,6 +373,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst) colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border]; colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); + colors[ImGuiCol_UnsavedMarker] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); colors[ImGuiCol_NavCursor] = colors[ImGuiCol_HeaderHovered]; colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.70f, 0.70f, 0.70f, 0.70f); colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.20f); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 592a76904..45a4dcf62 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -10716,8 +10716,8 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, const bool unsaved_marker_visible = (flags & ImGuiTabItemFlags_UnsavedDocument) != 0 && (button_pos.x + button_sz <= bb.Max.x) && (!close_button_visible || !is_hovered); if (unsaved_marker_visible) { - const ImRect bullet_bb(button_pos, button_pos + ImVec2(button_sz, button_sz)); - RenderBullet(draw_list, bullet_bb.GetCenter(), GetColorU32(ImGuiCol_Text)); + ImVec2 bullet_pos = button_pos + ImVec2(button_sz, button_sz) * 0.5f; + RenderBullet(draw_list, bullet_pos, GetColorU32(ImGuiCol_UnsavedMarker)); } else if (close_button_visible) { From 09e15e8c9dd1c5a780d51c8f7c8ddfdb9d400e84 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Oct 2025 13:55:54 +0200 Subject: [PATCH 02/50] Nav: fixed typo. --- imgui_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_internal.h b/imgui_internal.h index fe79a862f..c2d858580 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2306,7 +2306,7 @@ struct ImGuiContext float NavHighlightActivatedTimer; ImGuiID NavNextActivateId; // Set by ActivateItemByID(), queued until next frame. ImGuiActivateFlags NavNextActivateFlags; - ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Mouse + ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Gamepad ImGuiSelectionUserData NavLastValidSelectionUserData; // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data. ImS8 NavCursorHideFrames; //ImGuiID NavActivateInputId; // Removed in 1.89.4 (July 2023). This is now part of g.NavActivateId and sets g.NavActivateFlags |= ImGuiActivateFlags_PreferInput. See commit c9a53aa74, issue #5606. From 4b858cf5d1327fa5e3a84ae8044ff2026f3a43d3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Oct 2025 16:55:11 +0200 Subject: [PATCH 03/50] Made tooltip windows inherit parent. (#8982, #1345) Intent here was for a manually focused tooltip to not steal title bar highlight. --- imgui.cpp | 4 ++-- imgui.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6b501f343..2ba3aacd9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7187,7 +7187,7 @@ void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags window->RootWindow = parent_window->RootWindow; if (parent_window && (flags & ImGuiWindowFlags_Popup)) window->RootWindowPopupTree = parent_window->RootWindowPopupTree; - if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) + if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip))) window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight; while (window->RootWindowForNav->ChildFlags & ImGuiChildFlags_NavFlattened) { @@ -7296,7 +7296,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack ImGuiWindow* parent_window_in_stack = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back().Window; - ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow; + ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) ? parent_window_in_stack : NULL) : window->ParentWindow; IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); // We allow window memory to be compacted so recreate the base stack when needed. diff --git a/imgui.h b/imgui.h index 9589fa561..24c6423b4 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.4 WIP" -#define IMGUI_VERSION_NUM 19234 +#define IMGUI_VERSION_NUM 19235 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198 From ee3d16f15070b4de6656cc68e39e89fa9a469436 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Oct 2025 18:39:10 +0200 Subject: [PATCH 04/50] Demo: fixed layout issue in "Layout & Scrolling -> Scrolling" section. --- docs/CHANGELOG.txt | 13 +++++++------ imgui_demo.cpp | 15 +++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index bc6fd0063..496bf1d9f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,9 +68,6 @@ Other Changes: using ImGuiWindowFlags_UnsavedDocument/ImGuiTabItemFlags_UnsavedDocument. (#8983) - IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers() helpers to null all handlers. (#8945, #2769) -- Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode, - Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc. - See misc/debuggers/ for details. (#8950) [@mentlerd] - Textures: fixed a crash if texture status is set to _WantDestroy by a backend after it had already been destroyed. This would typically happen when calling backend's ImGui_ImplXXXX_InvalidateDeviceObjects() helpers twice in a row. (#8977, #8811) @@ -83,12 +80,16 @@ Other Changes: - Textures: fixed not updating ImTextureData's RefCount when destroying a context using a shared ImFontAtlas, leading standard backends to not properly free texture resources. (#8975) [@icrashstuff] -- CI: Updates Windows CI scripts to generate/use VulkanSDK. (#8925, #8778) [@yaz0r] +- Demo: fixed layout issue in "Layout & Scrolling -> Scrolling" section. +- Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode, + Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc. + See misc/debuggers/ for details. (#8950) [@mentlerd] +- CI: updated Windows CI scripts to generate/use VulkanSDK. (#8925, #8778) [@yaz0r] +- Docs: updated FAQ with new "What is the difference between Dear ImGui and + traditional UI toolkits?" entry. (#8862) - Backends: all backends call ImGuiPlatformIO::ClearPlatformHandlers() and ClearRendererHandlers() on shutdown, so as not to leave function pointers which may be dangling when using backend in e.g. DLL. (#8945, #2769) -- Docs: updated FAQ with new "What is the difference between Dear ImGui and - traditional UI toolkits?" entry. (#8862) - Backends: DirectX12: reuse a command list and allocator for texture uploads instead of recreating them each time. (#8963, #8465) [@RT2Code] - Backends: DirectX12: Rework synchronization logic. (#8961) [@RT2Code] diff --git a/imgui_demo.cpp b/imgui_demo.cpp index e3991a60e..3a6bcf5a5 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -4795,15 +4795,18 @@ static void DemoWindowLayout() ImGui::Checkbox("Decoration", &enable_extra_decorations); + ImGui::PushItemWidth(ImGui::GetFontSize() * 10); + enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d"); + ImGui::SameLine(); ImGui::Checkbox("Track", &enable_track); - ImGui::PushItemWidth(100); - ImGui::SameLine(140); enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d"); - bool scroll_to_off = ImGui::Button("Scroll Offset"); - ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, FLT_MAX, "+%.0f px"); + bool scroll_to_off = ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, FLT_MAX, "+%.0f px"); + ImGui::SameLine(); + scroll_to_off |= ImGui::Button("Scroll Offset"); - bool scroll_to_pos = ImGui::Button("Scroll To Pos"); - ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px"); + bool scroll_to_pos = ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px");; + ImGui::SameLine(); + scroll_to_pos |= ImGui::Button("Scroll To Pos"); ImGui::PopItemWidth(); if (scroll_to_off || scroll_to_pos) From fd0873c61ffc3e41415e00441ced4d2e1905553c Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 7 Oct 2025 15:59:45 +0200 Subject: [PATCH 05/50] Test Engine: fixed mismatched macro signature when disabled. The macro was actually unused in our code if IMGUI_ENABLE_TEST_ENGINE is not defined, but can affect third-party code. --- imgui_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_internal.h b/imgui_internal.h index c2d858580..e65cbcab7 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3921,7 +3921,7 @@ extern const char* ImGuiTestEngine_FindItemDebugLabel(ImGuiContext* ctx, ImGuiI #define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional) #define IMGUI_TEST_ENGINE_LOG(_FMT,...) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log #else -#define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) ((void)0) +#define IMGUI_TEST_ENGINE_ITEM_ADD(_ID,_BB,_ITEM_DATA) ((void)0) #define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) ((void)g) #endif From bee2720faac5f33401fcda7fa9eb51113d13e8d6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 8 Oct 2025 18:44:07 +0200 Subject: [PATCH 06/50] Docs: clarify meaning/purpose of IMGUI_ENABLE_FREETYPE. (#8993) --- imconfig.h | 1 + misc/freetype/README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/imconfig.h b/imconfig.h index 4dab1b604..0e7cf6182 100644 --- a/imconfig.h +++ b/imconfig.h @@ -83,6 +83,7 @@ //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). +// Note that imgui_freetype.cpp may be used _without_ this define, if you manually call ImFontAtlas::SetFontLoader(). The define is simply a convenience. // On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'. //#define IMGUI_ENABLE_FREETYPE diff --git a/misc/freetype/README.md b/misc/freetype/README.md index e1bd0198b..6ea6ad1ae 100644 --- a/misc/freetype/README.md +++ b/misc/freetype/README.md @@ -7,7 +7,7 @@ Build font atlases using FreeType instead of stb_truetype (which is the default 1. Get latest FreeType binaries or build yourself (under Windows you may use vcpkg with `vcpkg install freetype --triplet=x64-windows`, `vcpkg integrate install`). 2. Add imgui_freetype.h/cpp alongside your project files. -3. Add `#define IMGUI_ENABLE_FREETYPE` in your [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) file +3. Add `#define IMGUI_ENABLE_FREETYPE` in your [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) file to make Dear ImGui automatically use the imgui_freetype loader. If your copy Dear ImGui is precompiled, you can always enable imgui_freetype by calling ImFontAtlas::SetFontLoader(). ### About Gamma Correct Blending From 2b770a029ba01b78c6e27d6fc74de308eaefb634 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 8 Oct 2025 19:00:34 +0200 Subject: [PATCH 07/50] InputText: fixed an infinite loop error happening if a custom input text callback modifies/clear BufTextLen before calling InsertChars(). (#8994, #3237) + misc comments. --- docs/CHANGELOG.txt | 5 +++++ imgui_demo.cpp | 2 +- imgui_internal.h | 2 +- imgui_widgets.cpp | 8 +++++--- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 496bf1d9f..9c5b50988 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -64,6 +64,11 @@ Other Changes: The grip is not visible before hovering to reduce clutter. - InputText: fixed single-line InputText() not applying fine character clipping properly (regression in 1.92.3). (#8967) [@Cyphall] +- InputText: fixed an infinite loop error happening if a custom input text + callback modifies/clear BufTextLen before calling InsertChars(). + (regression from 1.92.3). Note that this never really worked correctly, but + previously it would only temporary wreck cursor position, and since 1.92.3 it + would go in an infinite loop. (#8994, #3237) - Style: added ImGuiCol_UnsavedMarker, color of the unsaved document marker when using ImGuiWindowFlags_UnsavedDocument/ImGuiTabItemFlags_UnsavedDocument. (#8983) - IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers() diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3a6bcf5a5..dec1bad40 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -4804,7 +4804,7 @@ static void DemoWindowLayout() ImGui::SameLine(); scroll_to_off |= ImGui::Button("Scroll Offset"); - bool scroll_to_pos = ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px");; + bool scroll_to_pos = ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px"); ImGui::SameLine(); scroll_to_pos |= ImGui::Button("Scroll To Pos"); ImGui::PopItemWidth(); diff --git a/imgui_internal.h b/imgui_internal.h index e65cbcab7..1510271a0 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2484,7 +2484,7 @@ struct ImGuiContext ImGuiWindow* LogWindow; ImFileHandle LogFile; // If != NULL log to stdout/ file ImGuiTextBuffer LogBuffer; // Accumulation buffer when log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators. - const char* LogNextPrefix; + const char* LogNextPrefix; // See comment in LogSetNextTextDecoration(): doesn't copy underlying data, use carefully! const char* LogNextSuffix; float LogLinePosY; bool LogLineFirstItem; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 45a4dcf62..a3a4ae1cf 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3941,6 +3941,7 @@ static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, c { ImGuiContext& g = *ctx; ImGuiInputTextState* obj = &g.InputTextState; + IM_ASSERT(text_end_display >= text_begin && text_end_display <= text_end); return ImFontCalcTextSizeEx(g.Font, g.FontSize, FLT_MAX, obj->WrapWidth, text_begin, text_end_display, text_end, out_remaining, out_offset, flags); } @@ -4321,11 +4322,12 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char)); Buf[BufTextLen + new_text_len] = '\0'; - if (CursorPos >= pos) - CursorPos += new_text_len; - SelectionStart = SelectionEnd = CursorPos; BufDirty = true; BufTextLen += new_text_len; + if (CursorPos >= pos) + CursorPos += new_text_len; + CursorPos = ImClamp(CursorPos, 0, BufTextLen); + SelectionStart = SelectionEnd = CursorPos; } void ImGui::PushPasswordFont() From 5af650fc6d27daf585edbd9ac872465f756a65e9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 9 Oct 2025 18:54:16 +0200 Subject: [PATCH 08/50] Examples: GLFW+WGPU: various tweaks to reduce diff with #8381 --- backends/imgui_impl_wgpu.cpp | 2 +- backends/imgui_impl_wgpu.h | 2 +- examples/example_glfw_wgpu/main.cpp | 63 ++++++++++++++++------------- 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 9f731c8f1..3045f9c7c 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -46,7 +46,7 @@ #include "imgui.h" -// When targeting native platforms (i.e. NOT emscripten), one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN +// When targeting native platforms (i.e. NOT Emscripten), one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN // or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details. #ifndef __EMSCRIPTEN__ #if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) == defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) diff --git a/backends/imgui_impl_wgpu.h b/backends/imgui_impl_wgpu.h index 61d2d23c0..499c899a0 100644 --- a/backends/imgui_impl_wgpu.h +++ b/backends/imgui_impl_wgpu.h @@ -32,7 +32,7 @@ // Initialization data, for ImGui_ImplWGPU_Init() struct ImGui_ImplWGPU_InitInfo { - WGPUDevice Device; + WGPUDevice Device = nullptr; int NumFramesInFlight = 3; WGPUTextureFormat RenderTargetFormat = WGPUTextureFormat_Undefined; WGPUTextureFormat DepthStencilFormat = WGPUTextureFormat_Undefined; diff --git a/examples/example_glfw_wgpu/main.cpp b/examples/example_glfw_wgpu/main.cpp index 670dd08c2..59bb505a9 100644 --- a/examples/example_glfw_wgpu/main.cpp +++ b/examples/example_glfw_wgpu/main.cpp @@ -1,4 +1,4 @@ -// Dear ImGui: standalone example application for using GLFW + WebGPU +// Dear ImGui: standalone example application for GLFW + WebGPU // - Emscripten is supported for publishing on web. See https://emscripten.org. // - Dawn is used as a WebGPU implementation on desktop. @@ -12,36 +12,32 @@ #include "imgui_impl_glfw.h" #include "imgui_impl_wgpu.h" #include +#include +// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details. #ifdef __EMSCRIPTEN__ #include #include #include +#include "../libs/emscripten/emscripten_mainloop_stub.h" #else #include #endif - -#include #include #include -// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details. -#ifdef __EMSCRIPTEN__ -#include "../libs/emscripten/emscripten_mainloop_stub.h" -#endif - -// Global WebGPU required states +// Data static WGPUInstance wgpu_instance = nullptr; static WGPUDevice wgpu_device = nullptr; static WGPUSurface wgpu_surface = nullptr; static WGPUTextureFormat wgpu_preferred_fmt = WGPUTextureFormat_RGBA8Unorm; static WGPUSwapChain wgpu_swap_chain = nullptr; -static int wgpu_swap_chain_width = 1280; -static int wgpu_swap_chain_height = 800; +static int wgpu_surface_width = 1280; +static int wgpu_surface_height = 800; // Forward declarations static bool InitWGPU(GLFWwindow* window); -static void CreateSwapChain(int width, int height); +static void ResizeSurface(int width, int height); static void glfw_error_callback(int error, const char* description) { @@ -72,19 +68,23 @@ int main(int, char**) // Make sure GLFW does not initialize any graphics context. // This needs to be done explicitly later. glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - GLFWwindow* window = glfwCreateWindow(wgpu_swap_chain_width, wgpu_swap_chain_height, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr); + + // Create window + float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only + wgpu_surface_width *= main_scale; + wgpu_surface_height *= main_scale; + GLFWwindow* window = glfwCreateWindow(wgpu_surface_width, wgpu_surface_height, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr); if (window == nullptr) return 1; // Initialize the WebGPU environment if (!InitWGPU(window)) { - if (window) - glfwDestroyWindow(window); + glfwDestroyWindow(window); glfwTerminate(); return 1; } - CreateSwapChain(wgpu_swap_chain_width, wgpu_swap_chain_height); + ResizeSurface(wgpu_surface_width, wgpu_surface_height); glfwShowWindow(window); // Setup Dear ImGui context @@ -98,6 +98,11 @@ int main(int, char**) ImGui::StyleColorsDark(); //ImGui::StyleColorsLight(); + // Setup scaling + ImGuiStyle& style = ImGui::GetStyle(); + style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again) + style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose) + // Setup Platform/Renderer backends ImGui_ImplGlfw_InitForOther(window, true); #ifdef __EMSCRIPTEN__ @@ -117,15 +122,14 @@ int main(int, char**) // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering. // - Read 'docs/FONTS.md' for more instructions and details. If you like the default font but want it to scale better, consider using the 'ProggyVector' from the same author! // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! - // - Emscripten allows preloading a file or folder to be accessible at runtime. See Makefile for details. - //io.Fonts->AddFontDefault(); + // - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details. //style.FontSizeBase = 20.0f; + //io.Fonts->AddFontDefault(); #ifndef IMGUI_DISABLE_FILE_FUNCTIONS //io.Fonts->AddFontFromFileTTF("fonts/segoeui.ttf"); //io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf"); //io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf"); //io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf"); - //io.Fonts->AddFontFromFileTTF("fonts/ProggyTiny.ttf"); //ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf"); //IM_ASSERT(font != nullptr); #endif @@ -160,10 +164,10 @@ int main(int, char**) // React to changes in screen size int width, height; glfwGetFramebufferSize((GLFWwindow*)window, &width, &height); - if (width != wgpu_swap_chain_width || height != wgpu_swap_chain_height) + if (width != wgpu_surface_width || height != wgpu_surface_height) { ImGui_ImplWGPU_InvalidateDeviceObjects(); - CreateSwapChain(width, height); + ResizeSurface(width, height); ImGui_ImplWGPU_CreateDeviceObjects(); } @@ -238,8 +242,8 @@ int main(int, char**) WGPUCommandBufferDescriptor cmd_buffer_desc = {}; WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc); - WGPUQueue queue = wgpuDeviceGetQueue(wgpu_device); - wgpuQueueSubmit(queue, 1, &cmd_buffer); + WGPUQueue wgpu_queue = wgpuDeviceGetQueue(wgpu_device); + wgpuQueueSubmit(wgpu_queue, 1, &cmd_buffer); #ifndef __EMSCRIPTEN__ wgpuSwapChainPresent(wgpu_swap_chain); @@ -311,10 +315,10 @@ static bool InitWGPU(GLFWwindow* window) #endif #ifdef __EMSCRIPTEN__ - wgpu::SurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {}; - html_surface_desc.selector = "#canvas"; + wgpu::SurfaceDescriptorFromCanvasHTMLSelector canvas_desc = {}; + canvas_desc.selector = "#canvas"; wgpu::SurfaceDescriptor surface_desc = {}; - surface_desc.nextInChain = &html_surface_desc; + surface_desc.nextInChain = &canvas_desc; wgpu::Surface surface = instance.CreateSurface(&surface_desc); wgpu::Adapter adapter = {}; @@ -326,6 +330,7 @@ static bool InitWGPU(GLFWwindow* window) wgpu_preferred_fmt = WGPUTextureFormat_BGRA8Unorm; #endif + // Moving Dawn objects into WGPU handles wgpu_instance = instance.MoveToCHandle(); wgpu_surface = surface.MoveToCHandle(); @@ -334,12 +339,12 @@ static bool InitWGPU(GLFWwindow* window) return true; } -static void CreateSwapChain(int width, int height) +static void ResizeSurface(int width, int height) { if (wgpu_swap_chain) wgpuSwapChainRelease(wgpu_swap_chain); - wgpu_swap_chain_width = width; - wgpu_swap_chain_height = height; + wgpu_surface_width = width; + wgpu_surface_height = height; WGPUSwapChainDescriptor swap_chain_desc = {}; swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment; swap_chain_desc.format = wgpu_preferred_fmt; From 8de97d14d8f43e23d30a06aca15bbf3dad121374 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 10 Oct 2025 18:31:20 +0200 Subject: [PATCH 09/50] Backends: DX10, DX11: avoid ImGui_ImplXXXX_SwapBuffers() handlers for secondary viewports crashing if SwapChain could not be created. It's not really clear when that would fail but someone privately reported, and since we allow failure in ImGui_ImplDX11_CreateWindow() it makes sense to allow it here. --- backends/imgui_impl_dx10.cpp | 3 ++- backends/imgui_impl_dx11.cpp | 3 ++- docs/CHANGELOG.txt | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp index 376ed38b1..cff86fd0f 100644 --- a/backends/imgui_impl_dx10.cpp +++ b/backends/imgui_impl_dx10.cpp @@ -770,7 +770,8 @@ static void ImGui_ImplDX10_RenderViewport(ImGuiViewport* viewport, void*) static void ImGui_ImplDX10_SwapBuffers(ImGuiViewport* viewport, void*) { ImGui_ImplDX10_ViewportData* vd = (ImGui_ImplDX10_ViewportData*)viewport->RendererUserData; - vd->SwapChain->Present(0, 0); // Present without vsync + if (vd->SwapChain) + vd->SwapChain->Present(0, 0); // Present without vsync } void ImGui_ImplDX10_InitMultiViewportSupport() diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp index 33751bfeb..d6b99a9f6 100644 --- a/backends/imgui_impl_dx11.cpp +++ b/backends/imgui_impl_dx11.cpp @@ -800,7 +800,8 @@ static void ImGui_ImplDX11_RenderWindow(ImGuiViewport* viewport, void*) static void ImGui_ImplDX11_SwapBuffers(ImGuiViewport* viewport, void*) { ImGui_ImplDX11_ViewportData* vd = (ImGui_ImplDX11_ViewportData*)viewport->RendererUserData; - vd->SwapChain->Present(0, 0); // Present without vsync + if (vd->SwapChain) + vd->SwapChain->Present(0, 0); // Present without vsync } static void ImGui_ImplDX11_InitMultiViewportSupport() diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3cc0d2a1b..4a2a841e4 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -142,6 +142,8 @@ Docking+Viewports Branch: backends have been shutdown since 1.90.4. Changed into asserts. (#7175, #8945) - Backends: DX10, DX11, DX12: Disabled DXGI's Alt+Enter default behavior on secondary viewports managed by the backend. (#4350) [@PathogenDavid] +- Backends: DX10, DX11: avoid ImGui_ImplXXXX_SwapBuffers() handlers for secondary + viewports crashing if SwapChain could not be created. - Backends: Vulkan: Added a way to configure secondary viewport pipelinen creation by setting init_info.PipelineInfoForViewports fields. (#8946, #8110, #8111, #8686) - Backends: Vulkan: Added a way to configure secondary viewport swapchain VkImageUsageFlags From 00251c8921bbc08092e472ad40ffedbca81e00db Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Oct 2025 12:01:10 +0200 Subject: [PATCH 10/50] CI: disable PVS-Studio's --disableLicenseExpirationCheck --- .github/workflows/static-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index a69c5110c..53db04764 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -42,5 +42,5 @@ jobs: fi cd examples/example_null pvs-studio-analyzer trace -- make WITH_EXTRA_WARNINGS=1 - pvs-studio-analyzer analyze --disableLicenseExpirationCheck -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log + pvs-studio-analyzer analyze -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log plog-converter -a 'GA:1,2;OP:1' -d V1071 -t errorfile -w pvs-studio.log From 8d9c90391937e389ed19a8abd96a5ec08c8876c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Tassoux?= Date: Mon, 13 Oct 2025 13:10:01 +0200 Subject: [PATCH 11/50] Backends: DirectX12: remove unused members. (#8998) Unused in docking branch. Leftover from a merge. --- backends/imgui_impl_dx12.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 931e8e2fb..506e1731b 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -112,9 +112,6 @@ struct ImGui_ImplDX12_Data ID3D12CommandAllocator* pTexCmdAllocator; ID3D12GraphicsCommandList* pTexCmdList; - ImGui_ImplDX12_RenderBuffers* pFrameResources; - UINT frameIndex; - ImGui_ImplDX12_Data() { memset((void*)this, 0, sizeof(*this)); } }; From 9be4f150ef4c4561eaf8b4abc7ac34ccf2278995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Tassoux?= Date: Fri, 10 Oct 2025 17:56:31 +0200 Subject: [PATCH 12/50] Backends: DirectX12: Reuse texture upload buffer and grow it only when necessary. (#9002) --- backends/imgui_impl_dx12.cpp | 84 ++++++++++++++++++++++-------------- docs/CHANGELOG.txt | 2 + 2 files changed, 53 insertions(+), 33 deletions(-) diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 1e122a76e..d4da6ab02 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-10-11: DirectX12: Reuse texture upload buffer and grow it only when necessary. (#9002) // 2025-09-29: DirectX12: Rework synchronization logic. (#8961) // 2025-09-29: DirectX12: Enable swapchain tearing to eliminate viewports framerate throttling. (#8965) // 2025-09-29: DirectX12: Reuse a command list and allocator for texture uploads instead of recreating them each time. (#8963) @@ -108,6 +109,9 @@ struct ImGui_ImplDX12_Data ID3D12CommandAllocator* pTexCmdAllocator; ID3D12GraphicsCommandList* pTexCmdList; + ID3D12Resource* pTexUploadBuffer; + UINT pTexUploadBufferSize; + void* pTexUploadBufferMapped; ImGui_ImplDX12_RenderBuffers* pFrameResources; UINT frameIndex; @@ -438,44 +442,53 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex) UINT upload_pitch_dst = (upload_pitch_src + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u); UINT upload_size = upload_pitch_dst * upload_h; - D3D12_RESOURCE_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - desc.Alignment = 0; - desc.Width = upload_size; - desc.Height = 1; - desc.DepthOrArraySize = 1; - desc.MipLevels = 1; - desc.Format = DXGI_FORMAT_UNKNOWN; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - desc.Flags = D3D12_RESOURCE_FLAG_NONE; + if (bd->pTexUploadBuffer == nullptr || upload_size > bd->pTexUploadBufferSize) + { + if (bd->pTexUploadBufferMapped) + { + D3D12_RANGE range = { 0, bd->pTexUploadBufferSize }; + bd->pTexUploadBuffer->Unmap(0, &range); + bd->pTexUploadBufferMapped = nullptr; + } + SafeRelease(bd->pTexUploadBuffer); - D3D12_HEAP_PROPERTIES props; - memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES)); - props.Type = D3D12_HEAP_TYPE_UPLOAD; - props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; - props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + D3D12_RESOURCE_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + desc.Alignment = 0; + desc.Width = upload_size; + desc.Height = 1; + desc.DepthOrArraySize = 1; + desc.MipLevels = 1; + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + desc.Flags = D3D12_RESOURCE_FLAG_NONE; - // FIXME-OPT: Could upload buffer be kept around, reused, and grown only when needed? Would that be worth it? - ID3D12Resource* uploadBuffer = nullptr; - HRESULT hr = bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, - D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&uploadBuffer)); - IM_ASSERT(SUCCEEDED(hr)); + D3D12_HEAP_PROPERTIES props; + memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES)); + props.Type = D3D12_HEAP_TYPE_UPLOAD; + props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + + HRESULT hr = bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, + D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&bd->pTexUploadBuffer)); + IM_ASSERT(SUCCEEDED(hr)); + + D3D12_RANGE range = {0, upload_size}; + hr = bd->pTexUploadBuffer->Map(0, &range, &bd->pTexUploadBufferMapped); + IM_ASSERT(SUCCEEDED(hr)); + bd->pTexUploadBufferSize = upload_size; + } bd->pTexCmdAllocator->Reset(); bd->pTexCmdList->Reset(bd->pTexCmdAllocator, nullptr); ID3D12GraphicsCommandList* cmdList = bd->pTexCmdList; // Copy to upload buffer - void* mapped = nullptr; - D3D12_RANGE range = { 0, upload_size }; - hr = uploadBuffer->Map(0, &range, &mapped); - IM_ASSERT(SUCCEEDED(hr)); for (int y = 0; y < upload_h; y++) - memcpy((void*)((uintptr_t)mapped + y * upload_pitch_dst), tex->GetPixelsAt(upload_x, upload_y + y), upload_pitch_src); - uploadBuffer->Unmap(0, &range); + memcpy((void*)((uintptr_t)bd->pTexUploadBufferMapped + y * upload_pitch_dst), tex->GetPixelsAt(upload_x, upload_y + y), upload_pitch_src); if (need_barrier_before_copy) { @@ -492,7 +505,7 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex) D3D12_TEXTURE_COPY_LOCATION srcLocation = {}; D3D12_TEXTURE_COPY_LOCATION dstLocation = {}; { - srcLocation.pResource = uploadBuffer; + srcLocation.pResource = bd->pTexUploadBuffer; srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; srcLocation.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srcLocation.PlacedFootprint.Footprint.Width = upload_w; @@ -516,9 +529,8 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex) cmdList->ResourceBarrier(1, &barrier); } - hr = cmdList->Close(); + HRESULT hr = cmdList->Close(); IM_ASSERT(SUCCEEDED(hr)); - ID3D12CommandQueue* cmdQueue = bd->pCommandQueue; cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&cmdList); hr = cmdQueue->Signal(bd->Fence, ++bd->FenceLastSignaledValue); @@ -531,7 +543,6 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex) bd->Fence->SetEventOnCompletion(bd->FenceLastSignaledValue, bd->FenceEvent); ::WaitForSingleObject(bd->FenceEvent, INFINITE); - uploadBuffer->Release(); tex->SetStatus(ImTextureStatus_OK); } @@ -804,6 +815,13 @@ void ImGui_ImplDX12_InvalidateDeviceObjects() bd->commandQueueOwned = false; SafeRelease(bd->pRootSignature); SafeRelease(bd->pPipelineState); + if (bd->pTexUploadBufferMapped) + { + D3D12_RANGE range = { 0, bd->pTexUploadBufferSize }; + bd->pTexUploadBuffer->Unmap(0, &range); + bd->pTexUploadBufferMapped = nullptr; + } + SafeRelease(bd->pTexUploadBuffer); SafeRelease(bd->pTexCmdList); SafeRelease(bd->pTexCmdAllocator); SafeRelease(bd->Fence); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9c5b50988..e72b81462 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -99,6 +99,8 @@ Other Changes: of recreating them each time. (#8963, #8465) [@RT2Code] - Backends: DirectX12: Rework synchronization logic. (#8961) [@RT2Code] (presumably fixes old hard-to-repro crash issues such as #3463, #5018) +- Backends: DirectX12: Reuse texture upload buffer and grow it only when + necessary. (#9002) [@RT2Code] - Backends: DirectX12: Enable swapchain tearing if available. (#8965) [@RT2Code] - Backends: OpenGL3: fixed GL loader to work on Haiku OS which does not support `RTLD_NOLOAD`. (#8952) [@Xottab-DUTY, @threedeyes] From 878c863af4cdef451d9da92df4a3078694574411 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Oct 2025 13:25:02 +0200 Subject: [PATCH 13/50] Docs: reformat changlog entries. --- docs/CHANGELOG.txt | 135 +++++++++++++++++++++++---------------------- 1 file changed, 70 insertions(+), 65 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e72b81462..409bcb11d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,50 +41,53 @@ HOW TO UPDATE? Breaking Changes: -- Backends: Vulkan: moved some fields in ImGui_ImplVulkan_InitInfo: - init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass - init_info.Subpass --> init_info.PipelineInfoMain.Subpass - init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples - init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo - It makes things more consistent and was desirable to introduce new settings for - secondary viewports. (#8946, #8110, #8111, #8686) [@ocornut, @SuperRonan, @sylmroz] -- Backends: Vulkan: renamed ImGui_ImplVulkan_MainPipelineCreateInfo --> ImGui_ImplVulkan_PipelineInfo - (introduced very recently and only used by `ImGui_ImplVulkan_CreateMainPipeline()` - so it should not affect many users). (#8110, #8111) -- Backends: Vulkan: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a - `VkImageUsageFlags image_usage` argument. - It was previously hardcoded to `VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT` and defaults - to that when the value is 0. In theory the function is an internal helper but - since it's used by our examples some may have used it. (#8946, #8111, #8686) +- Backends: + - Vulkan: moved some fields in ImGui_ImplVulkan_InitInfo: + init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass + init_info.Subpass --> init_info.PipelineInfoMain.Subpass + init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples + init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo + It makes things more consistent and was desirable to introduce new settings for + secondary viewports. (#8946, #8110, #8111, #8686) [@ocornut, @SuperRonan, @sylmroz] + - Vulkan: renamed ImGui_ImplVulkan_MainPipelineCreateInfo --> ImGui_ImplVulkan_PipelineInfo + (introduced very recently and only used by `ImGui_ImplVulkan_CreateMainPipeline()` + so it should not affect many users). (#8110, #8111) + - Vulkan: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a + `VkImageUsageFlags image_usage` argument. + It was previously hardcoded to `VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT` and defaults + to that when the value is 0. In theory the function is an internal helper but + since it's used by our examples some may have used it. (#8946, #8111, #8686) Other Changes: - Windows: added lower-right resize grip on child windows using both ImGuiChildFlags_ResizeX and ImGuiChildFlags_ResizeY flags. (#8501) [@aleksijuvani] The grip is not visible before hovering to reduce clutter. -- InputText: fixed single-line InputText() not applying fine character clipping - properly (regression in 1.92.3). (#8967) [@Cyphall] -- InputText: fixed an infinite loop error happening if a custom input text - callback modifies/clear BufTextLen before calling InsertChars(). - (regression from 1.92.3). Note that this never really worked correctly, but - previously it would only temporary wreck cursor position, and since 1.92.3 it - would go in an infinite loop. (#8994, #3237) - Style: added ImGuiCol_UnsavedMarker, color of the unsaved document marker when using ImGuiWindowFlags_UnsavedDocument/ImGuiTabItemFlags_UnsavedDocument. (#8983) - IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers() helpers to null all handlers. (#8945, #2769) -- Textures: fixed a crash if texture status is set to _WantDestroy by a backend after - it had already been destroyed. This would typically happen when calling backend's - ImGui_ImplXXXX_InvalidateDeviceObjects() helpers twice in a row. (#8977, #8811) -- Textures: allowed backend to destroy texture while inside the NewFrame/EndFrame - scope. Basically if a backend decide to destroy a texture that we didn't request - to destroy (for e.g. freeing resources) the texture is immediately set to - a _WantCreate status again. (#8811) -- Textures: fixed an issue preventing multi-contexts sharing a ImFontAtlas from - being possible to destroy in any order. -- Textures: fixed not updating ImTextureData's RefCount when destroying a context - using a shared ImFontAtlas, leading standard backends to not properly free - texture resources. (#8975) [@icrashstuff] +- InputText: + - Fixed single-line InputText() not applying fine character clipping + properly (regression in 1.92.3). (#8967) [@Cyphall] + - Fixed an infinite loop error happening if a custom input text + callback modifies/clear BufTextLen before calling InsertChars(). + (regression from 1.92.3). Note that this never really worked correctly, but + previously it would only temporary wreck cursor position, and since 1.92.3 it + would go in an infinite loop. (#8994, #3237) +- Textures: + - Fixed a crash if texture status is set to _WantDestroy by a backend after + it had already been destroyed. This would typically happen when calling backend's + ImGui_ImplXXXX_InvalidateDeviceObjects() helpers twice in a row. (#8977, #8811) + - Allowed backend to destroy texture while inside the NewFrame/EndFrame + scope. Basically if a backend decide to destroy a texture that we didn't request + to destroy (for e.g. freeing resources) the texture is immediately set to + a _WantCreate status again. (#8811) + - Fixed an issue preventing multi-contexts sharing a ImFontAtlas from + being possible to destroy in any order. + - Fixed not updating ImTextureData's RefCount when destroying a context + using a shared ImFontAtlas, leading standard backends to not properly + free texture resources. (#8975) [@icrashstuff] - Demo: fixed layout issue in "Layout & Scrolling -> Scrolling" section. - Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode, Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc. @@ -92,37 +95,39 @@ Other Changes: - CI: updated Windows CI scripts to generate/use VulkanSDK. (#8925, #8778) [@yaz0r] - Docs: updated FAQ with new "What is the difference between Dear ImGui and traditional UI toolkits?" entry. (#8862) -- Backends: all backends call ImGuiPlatformIO::ClearPlatformHandlers() and - ClearRendererHandlers() on shutdown, so as not to leave function pointers - which may be dangling when using backend in e.g. DLL. (#8945, #2769) -- Backends: DirectX12: reuse a command list and allocator for texture uploads instead - of recreating them each time. (#8963, #8465) [@RT2Code] -- Backends: DirectX12: Rework synchronization logic. (#8961) [@RT2Code] - (presumably fixes old hard-to-repro crash issues such as #3463, #5018) -- Backends: DirectX12: Reuse texture upload buffer and grow it only when - necessary. (#9002) [@RT2Code] -- Backends: DirectX12: Enable swapchain tearing if available. (#8965) [@RT2Code] -- Backends: OpenGL3: fixed GL loader to work on Haiku OS which does not support - `RTLD_NOLOAD`. (#8952) [@Xottab-DUTY, @threedeyes] -- Backends: GLFW: fixed build on platform that are neither Windows, macOS or - known Unixes (Regression in 1.92.3). (#8969, #8920, #8921) [@oktonion] -- Backends: SDL2,SDL3: avoid using the SDL_GetGlobalMouseState() path when one of our - window is hovered, as the event data is reliable and enough in this case. - - Fix mouse coordinates issue in fullscreen apps with macOS notch. (#7919, #7786) - - Essentially a working for SDL3 bug which will be fixed in SDL 3.3.0. - - Better perf on X11 as querying global position requires a round trip to X11 server. -- Backends: Win32: minor optimization not submitting gamepad io again if - XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN] -- Backends: Vulkan: added a way to specify custom shaders by filling init fields - CustomShaderVertCreateInfo and CustomShaderFragCreateInfo. (#8585, #8271) [@johan0A] -- Backends: DX9,DX10,DX11,DX12,Metal,Vulkan,WGPU,SDLRenderer2,SDLRenderer3: - ensure that a texture in _WantDestroy state always turn to _Destroyed even - if your underlying graphics data was already destroyed. (#8977) -- Examples: SDL2+DirectX11: Try WARP software driver if hardware driver is - not available. (#5924, #5562) -- Examples: SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82] -- Examples: Win32+DirectX12: Rework synchronization logic. (#8961) [@RT2Code] -- Examples: made examples's main.cpp consistent with returning 1 on error. +- Backends: + - All backends call ImGuiPlatformIO::ClearPlatformHandlers() and + ClearRendererHandlers() on shutdown, so as not to leave function pointers + which may be dangling when using backend in e.g. DLL. (#8945, #2769) + - DirectX12: reuse a command list and allocator for texture uploads instead + of recreating them each time. (#8963, #8465) [@RT2Code] + - DirectX12: Rework synchronization logic. (#8961) [@RT2Code] + (presumably fixes old hard-to-repro crash issues such as #3463, #5018) + - DirectX12: Reuse texture upload buffer and grow it only when + necessary. (#9002) [@RT2Code] + - DirectX12: Enable swapchain tearing if available. (#8965) [@RT2Code] + - OpenGL3: fixed GL loader to work on Haiku OS which does not support + `RTLD_NOLOAD`. (#8952) [@Xottab-DUTY, @threedeyes] + - GLFW: fixed build on platform that are neither Windows, macOS or + known Unixes (Regression in 1.92.3). (#8969, #8920, #8921) [@oktonion] + - SDL2,SDL3: avoid using the SDL_GetGlobalMouseState() path when one of our + window is hovered, as the event data is reliable and enough in this case. + - Fix mouse coordinates issue in fullscreen apps with macOS notch. (#7919, #7786) + - Essentially a workaround for SDL3 bug which will be fixed in SDL 3.3.0. + - Better perf on X11 as querying global position requires a round trip to X11 server. + - Win32: minor optimization not submitting gamepad io again if + XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN] + - Vulkan: added a way to specify custom shaders by filling init fields + CustomShaderVertCreateInfo and CustomShaderFragCreateInfo. (#8585, #8271) [@johan0A] + - DX9,DX10,DX11,DX12,Metal,Vulkan,WGPU,SDLRenderer2,SDLRenderer3: + ensure that a texture in _WantDestroy state always turn to _Destroyed even + if your underlying graphics data was already destroyed. (#8977) +- Examples: + - SDL2+DirectX11: Try WARP software driver if hardware driver is + not available. (#5924, #5562) + - SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82] + - Win32+DirectX12: Rework synchronization logic. (#8961) [@RT2Code] + - Made examples's main.cpp consistent with returning 1 on error. ----------------------------------------------------------------------- From b6e277980fbb00317ef5a9ff319e64ac3976866c Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Oct 2025 15:02:55 +0200 Subject: [PATCH 14/50] Shortcuts: reorganize route scoring so values are easier to read. (#9004) Score now require 16-bits but ImGuiKeyRoutingData doesn't grow size. --- imgui.cpp | 49 +++++++++++++++++++++++++----------------------- imgui_internal.h | 6 +++--- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2ba3aacd9..484c8513f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9378,7 +9378,7 @@ static void ImGui::UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt) routing_entry->RoutingCurrScore = routing_entry->RoutingNextScore; routing_entry->RoutingCurr = routing_entry->RoutingNext; // Update entry routing_entry->RoutingNext = ImGuiKeyOwner_NoOwner; - routing_entry->RoutingNextScore = 255; + routing_entry->RoutingNextScore = 0; if (routing_entry->RoutingCurr == ImGuiKeyOwner_NoOwner) continue; rt->EntriesNext.push_back(*routing_entry); // Write alive ones into new buffer @@ -9447,23 +9447,24 @@ ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord) return routing_data; } -// Current score encoding (lower is highest priority): -// - 0: ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive -// - 1: ImGuiInputFlags_ActiveItem or ImGuiInputFlags_RouteFocused (if item active) -// - 2: ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused -// - 3+: ImGuiInputFlags_RouteFocused (if window in focus-stack) -// - 254: ImGuiInputFlags_RouteGlobal -// - 255: never route +// Current score encoding +// - 0: Never route +// - 1: ImGuiInputFlags_RouteGlobal (lower priority) +// - 100..199: ImGuiInputFlags_RouteFocused (if window in focus-stack) +// 200: ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused +// 300: ImGuiInputFlags_RouteActive or ImGuiInputFlags_RouteFocused (if item active) +// 400: ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive +// - 500..599: ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteOverActive (if window in focus-stack) (higher priority) // 'flags' should include an explicit routing policy static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInputFlags flags) { ImGuiContext& g = *GImGui; if (flags & ImGuiInputFlags_RouteFocused) { - // ActiveID gets top priority + // ActiveID gets high priority // (we don't check g.ActiveIdUsingAllKeys here. Routing is applied but if input ownership is tested later it may discard it) if (owner_id != 0 && g.ActiveId == owner_id) - return 1; + return 300; // Score based on distance to focused window (lower is better) // Assuming both windows are submitting a routing request, @@ -9473,25 +9474,27 @@ static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInput // - When Window/ChildB is focused -> Window scores 4 (best), Window/ChildB doesn't have a score. // This essentially follow the window->ParentWindowForFocusRoute chain. if (focus_scope_id == 0) - return 255; + return 0; for (int index_in_focus_path = 0; index_in_focus_path < g.NavFocusRoute.Size; index_in_focus_path++) if (g.NavFocusRoute.Data[index_in_focus_path].ID == focus_scope_id) - return 3 + index_in_focus_path; - return 255; + return 199 - index_in_focus_path; + return 0; } else if (flags & ImGuiInputFlags_RouteActive) { if (owner_id != 0 && g.ActiveId == owner_id) - return 1; - return 255; + return 300; + return 0; } else if (flags & ImGuiInputFlags_RouteGlobal) { if (flags & ImGuiInputFlags_RouteOverActive) - return 0; + return 400; + if (owner_id != 0 && g.ActiveId == owner_id) + return 300; if (flags & ImGuiInputFlags_RouteOverFocused) - return 2; - return 254; + return 200; + return 1; } IM_ASSERT(0); return 0; @@ -9587,17 +9590,17 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, I const int score = CalcRoutingScore(focus_scope_id, owner_id, flags); IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, flags=%04X, owner_id=0x%08X) -> score %d\n", GetKeyChordName(key_chord), flags, owner_id, score); - if (score == 255) + if (score == 0) return false; // Submit routing for NEXT frame (assuming score is sufficient) - // FIXME: Could expose a way to use a "serve last" policy for same score resolution (using <= instead of <). + // FIXME: Could expose a way to use a "serve last" policy for same score resolution (using >= instead of >). ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord); - //const bool set_route = (flags & ImGuiInputFlags_ServeLast) ? (score <= routing_data->RoutingNextScore) : (score < routing_data->RoutingNextScore); - if (score < routing_data->RoutingNextScore) + //const bool set_route = (flags & ImGuiInputFlags_ServeLast) ? (score >= routing_data->RoutingNextScore) : (score > routing_data->RoutingNextScore); + if (score > routing_data->RoutingNextScore) { routing_data->RoutingNext = owner_id; - routing_data->RoutingNextScore = (ImU8)score; + routing_data->RoutingNextScore = (ImU16)score; } // Return routing state for CURRENT frame diff --git a/imgui_internal.h b/imgui_internal.h index 1510271a0..c9c1f1333 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1556,12 +1556,12 @@ struct ImGuiKeyRoutingData { ImGuiKeyRoutingIndex NextEntryIndex; ImU16 Mods; // Technically we'd only need 4-bits but for simplify we store ImGuiMod_ values which need 16-bits. - ImU8 RoutingCurrScore; // [DEBUG] For debug display - ImU8 RoutingNextScore; // Lower is better (0: perfect score) + ImU16 RoutingCurrScore; // [DEBUG] For debug display + ImU16 RoutingNextScore; // Lower is better (0: perfect score) ImGuiID RoutingCurr; ImGuiID RoutingNext; - ImGuiKeyRoutingData() { NextEntryIndex = -1; Mods = 0; RoutingCurrScore = RoutingNextScore = 255; RoutingCurr = RoutingNext = ImGuiKeyOwner_NoOwner; } + ImGuiKeyRoutingData() { NextEntryIndex = -1; Mods = 0; RoutingCurrScore = RoutingNextScore = 0; RoutingCurr = RoutingNext = ImGuiKeyOwner_NoOwner; } }; // Routing table: maintain a desired owner for each possible key-chord (key + mods), and setup owner in NewFrame() when mods are matching. From bad5ee167b06484e06015bca34ebfb20f8aeed24 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Oct 2025 15:03:26 +0200 Subject: [PATCH 15/50] Shortcuts: added support for combining ImGuiInputFlags_RouteFocused with ImGuiInputFlags_RouteOverActive,. (#9004) --- docs/CHANGELOG.txt | 4 ++++ imgui.cpp | 11 +++++++++-- imgui.h | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 409bcb11d..73c029ae0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -67,6 +67,10 @@ Other Changes: using ImGuiWindowFlags_UnsavedDocument/ImGuiTabItemFlags_UnsavedDocument. (#8983) - IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers() helpers to null all handlers. (#8945, #2769) +- Inputs: + - Shortcuts: added support for combining ImGuiInputFlags_RouteFocused + (which is the default route) with ImGuiInputFlags_RouteOverActive, allowing + to steal shortcuts from active item without using global routing. (#9004) - InputText: - Fixed single-line InputText() not applying fine character clipping properly (regression in 1.92.3). (#8967) [@Cyphall] diff --git a/imgui.cpp b/imgui.cpp index 484c8513f..2cf1cb273 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9477,7 +9477,12 @@ static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInput return 0; for (int index_in_focus_path = 0; index_in_focus_path < g.NavFocusRoute.Size; index_in_focus_path++) if (g.NavFocusRoute.Data[index_in_focus_path].ID == focus_scope_id) - return 199 - index_in_focus_path; + { + if (flags & ImGuiInputFlags_RouteOverActive) // && g.ActiveId != 0 && g.ActiveId != owner_id) + return 599 - index_in_focus_path; + else + return 199 - index_in_focus_path; + } return 0; } else if (flags & ImGuiInputFlags_RouteActive) @@ -9534,8 +9539,10 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, I else IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteTypeMask_)); // Check that only 1 routing flag is used IM_ASSERT(owner_id != ImGuiKeyOwner_Any && owner_id != ImGuiKeyOwner_NoOwner); - if (flags & (ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused)) + if (flags & (ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteUnlessBgFocused)) IM_ASSERT(flags & ImGuiInputFlags_RouteGlobal); + if (flags & ImGuiInputFlags_RouteOverActive) + IM_ASSERT(flags & (ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteFocused)); // Add ImGuiMod_XXXX when a corresponding ImGuiKey_LeftXXX/ImGuiKey_RightXXX is specified. key_chord = FixupKeyChord(key_chord); diff --git a/imgui.h b/imgui.h index 24c6423b4..b798903be 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.4 WIP" -#define IMGUI_VERSION_NUM 19235 +#define IMGUI_VERSION_NUM 19236 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198 From 2c499021599bcfde7ea0daf35632568615f54adc Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Oct 2025 15:16:15 +0200 Subject: [PATCH 16/50] Docs: reformat changlog entries. --- docs/CHANGELOG.txt | 62 +++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index fe4b97636..08b37451f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -142,37 +142,37 @@ Docking+Viewports Branch: - Nav: fixed a crash that could occur when opening a popup following the processing of a global shortcut while no windows were focused (the fix done in 1.92.3 was incomplete for docking branch). -- Viewports: added ImGuiBackendFlags_HasParentViewport backend flag for - backend to specify if it can honor the viewport->ParentViewportId value by - applying the corresponding parent/child relation at the Platform level. (#8948) - - SDL3, Win32 backends: supported. - - SDL2, GLFW, OSX backends: unsupported. -- Viewports: fixed a bug where ImGuiWindowFlags_NoBringToFrontOnFocus would effectivey - be ignored when windows first appear and viewports are enabled. (#7008) [@jshofmann] -- Viewports: changed default value of io.ConfigViewportsNoDefaultParent to true. (#8948) -- Viewports: fixed an issue inferring Z-order when attempting to merge a viewport - back in the the main/hosting viewport. (#8948) - Note that for GLFW/SDL2/OSX backends, which do not support honoring ParentViewportID. - setting io.ConfigViewportsNoDefaultParent=true will align imgui's expectation - with what the backend does. -- Viewports: storing `ImGuiViewport* ParentViewport` pointer along with ParentViewportID. -- Viewports: DestroyContext() does not call DestroyPlatformWindows() anymore at - it assumed to be unnecessary as backensd should have done it and we check that - backends have been shutdown since 1.90.4. Changed into asserts. (#7175, #8945) -- Backends: DX10, DX11, DX12: Disabled DXGI's Alt+Enter default behavior on secondary - viewports managed by the backend. (#4350) [@PathogenDavid] -- Backends: DX10, DX11: avoid ImGui_ImplXXXX_SwapBuffers() handlers for secondary - viewports crashing if SwapChain could not be created. -- Backends: Vulkan: Added a way to configure secondary viewport pipelinen creation - by setting init_info.PipelineInfoForViewports fields. (#8946, #8110, #8111, #8686) -- Backends: Vulkan: Added a way to configure secondary viewport swapchain VkImageUsageFlags - to e.g. capture rendering. (#8946, #8940) [@olivier-gerard, @ocornut] - Usage example: - `init_info.PipelineInfoForViewports.SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;` -- Backends: Vulkan: pipeline created for secondary viewport automatically match - surface format. (#8686) [@sylmroz] -- Backends: Vulkan: Added ImGui_ImplVulkanH_GetWindowDataFromViewport() accessor/helper. - (#8946, #8940) [@olivier-gerard] +- Viewports: + - Added ImGuiBackendFlags_HasParentViewport backend flag for + backend to specify if it can honor the viewport->ParentViewportId value by + applying the corresponding parent/child relation at the Platform level. (#8948) + - SDL3, Win32 backends: supported. + - SDL2, GLFW, OSX backends: unsupported. + - Fixed a bug where ImGuiWindowFlags_NoBringToFrontOnFocus would effectivey + be ignored when windows first appear and viewports are enabled. (#7008) [@jshofmann] + - Changed default value of io.ConfigViewportsNoDefaultParent to true. (#8948) + - Fixed an issue inferring Z-order when attempting to merge a viewport + back in the the main/hosting viewport. (#8948) + Note that for GLFW/SDL2/OSX backends, which do not support honoring ParentViewportID. + Setting io.ConfigViewportsNoDefaultParent=true will align imgui's expectation + with what the backend does. + - Storing `ImGuiViewport* ParentViewport` pointer along with ParentViewportID. + - DestroyContext() does not call DestroyPlatformWindows() anymore at it is + assumed to be unnecessary as backends should have done it and we check that + backends have been shutdown since 1.90.4. Changed into asserts. (#7175, #8945) +- Backends: + - DirectX10, DirectX11, DirectX12: Disabled DXGI's Alt+Enter default behavior on + secondary viewports managed by the backend. (#4350) [@PathogenDavid] + - DirectX10, DirectX11: avoid ImGui_ImplXXXX_SwapBuffers() handlers for secondary + viewports crashing if SwapChain could not be created. + - Vulkan: Added a way to configure secondary viewport pipeline creation by + setting init_info.PipelineInfoForViewports fields. (#8946, #8110, #8111, #8686) + - Vulkan: Added a way to configure secondary viewport swapchain VkImageUsageFlags + to e.g. capture rendering. (#8946, #8940) [@olivier-gerard, @ocornut] + Usage example: `init_info.PipelineInfoForViewports.SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;` + - Vulkan: pipeline created for secondary viewport automatically match + surface format. (#8686) [@sylmroz] + - Vulkan: Added ImGui_ImplVulkanH_GetWindowDataFromViewport() accessor/helper. (#8946, #8940) [@olivier-gerard] - Examples: DX10, DX11: Disabled DXGI's Alt+Enter default behavior in examples. Applications are free to leave this enabled, but it does not work properly with multiple viewports. (#4350) [@PathogenDavid] From 28ed29078bf3320b311910db6f3a60ba49133ec3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 14 Oct 2025 16:07:07 +0200 Subject: [PATCH 17/50] Relaxed internal assert in MarkItemEdited() some more. (#8997) Amend e7a734f78d, 5a2b1e8482 --- docs/CHANGELOG.txt | 1 + imgui.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 08b37451f..6db8ee44a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -97,6 +97,7 @@ Other Changes: using a shared ImFontAtlas, leading standard backends to not properly free texture resources. (#8975) [@icrashstuff] - Demo: fixed layout issue in "Layout & Scrolling -> Scrolling" section. +- Misc: Relaxed internal assert in MarkItemEdited() to allow for more use cases. (#8997) - Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode, Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc. See misc/debuggers/ for details. (#8950) [@mentlerd] diff --git a/imgui.cpp b/imgui.cpp index f7c9fd2f1..4b30a0353 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4748,7 +4748,8 @@ void ImGui::MarkItemEdited(ImGuiID id) // We accept a MarkItemEdited() on drag and drop targets (see https://github.com/ocornut/imgui/issues/1875#issuecomment-978243343) // We accept 'ActiveIdPreviousFrame == id' for InputText() returning an edit after it has been taken ActiveId away (#4714) - IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id || (g.CurrentMultiSelect != NULL && g.BoxSelectState.IsActive)); + // FIXME: This assert is getting a bit meaningless over time. It helped detect some unusual use cases but eventually it is becoming an unnecessary restriction. + IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id || g.NavJustMovedToId || (g.CurrentMultiSelect != NULL && g.BoxSelectState.IsActive)); //IM_ASSERT(g.CurrentWindow->DC.LastItemId == id); g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited; From 96ad0030005ca720196892bf7bc4f3044e719534 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 14 Oct 2025 16:30:30 +0200 Subject: [PATCH 18/50] Nav, Docking, Selection: Fixed tab change from reinitializing navigation state. (#8997) --- docs/CHANGELOG.txt | 5 ++++- imgui.cpp | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6db8ee44a..fae4d30b7 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -140,7 +140,10 @@ Other Changes: Docking+Viewports Branch: -- Nav: fixed a crash that could occur when opening a popup following the processing +- Nav, Docking, Selection: Fixed tab change from reinitializing navigation state, + which would erroneously clear selection when using ImGuiSelectableFlags_SelectOnNav + or clear multi-selection when not using ImGuiMultiSelectFlags_NoAutoSelect. (#8997) +- Nav: Fixed a crash that could occur when opening a popup following the processing of a global shortcut while no windows were focused (the fix done in 1.92.3 was incomplete for docking branch). - Viewports: diff --git a/imgui.cpp b/imgui.cpp index 4b30a0353..8df079f41 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -14953,7 +14953,7 @@ static void ImGui::NavUpdateWindowingApplyFocus(ImGuiWindow* apply_focus_window) FocusWindow(apply_focus_window, ImGuiFocusRequestFlags_RestoreFocusedChild); IM_ASSERT(g.NavWindow != NULL); apply_focus_window = g.NavWindow; - if (apply_focus_window->NavLastIds[0] == 0) + if (apply_focus_window->NavLastIds[0] == 0) // FIXME: This is the equivalent of the 'if (g.NavId == 0) { NavInitWindow() }' in DockNodeUpdateTabBar(). NavInitWindow(apply_focus_window, false); // If the window has ONLY a menu layer (no main layer), select it directly @@ -19366,7 +19366,8 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w if (tab->Window) { FocusWindow(tab->Window); - NavInitWindow(tab->Window, false); + if (g.NavId == 0) // only init if FocusWindow() didn't restore anything. + NavInitWindow(tab->Window, false); } EndTabBar(); From 702cc9993aca927d70c963d7c5826c2cd5ff0c0e Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 14 Oct 2025 16:07:07 +0200 Subject: [PATCH 19/50] Relaxed internal assert in MarkItemEdited() some more. (#8997) Amend e7a734f78d, 5a2b1e8482 --- docs/CHANGELOG.txt | 1 + imgui.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 73c029ae0..4d4193633 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -93,6 +93,7 @@ Other Changes: using a shared ImFontAtlas, leading standard backends to not properly free texture resources. (#8975) [@icrashstuff] - Demo: fixed layout issue in "Layout & Scrolling -> Scrolling" section. +- Misc: Relaxed internal assert in MarkItemEdited() to allow for more use cases. (#8997) - Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode, Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc. See misc/debuggers/ for details. (#8950) [@mentlerd] diff --git a/imgui.cpp b/imgui.cpp index 2cf1cb273..977ce3b11 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4639,7 +4639,8 @@ void ImGui::MarkItemEdited(ImGuiID id) // We accept a MarkItemEdited() on drag and drop targets (see https://github.com/ocornut/imgui/issues/1875#issuecomment-978243343) // We accept 'ActiveIdPreviousFrame == id' for InputText() returning an edit after it has been taken ActiveId away (#4714) - IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id || (g.CurrentMultiSelect != NULL && g.BoxSelectState.IsActive)); + // FIXME: This assert is getting a bit meaningless over time. It helped detect some unusual use cases but eventually it is becoming an unnecessary restriction. + IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id || g.NavJustMovedToId || (g.CurrentMultiSelect != NULL && g.BoxSelectState.IsActive)); //IM_ASSERT(g.CurrentWindow->DC.LastItemId == id); g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited; From 94ed5b140874c680afff2b551ad34e86c0f50e97 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 14 Oct 2025 18:14:59 +0200 Subject: [PATCH 20/50] Docs: improve docking API comments and demo. (#9000) --- docs/CHANGELOG.txt | 1 + imgui.h | 30 +++++++++++-------- imgui_demo.cpp | 74 +++++++++++++++++++++++----------------------- 3 files changed, 56 insertions(+), 49 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index fae4d30b7..18c5675d1 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -177,6 +177,7 @@ Docking+Viewports Branch: - Vulkan: pipeline created for secondary viewport automatically match surface format. (#8686) [@sylmroz] - Vulkan: Added ImGui_ImplVulkanH_GetWindowDataFromViewport() accessor/helper. (#8946, #8940) [@olivier-gerard] +- Docs: improve docking API comments and demo. (#9000) - Examples: DX10, DX11: Disabled DXGI's Alt+Enter default behavior in examples. Applications are free to leave this enabled, but it does not work properly with multiple viewports. (#4350) [@PathogenDavid] diff --git a/imgui.h b/imgui.h index 27baa6baf..60dc91d0d 100644 --- a/imgui.h +++ b/imgui.h @@ -956,18 +956,24 @@ namespace ImGui IMGUI_API void SetTabItemClosed(const char* tab_or_docked_window_label); // notify TabBar or Docking system of a closed tab/window ahead (useful to reduce visual flicker on reorderable tab bars). For tab-bar: call after BeginTabBar() and before Tab submissions. Otherwise call with a window name. // Docking - // [BETA API] Enable with io.ConfigFlags |= ImGuiConfigFlags_DockingEnable. - // Note: You can use most Docking facilities without calling any API. You DO NOT need to call DockSpace() to use Docking! - // - Drag from window title bar or their tab to dock/undock. Hold SHIFT to disable docking. - // - Drag from window menu button (upper-left button) to undock an entire node (all windows). - // - When io.ConfigDockingWithShift == true, you instead need to hold SHIFT to enable docking. - // About dockspaces: - // - Use DockSpaceOverViewport() to create a window covering the screen or a specific viewport + a dockspace inside it. - // This is often used with ImGuiDockNodeFlags_PassthruCentralNode to make it transparent. - // - Use DockSpace() to create an explicit dock node _within_ an existing window. See Docking demo for details. - // - Important: Dockspaces need to be submitted _before_ any window they can host. Submit it early in your frame! - // - Important: Dockspaces need to be kept alive if hidden, otherwise windows docked into it will be undocked. - // e.g. if you have multiple tabs with a dockspace inside each tab: submit the non-visible dockspaces with ImGuiDockNodeFlags_KeepAliveOnly. + // - Read https://github.com/ocornut/imgui/wiki/Docking for details. + // - Enable with io.ConfigFlags |= ImGuiConfigFlags_DockingEnable. + // - You can use most Docking facilities without calling any API. You don't necessarily need to call a DockSpaceXXX function to use Docking! + // - Drag from window title bar or their tab to dock/undock. Hold SHIFT to disable docking. + // - Drag from window menu button (upper-left button) to undock an entire node (all windows). + // - When io.ConfigDockingWithShift == true, you instead need to hold SHIFT to enable docking. + // - Dockspaces: + // - If you want to dock windows into the edge of your screen, most application can simply call DockSpaceOverViewport(): + // e.g. ImGui::NewFrame(); then ImGui::DockSpaceOverViewport(); // Create a dockspace in main viewport. + // or: ImGui::NewFrame(); then ImGui::DockSpaceOverViewport(0, nullptr, ImGuiDockNodeFlags_PassthruCentralNode); // Create a dockspace in main viewport, where central node is transparent. + // - A dockspace is an explicit dock node within an existing window. + // - DockSpaceOverViewport() basically creates an invisible window covering a viewport, and submit a DockSpace() into it. + // - IMPORTANT: Dockspaces need to be submitted _before_ any window they can host. Submit them early in your frame! + // - IMPORTANT: Dockspaces need to be kept alive if hidden, otherwise windows docked into it will be undocked. + // If you have e.g. multiple tabs with a dockspace inside each tab: submit the non-visible dockspaces with ImGuiDockNodeFlags_KeepAliveOnly. + // - Programmatic docking: + // - There is no public API yet other than the very limited SetNextWindowDockID() function. Sorry for that! + // - Read https://github.com/ocornut/imgui/wiki/Docking for examples of how to use current internal API. IMGUI_API ImGuiID DockSpace(ImGuiID dockspace_id, const ImVec2& size = ImVec2(0, 0), ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL); IMGUI_API ImGuiID DockSpaceOverViewport(ImGuiID dockspace_id = 0, const ImGuiViewport* viewport = NULL, ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL); IMGUI_API void SetNextWindowDockID(ImGuiID dock_id, ImGuiCond cond = 0); // set next window dock id diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 4c5066b5d..40960c534 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -10248,37 +10248,27 @@ static void ShowExampleAppCustomRendering(bool* p_open) // [SECTION] Example App: Docking, DockSpace / ShowExampleAppDockSpace() //----------------------------------------------------------------------------- -// Demonstrate using DockSpace() to create an explicit docking node within an existing window. -// Note: You can use most Docking facilities without calling any API. You DO NOT need to call DockSpace() to use Docking! -// - Drag from window title bar or their tab to dock/undock. Hold SHIFT to disable docking. -// - Drag from window menu button (upper-left button) to undock an entire node (all windows). -// - When io.ConfigDockingWithShift == true, you instead need to hold SHIFT to enable docking. -// About dockspaces: -// - Use DockSpace() to create an explicit dock node _within_ an existing window. -// - Use DockSpaceOverViewport() to create an explicit dock node covering the screen or a specific viewport. -// This is often used with ImGuiDockNodeFlags_PassthruCentralNode. -// - Important: Dockspaces need to be submitted _before_ any window they can host. Submit it early in your frame! (*) -// - Important: Dockspaces need to be kept alive if hidden, otherwise windows docked into it will be undocked. -// e.g. if you have multiple tabs with a dockspace inside each tab: submit the non-visible dockspaces with ImGuiDockNodeFlags_KeepAliveOnly. -// (*) because of this constraint, the implicit \"Debug\" window can not be docked into an explicit DockSpace() node, -// because that window is submitted as part of the part of the NewFrame() call. An easy workaround is that you can create -// your own implicit "Debug##2" window after calling DockSpace() and leave it in the window stack for anyone to use. +// Demonstrate using DockSpace() to create an explicit docking node within an existing window, with various options. +// THIS IS A DEMO FOR ADVANCED USAGE OF DockSpace(). +// MOST REGULAR APPLICATIONS WHO WANT TO ALLOW DOCKING WINDOWS ON THE EDGE OF YOUR SCREEN CAN SIMPLY USE: +// ImGui::NewFrame(); +// ImGui::DockSpaceOverViewport(); // Create a dockspace in main viewport +// OR: +// ImGui::NewFrame(); +// ImGui::DockSpaceOverViewport(0, nullptr, ImGuiDockNodeFlags_PassthruCentralNode); // Create a dockspace in main viewport, where central node is transparent. +// Read https://github.com/ocornut/imgui/wiki/Docking for details. +// The reasons we do not use DockSpaceOverViewport() in this demo is because: +// - (1) we allow the host window to be floating/moveable instead of filling the viewport (when opt_fullscreen == false) +// which is mostly to showcase the idea that DockSpace() may be submitted anywhere. +// - (2) we allow the host window to have padding (when opt_padding == true) +// - (3) we expose many flags and need a way to have them visible. +// - (4) we have a local menu bar in the host window (vs. you could use BeginMainMenuBar() + DockSpaceOverViewport() +// in your code, but we don't here because we allow the window to be floating) void ShowExampleAppDockSpace(bool* p_open) { - // READ THIS !!! // TL;DR; this demo is more complicated than what most users you would normally use. - // If we remove all options we are showcasing, this demo would become: - // void ShowExampleAppDockSpace() - // { - // ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport()); - // } - // In most cases you should be able to just call DockSpaceOverViewport() and ignore all the code below! + // If we remove all options we are showcasing, this demo would become a simple call to ImGui::DockSpaceOverViewport() !! // In this specific demo, we are not using DockSpaceOverViewport() because: - // - (1) we allow the host window to be floating/moveable instead of filling the viewport (when opt_fullscreen == false) - // - (2) we allow the host window to have padding (when opt_padding == true) - // - (3) we expose many flags and need a way to have them visible. - // - (4) we have a local menu bar in the host window (vs. you could use BeginMainMenuBar() + DockSpaceOverViewport() - // in your code, but we don't here because we allow the window to be floating) static bool opt_fullscreen = true; static bool opt_padding = false; @@ -10323,6 +10313,8 @@ void ShowExampleAppDockSpace(bool* p_open) ImGui::PopStyleVar(2); // Submit the DockSpace + // REMINDER: THIS IS A DEMO FOR ADVANCED USAGE OF DockSpace()! + // MOST REGULAR APPLICATIONS WILL SIMPLY WANT TO CALL DockSpaceOverViewport(). READ COMMENTS ABOVE. ImGuiIO& io = ImGui::GetIO(); if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) { @@ -10334,6 +10326,7 @@ void ShowExampleAppDockSpace(bool* p_open) ShowDockingDisabledMessage(); } + // Show demo options and help if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenu("Options")) @@ -10356,16 +10349,23 @@ void ShowExampleAppDockSpace(bool* p_open) *p_open = false; ImGui::EndMenu(); } - HelpMarker( - "When docking is enabled, you can ALWAYS dock MOST window into another! Try it now!" "\n" - "- Drag from window title bar or their tab to dock/undock." "\n" - "- Drag from window menu button (upper-left button) to undock an entire node (all windows)." "\n" - "- Hold SHIFT to disable docking (if io.ConfigDockingWithShift == false, default)" "\n" - "- Hold SHIFT to enable docking (if io.ConfigDockingWithShift == true)" "\n" - "This demo app has nothing to do with enabling docking!" "\n\n" - "This demo app only demonstrate the use of ImGui::DockSpace() which allows you to manually create a docking node _within_ another window." "\n\n" - "Read comments in ShowExampleAppDockSpace() for more details."); - + if (ImGui::BeginMenu("Help")) + { + ImGui::TextUnformatted( + "This demo has nothing to do with enabling docking!" "\n" + "This demo only demonstrate the use of ImGui::DockSpace() which allows you to manually\ncreate a docking node _within_ another window." "\n" + "Most application can simply call ImGui::DockSpaceOverViewport() and be done with it."); + ImGui::Separator(); + ImGui::TextUnformatted("When docking is enabled, you can ALWAYS dock MOST window into another! Try it now!" "\n" + "- Drag from window title bar or their tab to dock/undock." "\n" + "- Drag from window menu button (upper-left button) to undock an entire node (all windows)." "\n" + "- Hold SHIFT to disable docking (if io.ConfigDockingWithShift == false, default)" "\n" + "- Hold SHIFT to enable docking (if io.ConfigDockingWithShift == true)"); + ImGui::Separator(); + ImGui::TextUnformatted("More details:"); ImGui::Bullet(); ImGui::SameLine(); ImGui::TextLinkOpenURL("Docking Wiki page", "https://github.com/ocornut/imgui/wiki/Docking"); + ImGui::BulletText("Read comments in ShowExampleAppDockSpace()"); + ImGui::EndMenu(); + } ImGui::EndMenuBar(); } From c8db91b7b43a01ebb0c1440663abb02a89c371fb Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 14 Oct 2025 18:52:27 +0200 Subject: [PATCH 21/50] (Breaking) TreeNode, Selectable: commented out legacy ImGuiTreeNodeFlags_AllowItemOverlap, ImGuiSelectableFlags_AllowItemOverlap names obsoleted in 1.89.7. Amend 51f564e --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 3 +++ imgui.h | 6 +++--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 4d4193633..4b710a55e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -42,6 +42,9 @@ HOW TO UPDATE? Breaking Changes: - Backends: + - TreeNode, Selectable: commented out legacy names obsoleted in 1.89.7 (July 2023): + ImGuiTreeNodeFlags_AllowItemOverlap --> ImGuiTreeNodeFlags_AllowOverlap + ImGuiSelectableFlags_AllowItemOverlap --> ImGuiSelectableFlags_AllowOverlap - Vulkan: moved some fields in ImGui_ImplVulkan_InitInfo: init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass init_info.Subpass --> init_info.PipelineInfoMain.Subpass diff --git a/imgui.cpp b/imgui.cpp index 977ce3b11..c2c36a9e0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -392,6 +392,9 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures: 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. + - 2025/10/14 (1.92.4) - TreeNode, Selectable: commented out legacy names which were obsoleted in 1.89.7 (July 2023): + - ImGuiTreeNodeFlags_AllowItemOverlap --> ImGuiTreeNodeFlags_AllowOverlap + - ImGuiSelectableFlags_AllowItemOverlap --> ImGuiSelectableFlags_AllowOverlapB - 2025/08/08 (1.92.2) - Backends: SDL_GPU3: Changed ImTextureID type from SDL_GPUTextureSamplerBinding* to SDL_GPUTexture*, which is more natural and easier for user to manage. If you need to change the current sampler, you can access the ImGui_ImplSDLGPU3_RenderState struct. (#8866, #8163, #7998, #7988) - 2025/07/31 (1.92.2) - Tabs: Renamed ImGuiTabBarFlags_FittingPolicyResizeDown to ImGuiTabBarFlags_FittingPolicyShrink. Kept inline redirection enum (will obsolete). - 2025/06/25 (1.92.0) - Layout: commented out legacy ErrorCheckUsingSetCursorPosToExtendParentBoundaries() fallback obsoleted in 1.89 (August 2022) which allowed a SetCursorPos()/SetCursorScreenPos() call WITHOUT AN ITEM diff --git a/imgui.h b/imgui.h index b798903be..7b0c28831 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.4 WIP" -#define IMGUI_VERSION_NUM 19236 +#define IMGUI_VERSION_NUM 19237 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198 @@ -1311,7 +1311,7 @@ enum ImGuiTreeNodeFlags_ #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS ImGuiTreeNodeFlags_NavLeftJumpsBackHere = ImGuiTreeNodeFlags_NavLeftJumpsToParent, // Renamed in 1.92.0 ImGuiTreeNodeFlags_SpanTextWidth = ImGuiTreeNodeFlags_SpanLabelWidth, // Renamed in 1.90.7 - ImGuiTreeNodeFlags_AllowItemOverlap = ImGuiTreeNodeFlags_AllowOverlap, // Renamed in 1.89.7 + //ImGuiTreeNodeFlags_AllowItemOverlap = ImGuiTreeNodeFlags_AllowOverlap, // Renamed in 1.89.7 #endif }; @@ -1354,7 +1354,7 @@ enum ImGuiSelectableFlags_ #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS ImGuiSelectableFlags_DontClosePopups = ImGuiSelectableFlags_NoAutoClosePopups, // Renamed in 1.91.0 - ImGuiSelectableFlags_AllowItemOverlap = ImGuiSelectableFlags_AllowOverlap, // Renamed in 1.89.7 + //ImGuiSelectableFlags_AllowItemOverlap = ImGuiSelectableFlags_AllowOverlap, // Renamed in 1.89.7 #endif }; From 25e5baf5f0da5aa0820b4fdc5b2633a7d25965aa Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 14 Oct 2025 19:00:27 +0200 Subject: [PATCH 22/50] (Breaking) Clipper: commented out legacy IncludeRangeByIndices name obsoleted in 1.89.9. (#6424, #3841) --- docs/CHANGELOG.txt | 8 +++++--- imgui.cpp | 7 ++++--- imgui.h | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 4b710a55e..9c8a6077c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -42,9 +42,11 @@ HOW TO UPDATE? Breaking Changes: - Backends: - - TreeNode, Selectable: commented out legacy names obsoleted in 1.89.7 (July 2023): - ImGuiTreeNodeFlags_AllowItemOverlap --> ImGuiTreeNodeFlags_AllowOverlap - ImGuiSelectableFlags_AllowItemOverlap --> ImGuiSelectableFlags_AllowOverlap + - TreeNode, Selectable, Clipper: commented out legacy names obsoleted in + 1.89.7 (July 2023) and 1.89.9 (Sept 2023): + ImGuiTreeNodeFlags_AllowItemOverlap --> ImGuiTreeNodeFlags_AllowOverlap + ImGuiSelectableFlags_AllowItemOverlap --> ImGuiSelectableFlags_AllowOverlap + ImGuiListClipper::IncludeRangeByIndices() --> ImGuiListClipper::IncludeItemsByIndex() - Vulkan: moved some fields in ImGui_ImplVulkan_InitInfo: init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass init_info.Subpass --> init_info.PipelineInfoMain.Subpass diff --git a/imgui.cpp b/imgui.cpp index c2c36a9e0..216c56ba9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -392,9 +392,10 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures: 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. - - 2025/10/14 (1.92.4) - TreeNode, Selectable: commented out legacy names which were obsoleted in 1.89.7 (July 2023): - - ImGuiTreeNodeFlags_AllowItemOverlap --> ImGuiTreeNodeFlags_AllowOverlap - - ImGuiSelectableFlags_AllowItemOverlap --> ImGuiSelectableFlags_AllowOverlapB + - 2025/10/14 (1.92.4) - TreeNode, Selectable, Clipper: commented out legacy names which were obsoleted in 1.89.7 (July 2023) and 1.89.9 (Sept 2023); + - ImGuiTreeNodeFlags_AllowItemOverlap --> ImGuiTreeNodeFlags_AllowOverlap + - ImGuiSelectableFlags_AllowItemOverlap --> ImGuiSelectableFlags_AllowOverlap + - ImGuiListClipper::IncludeRangeByIndices() --> ImGuiListClipper::IncludeItemsByIndex() - 2025/08/08 (1.92.2) - Backends: SDL_GPU3: Changed ImTextureID type from SDL_GPUTextureSamplerBinding* to SDL_GPUTexture*, which is more natural and easier for user to manage. If you need to change the current sampler, you can access the ImGui_ImplSDLGPU3_RenderState struct. (#8866, #8163, #7998, #7988) - 2025/07/31 (1.92.2) - Tabs: Renamed ImGuiTabBarFlags_FittingPolicyResizeDown to ImGuiTabBarFlags_FittingPolicyShrink. Kept inline redirection enum (will obsolete). - 2025/06/25 (1.92.0) - Layout: commented out legacy ErrorCheckUsingSetCursorPosToExtendParentBoundaries() fallback obsoleted in 1.89 (August 2022) which allowed a SetCursorPos()/SetCursorScreenPos() call WITHOUT AN ITEM diff --git a/imgui.h b/imgui.h index 7b0c28831..6aa73009d 100644 --- a/imgui.h +++ b/imgui.h @@ -2855,7 +2855,7 @@ struct ImGuiListClipper IMGUI_API void SeekCursorForItem(int item_index); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - inline void IncludeRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.9] + //inline void IncludeRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.9] //inline void ForceDisplayRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.6] //inline ImGuiListClipper(int items_count, float items_height = -1.0f) { memset(this, 0, sizeof(*this)); ItemsCount = -1; Begin(items_count, items_height); } // [removed in 1.79] #endif From 9a5d5c45f54b1301ea471622eddede70384243af Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 14 Oct 2025 19:16:43 +0200 Subject: [PATCH 23/50] Version 1.92.4 --- docs/CHANGELOG.txt | 15 +++++++++------ imgui.cpp | 2 +- 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, 18 insertions(+), 15 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9c8a6077c..b703e065a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -36,9 +36,11 @@ HOW TO UPDATE? - Please report any issue! ----------------------------------------------------------------------- - VERSION 1.92.4 WIP (In Progress) + VERSION 1.92.4 (Released 2025-10-14) ----------------------------------------------------------------------- +Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.4 + Breaking Changes: - Backends: @@ -85,13 +87,13 @@ Other Changes: previously it would only temporary wreck cursor position, and since 1.92.3 it would go in an infinite loop. (#8994, #3237) - Textures: - - Fixed a crash if texture status is set to _WantDestroy by a backend after - it had already been destroyed. This would typically happen when calling backend's + - Fixed a crash if texture status is set to ImTextureStatus_WantDestroy by a backend + after it had already been destroyed. This would typically happen when calling ImGui_ImplXXXX_InvalidateDeviceObjects() helpers twice in a row. (#8977, #8811) - Allowed backend to destroy texture while inside the NewFrame/EndFrame scope. Basically if a backend decide to destroy a texture that we didn't request to destroy (for e.g. freeing resources) the texture is immediately set to - a _WantCreate status again. (#8811) + a ImTextureStatus_WantCreate status again. (#8811) - Fixed an issue preventing multi-contexts sharing a ImFontAtlas from being possible to destroy in any order. - Fixed not updating ImTextureData's RefCount when destroying a context @@ -130,8 +132,9 @@ Other Changes: - Vulkan: added a way to specify custom shaders by filling init fields CustomShaderVertCreateInfo and CustomShaderFragCreateInfo. (#8585, #8271) [@johan0A] - DX9,DX10,DX11,DX12,Metal,Vulkan,WGPU,SDLRenderer2,SDLRenderer3: - ensure that a texture in _WantDestroy state always turn to _Destroyed even - if your underlying graphics data was already destroyed. (#8977) + ensure that a texture in ImTextureStatus_WantDestroy state always turn to + ImTextureStatus_Destroyed even if your underlying graphics data was already + destroyed. (#8977) - Examples: - SDL2+DirectX11: Try WARP software driver if hardware driver is not available. (#5924, #5562) diff --git a/imgui.cpp b/imgui.cpp index 216c56ba9..76b4a73f4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.4 WIP +// dear imgui, v1.92.4 // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index 6aa73009d..0a216b76c 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.92.4 WIP +// dear imgui, v1.92.4 // (headers) // Help: @@ -28,8 +28,8 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') -#define IMGUI_VERSION "1.92.4 WIP" -#define IMGUI_VERSION_NUM 19237 +#define IMGUI_VERSION "1.92.4" +#define IMGUI_VERSION_NUM 19240 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198 diff --git a/imgui_demo.cpp b/imgui_demo.cpp index dec1bad40..e473b2520 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.4 WIP +// dear imgui, v1.92.4 // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index a2c616012..9d0f024f5 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.4 WIP +// dear imgui, v1.92.4 // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index c9c1f1333..9c920eda1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.92.4 WIP +// dear imgui, v1.92.4 // (internal structures/api) // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index af0e8c6cf..b4d4f891a 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.4 WIP +// dear imgui, v1.92.4 // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index a3a4ae1cf..9ebafa85b 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.4 WIP +// dear imgui, v1.92.4 // (widgets code) /* From e1b27ce51efcd655e29d263a4d8f881868abd508 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 14 Oct 2025 19:56:35 +0200 Subject: [PATCH 24/50] Docs: amend changelog with minor tweaks matching web version. --- docs/CHANGELOG.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 19ae677d8..d57ba0a69 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -156,11 +156,11 @@ Docking+Viewports Branch: incomplete for docking branch). - Viewports: - Added ImGuiBackendFlags_HasParentViewport backend flag for - backend to specify if it can honor the viewport->ParentViewportId value by - applying the corresponding parent/child relation at the Platform level. (#8948) + backend to specify if it can honor the `viewport->ParentViewport`/`ParentViewportId` + value by applying the corresponding parent/child relation at the Platform level. (#8948) - SDL3, Win32 backends: supported. - SDL2, GLFW, OSX backends: unsupported. - - Fixed a bug where ImGuiWindowFlags_NoBringToFrontOnFocus would effectivey + - Fixed a bug where ImGuiWindowFlags_NoBringToFrontOnFocus would effectively be ignored when windows first appear and viewports are enabled. (#7008) [@jshofmann] - Changed default value of io.ConfigViewportsNoDefaultParent to true. (#8948) - Fixed an issue inferring Z-order when attempting to merge a viewport @@ -169,8 +169,8 @@ Docking+Viewports Branch: Setting io.ConfigViewportsNoDefaultParent=true will align imgui's expectation with what the backend does. - Storing `ImGuiViewport* ParentViewport` pointer along with ParentViewportID. - - DestroyContext() does not call DestroyPlatformWindows() anymore at it is - assumed to be unnecessary as backends should have done it and we check that + - ImGui::DestroyContext() does not call DestroyPlatformWindows() anymore at it + is assumed to be unnecessary as backends should have done it and we check that backends have been shutdown since 1.90.4. Changed into asserts. (#7175, #8945) - Backends: - DirectX10, DirectX11, DirectX12: Disabled DXGI's Alt+Enter default behavior on @@ -188,7 +188,7 @@ Docking+Viewports Branch: - Docs: improve docking API comments and demo. (#9000) - Examples: DX10, DX11: Disabled DXGI's Alt+Enter default behavior in examples. Applications are free to leave this enabled, but it does not work properly with - multiple viewports. (#4350) [@PathogenDavid] + multiple viewports. (#4350, #8979) [@PathogenDavid] ----------------------------------------------------------------------- From 7d8d587bc064e84d519a0d7fd26c49fda16f2f23 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 15 Oct 2025 16:46:18 +0200 Subject: [PATCH 25/50] Version 1.92.5 WIP --- docs/CHANGELOG.txt | 9 +++++++++ imgui.cpp | 2 +- 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, 18 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b703e065a..1be5cadaf 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,6 +35,15 @@ HOW TO UPDATE? and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users. - Please report any issue! +----------------------------------------------------------------------- + VERSION 1.92.5 WIP (In Progress) +----------------------------------------------------------------------- + +Breaking Changes: + +Other Changes: + + ----------------------------------------------------------------------- VERSION 1.92.4 (Released 2025-10-14) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 76b4a73f4..b9845a6f1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.4 +// dear imgui, v1.92.5 WIP // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index 0a216b76c..575989a77 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.92.4 +// dear imgui, v1.92.5 WIP // (headers) // Help: @@ -28,8 +28,8 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') -#define IMGUI_VERSION "1.92.4" -#define IMGUI_VERSION_NUM 19240 +#define IMGUI_VERSION "1.92.5 WIP" +#define IMGUI_VERSION_NUM 19241 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198 diff --git a/imgui_demo.cpp b/imgui_demo.cpp index e473b2520..0c8e51b5c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.4 +// dear imgui, v1.92.5 WIP // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 9d0f024f5..b7613ef5a 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.4 +// dear imgui, v1.92.5 WIP // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 9c920eda1..0fa0ba8f2 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.92.4 +// dear imgui, v1.92.5 WIP // (internal structures/api) // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index b4d4f891a..7e7395352 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.4 +// dear imgui, v1.92.5 WIP // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 9ebafa85b..31bb3a060 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.4 +// dear imgui, v1.92.5 WIP // (widgets code) /* From d7fec5e1d33e4256104524fba669dbd4b68e5a65 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 15 Oct 2025 16:50:11 +0200 Subject: [PATCH 26/50] Tables: fixed a bug where nesting BeginTable()->Begin()->BeginTable(). (#9005) --- docs/CHANGELOG.txt | 5 +++++ imgui_internal.h | 1 + imgui_tables.cpp | 5 +++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1be5cadaf..924fbdb41 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,11 @@ Breaking Changes: Other Changes: +- Tables: fixed a bug where nesting BeginTable()->Begin()->BeginTable() would + result in temporarily incorrect state, which would lead to bugs to side effects + in various locations, e.g. GetContentRegionAvail() calls or using clipper. (#9005) + EndTable() was mistakenly restoring a wrong current table. + ----------------------------------------------------------------------- VERSION 1.92.4 (Released 2025-10-14) diff --git a/imgui_internal.h b/imgui_internal.h index 0fa0ba8f2..701652e4b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3045,6 +3045,7 @@ struct IMGUI_API ImGuiTable // sizeof() ~ 136 bytes. struct IMGUI_API ImGuiTableTempData { + ImGuiID WindowID; // Shortcut to g.Tables[TableIndex]->OuterWindow->ID. int TableIndex; // Index in g.Tables.Buf[] pool float LastTimeActive; // Last timestamp this structure was used float AngledHeadersExtraWidth; // Used in EndTable() diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 7e7395352..d79cfe435 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -464,6 +464,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG table->HostIndentX = inner_window->DC.Indent.x; table->HostClipRect = inner_window->ClipRect; table->HostSkipItems = inner_window->SkipItems; + temp_data->WindowID = inner_window->ID; temp_data->HostBackupWorkRect = inner_window->WorkRect; temp_data->HostBackupParentWorkRect = inner_window->ParentWorkRect; temp_data->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset; @@ -1366,7 +1367,7 @@ void ImGui::EndTable() ImGuiWindow* inner_window = table->InnerWindow; ImGuiWindow* outer_window = table->OuterWindow; ImGuiTableTempData* temp_data = table->TempData; - IM_ASSERT(inner_window == g.CurrentWindow); + IM_ASSERT(inner_window == g.CurrentWindow && inner_window->ID == temp_data->WindowID); IM_ASSERT(outer_window == inner_window || outer_window == inner_window->ParentWindow); if (table->IsInsideRow) @@ -1559,7 +1560,7 @@ void ImGui::EndTable() IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table); IM_ASSERT(g.TablesTempDataStacked > 0); temp_data = (--g.TablesTempDataStacked > 0) ? &g.TablesTempData[g.TablesTempDataStacked - 1] : NULL; - g.CurrentTable = temp_data ? g.Tables.GetByIndex(temp_data->TableIndex) : NULL; + g.CurrentTable = temp_data && (temp_data->WindowID == outer_window->ID) ? g.Tables.GetByIndex(temp_data->TableIndex) : NULL; if (g.CurrentTable) { g.CurrentTable->TempData = temp_data; From 2a5e9a15e4d1860df756fee9dd678569705f877d Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 15 Oct 2025 19:12:40 +0200 Subject: [PATCH 27/50] InputTextMultiline: fixed a crash when using ImGuiInputTextFlags_WordWrap and resizing the parent window while keeping the multi-line field active. (#9007, #3237) --- docs/CHANGELOG.txt | 4 ++++ imgui_widgets.cpp | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 924fbdb41..f42a3b030 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,6 +47,10 @@ Other Changes: result in temporarily incorrect state, which would lead to bugs to side effects in various locations, e.g. GetContentRegionAvail() calls or using clipper. (#9005) EndTable() was mistakenly restoring a wrong current table. +- InputTextMultiline: fixed a crash when using ImGuiInputTextFlags_WordWrap and + resizing the parent window while keeping the multi-line field active (which is + most typically achieved when resizing programmatically or via a docking layout + reacting to a platform window resize). (#3237, #9007) [@anton-kl, @ocornut] ----------------------------------------------------------------------- diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 31bb3a060..f0b6e2a5f 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5401,7 +5401,12 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ line_index->Offsets.resize(0); int line_count = 1; if (is_multiline) - line_count = InputTextLineIndexBuild(flags, line_index, buf_display, buf_display_end, wrap_width, (render_cursor && state && state->CursorFollow) ? INT_MAX : line_visible_n1 + 1, buf_display_end ? NULL : &buf_display_end); + { + // If scrolling is expected to change build full index. + // FIXME-OPT: Could append to index when new value of line_visible_n1 becomes bigger, see second call to CalcClipRectVisibleItemsY() below. + bool will_scroll_y = state && ((state->CursorFollow && render_cursor) || (state->CursorCenterY && (render_cursor || render_selection))); + line_count = InputTextLineIndexBuild(flags, line_index, buf_display, buf_display_end, wrap_width, will_scroll_y ? INT_MAX : line_visible_n1 + 1, buf_display_end ? NULL : &buf_display_end); + } line_index->EndOffset = (int)(buf_display_end - buf_display); line_visible_n1 = ImMin(line_visible_n1, line_count); From aa9f6db6983165de83085476a946df1d632a183a Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 16 Oct 2025 13:48:24 +0200 Subject: [PATCH 28/50] Examples: SDL2+DX11, SDL3+DX11, Win32+DX10, Win32+DX11: fixed one resource leak. (#9010, #4350) --- docs/CHANGELOG.txt | 10 ++++++++++ examples/example_sdl2_directx11/main.cpp | 3 +++ examples/example_sdl3_directx11/main.cpp | 3 +++ examples/example_win32_directx10/main.cpp | 3 +++ examples/example_win32_directx11/main.cpp | 3 +++ 5 files changed, 22 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d57ba0a69..34da19b52 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,6 +35,16 @@ HOW TO UPDATE? and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users. - Please report any issue! +----------------------------------------------------------------------- + VERSION 1.92.5 WIP (In Progress) +----------------------------------------------------------------------- + +Docking+Viewports Branch: + +- Examples: SDL2+DX11, SDL3+DX11, Win32+DX10, Win32+DX11: fixed one resource + leak from the use of MakeWindowAssociation() in 1.92.4. (#9010, #4350) [@o-3-o] + + ----------------------------------------------------------------------- VERSION 1.92.4 (Released 2025-10-14) ----------------------------------------------------------------------- diff --git a/examples/example_sdl2_directx11/main.cpp b/examples/example_sdl2_directx11/main.cpp index bbabf55c0..0e4540ef8 100644 --- a/examples/example_sdl2_directx11/main.cpp +++ b/examples/example_sdl2_directx11/main.cpp @@ -261,7 +261,10 @@ bool CreateDeviceD3D(HWND hWnd) // - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates. IDXGIFactory* pSwapChainFactory; if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory)))) + { pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER); + pSwapChainFactory->Release(); + } CreateRenderTarget(); return true; diff --git a/examples/example_sdl3_directx11/main.cpp b/examples/example_sdl3_directx11/main.cpp index f0940ae00..cb761a679 100644 --- a/examples/example_sdl3_directx11/main.cpp +++ b/examples/example_sdl3_directx11/main.cpp @@ -256,7 +256,10 @@ bool CreateDeviceD3D(HWND hWnd) // - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates. IDXGIFactory* pSwapChainFactory; if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory)))) + { pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER); + pSwapChainFactory->Release(); + } CreateRenderTarget(); return true; diff --git a/examples/example_win32_directx10/main.cpp b/examples/example_win32_directx10/main.cpp index 504502dac..1d7030536 100644 --- a/examples/example_win32_directx10/main.cpp +++ b/examples/example_win32_directx10/main.cpp @@ -246,7 +246,10 @@ bool CreateDeviceD3D(HWND hWnd) // - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates. IDXGIFactory* pSwapChainFactory; if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory)))) + { pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER); + pSwapChainFactory->Release(); + } CreateRenderTarget(); return true; diff --git a/examples/example_win32_directx11/main.cpp b/examples/example_win32_directx11/main.cpp index 16b7e2cf2..bdb5f14ee 100644 --- a/examples/example_win32_directx11/main.cpp +++ b/examples/example_win32_directx11/main.cpp @@ -250,7 +250,10 @@ bool CreateDeviceD3D(HWND hWnd) // - This must be done for all windows associated to the device. Our DX11 backend does this automatically for secondary viewports that it creates. IDXGIFactory* pSwapChainFactory; if (SUCCEEDED(g_pSwapChain->GetParent(IID_PPV_ARGS(&pSwapChainFactory)))) + { pSwapChainFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER); + pSwapChainFactory->Release(); + } CreateRenderTarget(); return true; From 36de604a5b3f4e726ad5cf4480b150195246d59e Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 16 Oct 2025 16:12:29 +0200 Subject: [PATCH 29/50] InputText: avoid continuously overwriting ownership of ImGuiKey_Enter / ImGuiKey_KeypadEnter in order to allow e.g. external Shortcut to override behavior. (#9004) --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f42a3b030..644ff316d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,6 +47,8 @@ Other Changes: result in temporarily incorrect state, which would lead to bugs to side effects in various locations, e.g. GetContentRegionAvail() calls or using clipper. (#9005) EndTable() was mistakenly restoring a wrong current table. +- InputText: avoid continuously overwriting ownership of ImGuiKey_Enter/_KeypadEnter + keys in order to allow e.g. external Shortcut override behavior. (#9004) - InputTextMultiline: fixed a crash when using ImGuiInputTextFlags_WordWrap and resizing the parent window while keeping the multi-line field active (which is most typically achieved when resizing programmatically or via a docking layout diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index f0b6e2a5f..035d7885a 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4820,7 +4820,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ { // Declare some inputs, the other are registered and polled via Shortcut() routing system. // FIXME: The reason we don't use Shortcut() is we would need a routing flag to specify multiple mods, or to all mods combination into individual shortcuts. - const ImGuiKey always_owned_keys[] = { ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_Enter, ImGuiKey_KeypadEnter, ImGuiKey_Delete, ImGuiKey_Backspace, ImGuiKey_Home, ImGuiKey_End }; + const ImGuiKey always_owned_keys[] = { ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_Delete, ImGuiKey_Backspace, ImGuiKey_Home, ImGuiKey_End }; for (ImGuiKey key : always_owned_keys) SetKeyOwner(key, id); if (user_clicked) @@ -5028,7 +5028,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful. const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; - const bool is_enter_pressed = IsKeyPressed(ImGuiKey_Enter, true) || IsKeyPressed(ImGuiKey_KeypadEnter, true); + const bool is_enter = Shortcut(ImGuiKey_Enter, f_repeat, id) || Shortcut(ImGuiKey_KeypadEnter, f_repeat, id); + const bool is_ctrl_enter = Shortcut(ImGuiMod_Ctrl | ImGuiKey_Enter, f_repeat, id) || Shortcut(ImGuiMod_Ctrl | ImGuiKey_KeypadEnter, f_repeat, id); const bool is_gamepad_validate = nav_gamepad_active && (IsKeyPressed(ImGuiKey_NavGamepadActivate, false) || IsKeyPressed(ImGuiKey_NavGamepadInput, false)); const bool is_cancel = Shortcut(ImGuiKey_Escape, f_repeat, id) || (nav_gamepad_active && Shortcut(ImGuiKey_NavGamepadCancel, f_repeat, id)); @@ -5063,11 +5064,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); } - else if (is_enter_pressed || is_gamepad_validate) + else if (is_enter || is_ctrl_enter || is_gamepad_validate) { // Determine if we turn Enter into a \n character bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0; - if (!is_multiline || is_gamepad_validate || (ctrl_enter_for_new_line != io.KeyCtrl)) + if (!is_multiline || is_gamepad_validate || (ctrl_enter_for_new_line != is_ctrl_enter)) { validated = true; if (io.ConfigInputTextEnterKeepActive && !is_multiline) @@ -5077,7 +5078,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } else if (!is_readonly) { - unsigned int c = '\n'; // Insert new line + // Insert new line + unsigned int c = '\n'; if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data)) state->OnCharPressed(c); } From 3dc511c71dd3155cd8036d64ee87ae0250cb1947 Mon Sep 17 00:00:00 2001 From: BrutPitt Date: Thu, 16 Oct 2025 18:13:34 +0200 Subject: [PATCH 30/50] Backends: WebGPU: update to compile with Dawn and Emscripten's 4.0.10+ '--use-port=emdawnwebgpu' ports. (#8381, #8898) --- backends/imgui_impl_wgpu.cpp | 74 ++++++++++++++++++++---------------- backends/imgui_impl_wgpu.h | 23 ++++++++--- docs/CHANGELOG.txt | 5 +++ 3 files changed, 65 insertions(+), 37 deletions(-) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 3045f9c7c..fe5cd5832 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -1,6 +1,6 @@ // dear imgui: Renderer for WebGPU -// This needs to be used along with a Platform Binding (e.g. GLFW) -// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.) +// This needs to be used along with a Platform Binding (e.g. GLFW, SDL2, SDL3) +// (Please note that WebGPU is a recent API, may not be supported by all browser, and its ecosystem is generally a mess) // Implemented features: // [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID/ImTextureRef! @@ -8,6 +8,8 @@ // [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'. // [X] Renderer: Texture updates support for dynamic font system (ImGuiBackendFlags_RendererHasTextures). +// Read imgui_impl_wgpu.h about how to use the IMGUI_IMPL_WEBGPU_BACKEND_WGPU or IMGUI_IMPL_WEBGPU_BACKEND_DAWN flags. + // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // Learn about Dear ImGui: @@ -18,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-10-16: Update to compile with Dawn and Emscripten's 4.0.10+ '--use-port=emdawnwebgpu' ports. (#8381, #8898) // 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-12: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. (#8465) // 2025-02-26: Recreate image bind groups during render. (#8426, #8046, #7765, #8027) + Update for latest webgpu-native changes. @@ -46,20 +49,20 @@ #include "imgui.h" -// When targeting native platforms (i.e. NOT Emscripten), one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN -// or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details. -#ifndef __EMSCRIPTEN__ - #if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) == defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) - #error exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be defined! - #endif -#else - #if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) - #error neither IMGUI_IMPL_WEBGPU_BACKEND_DAWN nor IMGUI_IMPL_WEBGPU_BACKEND_WGPU may be defined if targeting emscripten! - #endif -#endif - #ifndef IMGUI_DISABLE #include "imgui_impl_wgpu.h" + +// One of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details. +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) == defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) +#error Exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be defined! +#endif + +// This condition is true when it's built with EMSCRIPTEN using -sUSE_WEBGPU=1 flag (deprecated from 4.0.10) +// This condition is false for all other 3 cases: WGPU-Native, DAWN-Native or DAWN-EMSCRIPTEN (using --use-port=emdawnwebgpu flag) +#if defined(__EMSCRIPTEN__) && defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) +#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN +#endif + #include #include @@ -259,7 +262,7 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c { ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData(); -#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) +#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN) WGPUShaderSourceWGSL wgsl_desc = {}; wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL; wgsl_desc.code = { wgsl_source, WGPU_STRLEN }; @@ -275,7 +278,7 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c WGPUProgrammableStageDescriptor stage_desc = {}; stage_desc.module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc); -#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) +#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN) stage_desc.entryPoint = { "main", WGPU_STRLEN }; #else stage_desc.entryPoint = "main"; @@ -398,9 +401,10 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder WGPUBufferDescriptor vb_desc = { nullptr, +#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN) + { "Dear ImGui Vertex buffer", WGPU_STRLEN, }, +#else "Dear ImGui Vertex buffer", -#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) - WGPU_STRLEN, #endif WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex, MEMALIGN(fr->VertexBufferSize * sizeof(ImDrawVert), 4), @@ -425,9 +429,10 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder WGPUBufferDescriptor ib_desc = { nullptr, +#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN) + { "Dear ImGui Index buffer", WGPU_STRLEN, }, +#else "Dear ImGui Index buffer", -#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) - WGPU_STRLEN, #endif WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index, MEMALIGN(fr->IndexBufferSize * sizeof(ImDrawIdx), 4), @@ -560,7 +565,7 @@ void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex) // Create texture WGPUTextureDescriptor tex_desc = {}; -#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) +#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN) tex_desc.label = { "Dear ImGui Texture", WGPU_STRLEN }; #else tex_desc.label = "Dear ImGui Texture"; @@ -605,7 +610,7 @@ void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex) // Update full texture or selected blocks. We only ever write to textures regions which have never been used before! // This backend choose to use tex->UpdateRect but you can use tex->Updates[] to upload individual regions. -#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) +#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN) WGPUTexelCopyTextureInfo dst_view = {}; #else WGPUImageCopyTexture dst_view = {}; @@ -614,7 +619,7 @@ void ImGui_ImplWGPU_UpdateTexture(ImTextureData* tex) dst_view.mipLevel = 0; dst_view.origin = { (uint32_t)upload_x, (uint32_t)upload_y, 0 }; dst_view.aspect = WGPUTextureAspect_All; -#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) +#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN) WGPUTexelCopyBufferLayout layout = {}; #else WGPUTextureDataLayout layout = {}; @@ -636,9 +641,10 @@ static void ImGui_ImplWGPU_CreateUniformBuffer() WGPUBufferDescriptor ub_desc = { nullptr, +#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN) + { "Dear ImGui Uniform buffer", WGPU_STRLEN, }, +#else "Dear ImGui Uniform buffer", -#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) - WGPU_STRLEN, #endif WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform, MEMALIGN(sizeof(Uniforms), 16), @@ -751,7 +757,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() // Create depth-stencil State WGPUDepthStencilState depth_stencil_state = {}; depth_stencil_state.format = bd->depthStencilFormat; -#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) +#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU_EMSCRIPTEN) depth_stencil_state.depthWriteEnabled = WGPUOptionalBool_False; #else depth_stencil_state.depthWriteEnabled = false; @@ -833,14 +839,18 @@ bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info) // Setup backend capabilities flags ImGui_ImplWGPU_Data* bd = IM_NEW(ImGui_ImplWGPU_Data)(); io.BackendRendererUserData = (void*)bd; +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) #if defined(__EMSCRIPTEN__) - io.BackendRendererName = "imgui_impl_webgpu_emscripten"; -#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) - io.BackendRendererName = "imgui_impl_webgpu_dawn"; -#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) - io.BackendRendererName = "imgui_impl_webgpu_wgpu"; + io.BackendRendererName = "imgui_impl_wgpu (Dawn, Emscripten)"; // compiled & linked using EMSCRIPTEN with "--use-port=emdawnwebgpu" flag #else - io.BackendRendererName = "imgui_impl_webgpu"; + io.BackendRendererName = "imgui_impl_wgpu (Dawn, Native)"; +#endif +#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) +#if defined(__EMSCRIPTEN__) + io.BackendRendererName = "imgui_impl_wgpu (WGPU, Emscripten)"; // linked using EMSCRIPTEN with "-sUSE_WEBGPU=1" flag, deprecated from EMSCRIPTEN 4.0.10 +#else + io.BackendRendererName = "imgui_impl_wgpu (WGPU, Native)"; +#endif #endif io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render. diff --git a/backends/imgui_impl_wgpu.h b/backends/imgui_impl_wgpu.h index 499c899a0..9443106b8 100644 --- a/backends/imgui_impl_wgpu.h +++ b/backends/imgui_impl_wgpu.h @@ -1,11 +1,14 @@ // dear imgui: Renderer for WebGPU -// This needs to be used along with a Platform Binding (e.g. GLFW) -// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.) +// This needs to be used along with a Platform Binding (e.g. GLFW, SDL2, SDL3) +// (Please note that WebGPU is a recent API, may not be supported by all browser, and its ecosystem is generally a mess) -// Important note to dawn and/or wgpu users: when targeting native platforms (i.e. NOT emscripten), -// one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. +// When targeting native platforms: +// - One of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU *must* be provided. +// When targeting Emscripten: +// - We now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN is Emscripten version is 4.0.10+, which correspond to using Emscripten '--use-port=emdawnwebgpu'. +// - We can still define IMGUI_IMPL_WEBGPU_BACKEND_WGPU to use Emscripten '-s USE_WEBGPU=1' which is marked as obsolete by Emscripten. // Add #define to your imconfig.h file, or as a compilation flag in your build system. -// This requirement will be removed once WebGPU stabilizes and backends converge on a unified interface. +// This requirement may be removed once WebGPU stabilizes and backends converge on a unified interface. //#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN //#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU @@ -27,6 +30,16 @@ #include "imgui.h" // IMGUI_IMPL_API #ifndef IMGUI_DISABLE +// Setup Emscripten default if not specified. +#if defined(__EMSCRIPTEN__) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) && !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) +#include +#if (__EMSCRIPTEN_major__ >= 4) && (__EMSCRIPTEN_minor__ >= 0) && (__EMSCRIPTEN_tiny__ >= 10) +#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN +#else +#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU +#endif +#endif + #include // Initialization data, for ImGui_ImplWGPU_Init() diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 644ff316d..ad385527a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -53,6 +53,11 @@ Other Changes: resizing the parent window while keeping the multi-line field active (which is most typically achieved when resizing programmatically or via a docking layout reacting to a platform window resize). (#3237, #9007) [@anton-kl, @ocornut] +- Backends: WebGPU: update to compile with Dawn and Emscripten's 4.0.10+ + '--use-port=emdawnwebgpu' ports. (#8381, #8898) [@brutpitt, @trbabb] + When using Emscripten 4.0.10+, backend now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN + instead of IMGUI_IMPL_WEBGPU_BACKEND_WGPU, if neither are specified. + (note: examples application were not updated yet) ----------------------------------------------------------------------- From 71447b94fbdddc19495703d70037172fccd43048 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 16 Oct 2025 18:23:02 +0200 Subject: [PATCH 31/50] Examples: GLFW+WebGPU: default build to legacy for now. (#8381) --- examples/example_glfw_wgpu/Makefile.emscripten | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/example_glfw_wgpu/Makefile.emscripten b/examples/example_glfw_wgpu/Makefile.emscripten index 8ee398bc8..545a50578 100644 --- a/examples/example_glfw_wgpu/Makefile.emscripten +++ b/examples/example_glfw_wgpu/Makefile.emscripten @@ -34,9 +34,16 @@ EMS = # ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only) # Note: For glfw, we use emscripten-glfw port (contrib.glfw3) instead of (-s USE_GLFW=3) to get a better support for High DPI displays. EMS += -s DISABLE_EXCEPTION_CATCHING=1 --use-port=contrib.glfw3 -LDFLAGS += -s USE_WEBGPU=1 LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1 +# (1) Using legacy WebGPU implementation (Emscripten < 4.0.10) +EMS += -DIMGUI_IMPL_WEBGPU_BACKEND_WGPU +LDFLAGS += -s USE_WEBGPU=1 + +# or (2) Using newer Dawn-based WebGPU port (Emscripten >= 4.0.10) (UNSUPPORTED YET) +#EMS += --use-port=emdawnwebgpu +#LDFLAGS += --use-port=emdawnwebgpu + # Build as single file (binary text encoded in .html file) #LDFLAGS += -sSINGLE_FILE From 4b1f5aba80438a27b1ae85400e83e6d21391b0e1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 16 Oct 2025 19:10:10 +0200 Subject: [PATCH 32/50] Examples: GLFW+WebGPU: moving blocks to simplify upcoming diff. (#8381) --- examples/example_glfw_wgpu/main.cpp | 68 +++++++++++------------- examples/example_sdl3_directx11/main.cpp | 2 +- 2 files changed, 33 insertions(+), 37 deletions(-) diff --git a/examples/example_glfw_wgpu/main.cpp b/examples/example_glfw_wgpu/main.cpp index 59bb505a9..874734936 100644 --- a/examples/example_glfw_wgpu/main.cpp +++ b/examples/example_glfw_wgpu/main.cpp @@ -27,17 +27,16 @@ #include // Data -static WGPUInstance wgpu_instance = nullptr; -static WGPUDevice wgpu_device = nullptr; -static WGPUSurface wgpu_surface = nullptr; -static WGPUTextureFormat wgpu_preferred_fmt = WGPUTextureFormat_RGBA8Unorm; -static WGPUSwapChain wgpu_swap_chain = nullptr; -static int wgpu_surface_width = 1280; -static int wgpu_surface_height = 800; +static WGPUInstance wgpu_instance = nullptr; +static WGPUDevice wgpu_device = nullptr; +static WGPUSurface wgpu_surface = nullptr; +static WGPUTextureFormat wgpu_preferred_fmt = WGPUTextureFormat_RGBA8Unorm; +static WGPUSwapChain wgpu_swap_chain = nullptr; +static int wgpu_surface_width = 1280; +static int wgpu_surface_height = 800; // Forward declarations static bool InitWGPU(GLFWwindow* window); -static void ResizeSurface(int width, int height); static void glfw_error_callback(int error, const char* description) { @@ -58,6 +57,21 @@ static void wgpu_error_callback(WGPUErrorType error_type, const char* message, v printf("%s error: %s\n", error_type_lbl, message); } +static void ResizeSurface(int width, int height) +{ + if (wgpu_swap_chain) + wgpuSwapChainRelease(wgpu_swap_chain); + wgpu_surface_width = width; + wgpu_surface_height = height; + WGPUSwapChainDescriptor swap_chain_desc = {}; + swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment; + swap_chain_desc.format = wgpu_preferred_fmt; + swap_chain_desc.width = width; + swap_chain_desc.height = height; + swap_chain_desc.presentMode = WGPUPresentMode_Fifo; + wgpu_swap_chain = wgpuDeviceCreateSwapChain(wgpu_device, wgpu_surface, &swap_chain_desc); +} + // Main code int main(int, char**) { @@ -166,7 +180,7 @@ int main(int, char**) glfwGetFramebufferSize((GLFWwindow*)window, &width, &height); if (width != wgpu_surface_width || height != wgpu_surface_height) { - ImGui_ImplWGPU_InvalidateDeviceObjects(); + ImGui_ImplWGPU_InvalidateDeviceObjects(); // FIXME-OPT: Why doing this? This seems unnecessary and unoptimal. ResizeSurface(width, height); ImGui_ImplWGPU_CreateDeviceObjects(); } @@ -275,21 +289,21 @@ static WGPUAdapter RequestAdapter(WGPUInstance instance) auto onAdapterRequestEnded = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, const char* message, void* pUserData) { if (status == WGPURequestAdapterStatus_Success) - *(WGPUAdapter*)(pUserData) = adapter; + *(WGPUAdapter*)pUserData = adapter; else printf("Could not get WebGPU adapter: %s\n", message); -}; + }; WGPUAdapter adapter; wgpuInstanceRequestAdapter(instance, nullptr, onAdapterRequestEnded, (void*)&adapter); return adapter; } -static WGPUDevice RequestDevice(WGPUAdapter& adapter) +static WGPUDevice RequestDevice(WGPUAdapter adapter) { auto onDeviceRequestEnded = [](WGPURequestDeviceStatus status, WGPUDevice device, const char* message, void* pUserData) { if (status == WGPURequestDeviceStatus_Success) - *(WGPUDevice*)(pUserData) = device; + *(WGPUDevice*)pUserData = device; else printf("Could not get WebGPU device: %s\n", message); }; @@ -307,14 +321,7 @@ static bool InitWGPU(GLFWwindow* window) wgpu_device = emscripten_webgpu_get_device(); if (!wgpu_device) return false; -#else - WGPUAdapter adapter = RequestAdapter(instance.Get()); - if (!adapter) - return false; - wgpu_device = RequestDevice(adapter); -#endif -#ifdef __EMSCRIPTEN__ wgpu::SurfaceDescriptorFromCanvasHTMLSelector canvas_desc = {}; canvas_desc.selector = "#canvas"; wgpu::SurfaceDescriptor surface_desc = {}; @@ -324,6 +331,11 @@ static bool InitWGPU(GLFWwindow* window) wgpu::Adapter adapter = {}; wgpu_preferred_fmt = (WGPUTextureFormat)surface.GetPreferredFormat(adapter); #else + WGPUAdapter adapter = RequestAdapter(instance.Get()); + if (!adapter) + return false; + wgpu_device = RequestDevice(adapter); + wgpu::Surface surface = wgpu::glfw::CreateSurfaceForWindow(instance, window); if (!surface) return false; @@ -335,21 +347,5 @@ static bool InitWGPU(GLFWwindow* window) wgpu_surface = surface.MoveToCHandle(); wgpuDeviceSetUncapturedErrorCallback(wgpu_device, wgpu_error_callback, nullptr); - return true; } - -static void ResizeSurface(int width, int height) -{ - if (wgpu_swap_chain) - wgpuSwapChainRelease(wgpu_swap_chain); - wgpu_surface_width = width; - wgpu_surface_height = height; - WGPUSwapChainDescriptor swap_chain_desc = {}; - swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment; - swap_chain_desc.format = wgpu_preferred_fmt; - swap_chain_desc.width = width; - swap_chain_desc.height = height; - swap_chain_desc.presentMode = WGPUPresentMode_Fifo; - wgpu_swap_chain = wgpuDeviceCreateSwapChain(wgpu_device, wgpu_surface, &swap_chain_desc); -} diff --git a/examples/example_sdl3_directx11/main.cpp b/examples/example_sdl3_directx11/main.cpp index 946992409..39171c8cd 100644 --- a/examples/example_sdl3_directx11/main.cpp +++ b/examples/example_sdl3_directx11/main.cpp @@ -48,7 +48,7 @@ int main(int, char**) } SDL_PropertiesID props = SDL_GetWindowProperties(window); - HWND hwnd = (HWND)SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); + HWND hwnd = (HWND)SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr); // Initialize Direct3D if (!CreateDeviceD3D(hwnd)) From 065f9e02695c4eab92dab548f0c37f5297fc7a63 Mon Sep 17 00:00:00 2001 From: mwlasiuk Date: Wed, 15 Oct 2025 21:34:10 +0200 Subject: [PATCH 33/50] Backends: Vulkan: added IMGUI_IMPL_VULKAN_VOLK_FILENAME. (#9008, #7722, #6582, #4854) --- backends/imgui_impl_vulkan.cpp | 1 + backends/imgui_impl_vulkan.h | 11 ++++++++++- docs/CHANGELOG.txt | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index a8eb9a8c4..baffb7e51 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -27,6 +27,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-10-15: Vulkan: Added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to volk.h header. (#9008) // 2025-09-26: *BREAKING CHANGE*: moved some fields in ImGui_ImplVulkan_InitInfo: init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass, init_info.Subpass --> init_info.PipelineInfoMain.Subpass, init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples, init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo. // 2025-09-26: *BREAKING CHANGE*: renamed ImGui_ImplVulkan_MainPipelineCreateInfo to ImGui_ImplVulkan_PipelineInfo. Introduced very recently so shouldn't affect many users. // 2025-09-26: *BREAKING CHANGE*: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a VkImageUsageFlags image_usage` argument, default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT if 0. diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index afc698701..fb51a2ac0 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -41,9 +41,14 @@ // If you have no idea what this is, leave it alone! //#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES -// Convenience support for Volk +// [Configuration] Convenience support for Volk // (you can also technically use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().) +// (When using Volk from directory outside your include directories list you can specify full path to the volk.h header, +// for example when using Volk from VulkanSDK and using include_directories(${Vulkan_INCLUDE_DIRS})' from 'find_package(Vulkan REQUIRED)') //#define IMGUI_IMPL_VULKAN_USE_VOLK +//#define IMGUI_IMPL_VULKAN_VOLK_FILENAME +//#define IMGUI_IMPL_VULKAN_VOLK_FILENAME // Default +// Reminder: make those changes in your imconfig.h file, not here! #if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES) #define VK_NO_PROTOTYPES @@ -54,7 +59,11 @@ // Vulkan includes #ifdef IMGUI_IMPL_VULKAN_USE_VOLK +#ifdef IMGUI_IMPL_VULKAN_VOLK_FILENAME +#include IMGUI_IMPL_VULKAN_VOLK_FILENAME +#else #include +#endif #else #include #endif diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ad385527a..2213f5866 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -53,6 +53,8 @@ Other Changes: resizing the parent window while keeping the multi-line field active (which is most typically achieved when resizing programmatically or via a docking layout reacting to a platform window resize). (#3237, #9007) [@anton-kl, @ocornut] +- Backends: Vulkan: added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to + Volk (default to "volk.h"). (#9008, #7722, #6582, #4854) [@mwlasiuk] - Backends: WebGPU: update to compile with Dawn and Emscripten's 4.0.10+ '--use-port=emdawnwebgpu' ports. (#8381, #8898) [@brutpitt, @trbabb] When using Emscripten 4.0.10+, backend now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN From e11b7a0414859a51921359e64e664e58d277be9c Mon Sep 17 00:00:00 2001 From: Ingmar Rieger Date: Sat, 18 Oct 2025 17:34:40 +0200 Subject: [PATCH 34/50] Make ClearPlatformHandlers and ClearRendererHandlers API public (#9016) --- imgui.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index 575989a77..99ef32e17 100644 --- a/imgui.h +++ b/imgui.h @@ -3978,8 +3978,8 @@ struct ImGuiPlatformIO // Functions //------------------------------------------------------------------ - void ClearPlatformHandlers(); // Clear all Platform_XXX fields. Typically called on Platform Backend shutdown. - void ClearRendererHandlers(); // Clear all Renderer_XXX fields. Typically called on Renderer Backend shutdown. + IMGUI_API void ClearPlatformHandlers(); // Clear all Platform_XXX fields. Typically called on Platform Backend shutdown. + IMGUI_API void ClearRendererHandlers(); // Clear all Renderer_XXX fields. Typically called on Renderer Backend shutdown. }; // (Optional) Support for IME (Input Method Editor) via the platform_io.Platform_SetImeDataFn() function. Handler is called during EndFrame(). From 63bfad401fb3d44670ecd99dea4fa6d8ef607c46 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 20 Oct 2025 18:58:45 +0200 Subject: [PATCH 35/50] MultiSelect: added ImGuiMultiSelectFlags_NoSelectOnRightClick. (#8200, #9015) --- docs/CHANGELOG.txt | 3 +++ imgui.h | 1 + imgui_demo.cpp | 5 +++++ imgui_widgets.cpp | 4 ++-- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 2213f5866..ecc881700 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -53,6 +53,9 @@ Other Changes: resizing the parent window while keeping the multi-line field active (which is most typically achieved when resizing programmatically or via a docking layout reacting to a platform window resize). (#3237, #9007) [@anton-kl, @ocornut] +- MultiSelect: added ImGuiMultiSelectFlags_NoSelectOnRightClick to disable default + right-click processing, which selects item on mouse down and is designed for + context-menus. (#8200, #9015) - Backends: Vulkan: added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to Volk (default to "volk.h"). (#9008, #7722, #6582, #4854) [@mwlasiuk] - Backends: WebGPU: update to compile with Dawn and Emscripten's 4.0.10+ diff --git a/imgui.h b/imgui.h index 99ef32e17..c2ea4aa50 100644 --- a/imgui.h +++ b/imgui.h @@ -3003,6 +3003,7 @@ enum ImGuiMultiSelectFlags_ ImGuiMultiSelectFlags_SelectOnClickRelease = 1 << 14, // Apply selection on mouse release when clicking an unselected item. Allow dragging an unselected item without altering selection. //ImGuiMultiSelectFlags_RangeSelect2d = 1 << 15, // Shift+Selection uses 2d geometry instead of linear sequence, so possible to use Shift+up/down to select vertically in grid. Analogous to what BoxSelect does. ImGuiMultiSelectFlags_NavWrapX = 1 << 16, // [Temporary] Enable navigation wrapping on X axis. Provided as a convenience because we don't have a design for the general Nav API for this yet. When the more general feature be public we may obsolete this flag in favor of new one. + ImGuiMultiSelectFlags_NoSelectOnRightClick = 1 << 17, // Disable default right-click processing, which selects item on mouse down, and is designed for context-menus. }; // Main IO structure returned by BeginMultiSelect()/EndMultiSelect(). diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 0c8e51b5c..8f0e393a1 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2647,6 +2647,10 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d { HelpMarker("Selections can be built using Selectable(), TreeNode() or other widgets. Selection state is owned by application code/data."); + ImGui::BulletText("Wiki page:"); + ImGui::SameLine(); + ImGui::TextLinkOpenURL("imgui/wiki/Multi-Select", "https://github.com/ocornut/imgui/wiki/Multi-Select"); + // Without any fancy API: manage single-selection yourself. IMGUI_DEMO_MARKER("Widgets/Selection State/Single-Select"); if (ImGui::TreeNode("Single-Select")) @@ -3180,6 +3184,7 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoSelect", &flags, ImGuiMultiSelectFlags_NoAutoSelect); ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClear", &flags, ImGuiMultiSelectFlags_NoAutoClear); ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClearOnReselect", &flags, ImGuiMultiSelectFlags_NoAutoClearOnReselect); + ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoSelectOnRightClick", &flags, ImGuiMultiSelectFlags_NoSelectOnRightClick); ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect1d", &flags, ImGuiMultiSelectFlags_BoxSelect1d); ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect2d", &flags, ImGuiMultiSelectFlags_BoxSelect2d); ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelectNoScroll", &flags, ImGuiMultiSelectFlags_BoxSelectNoScroll); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 035d7885a..4033203da 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -8213,8 +8213,8 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed) } // Right-click handling. - // FIXME-MULTISELECT: Currently filtered out by ImGuiMultiSelectFlags_NoAutoSelect but maybe should be moved to Selectable(). See https://github.com/ocornut/imgui/pull/5816 - if (hovered && IsMouseClicked(1) && (flags & ImGuiMultiSelectFlags_NoAutoSelect) == 0) + // FIXME-MULTISELECT: Maybe should be moved to Selectable()? Also see #5816, #8200, #9015 + if (hovered && IsMouseClicked(1) && (flags & (ImGuiMultiSelectFlags_NoAutoSelect | ImGuiMultiSelectFlags_NoSelectOnRightClick)) == 0) { if (g.ActiveId != 0 && g.ActiveId != id) ClearActiveID(); From b46f099a3fcb837af9c22e1721b6563c8afa43d4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 20 Oct 2025 23:57:09 +0200 Subject: [PATCH 36/50] Backends: GLFW: fixed building on Linux platforms where Wayland headers are not available. (#9024, #8969, #8921, #8920) --- backends/imgui_impl_glfw.cpp | 3 --- docs/CHANGELOG.txt | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index d98248acc..d7c208b93 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -126,9 +126,6 @@ #ifndef GLFW_EXPOSE_NATIVE_X11 // for glfwGetX11Display(), glfwGetX11Window() on Freedesktop (Linux, BSD, etc.) #define GLFW_EXPOSE_NATIVE_X11 #endif -#ifndef GLFW_EXPOSE_NATIVE_WAYLAND -#define GLFW_EXPOSE_NATIVE_WAYLAND -#endif #include #endif #undef Status // X11 headers are leaking this. diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ecc881700..a605dbef1 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -56,6 +56,8 @@ Other Changes: - MultiSelect: added ImGuiMultiSelectFlags_NoSelectOnRightClick to disable default right-click processing, which selects item on mouse down and is designed for context-menus. (#8200, #9015) +- Backends: GLFW: fixed building on Linux platforms where Wayland headers + are not available. (#9024, #8969, #8921, #8920) [@jagot] - Backends: Vulkan: added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to Volk (default to "volk.h"). (#9008, #7722, #6582, #4854) [@mwlasiuk] - Backends: WebGPU: update to compile with Dawn and Emscripten's 4.0.10+ From bdb8243602d2b61f253dd88acb6ff0044dc4152b Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 22 Oct 2025 13:33:36 +0200 Subject: [PATCH 37/50] Backends: SDl3: Fixed Platform_OpenInShellFn() return value. (#9027) --- backends/imgui_impl_sdl3.cpp | 3 ++- docs/CHANGELOG.txt | 2 ++ imgui.h | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 564131a4d..3ddd4a7f7 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-10-22: Fixed Platform_OpenInShellFn() return value (unused in core). // 2025-09-24: Skip using the SDL_GetGlobalMouseState() state when one of our window is hovered, as the SDL_EVENT_MOUSE_MOTION data is reliable. Fix macOS notch mouse coordinates issue in fullscreen mode + better perf on X11. (#7919, #7786) // 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown. // 2025-09-15: Use SDL_GetWindowDisplayScale() on Mac to output DisplayFrameBufferScale. The function is more reliable during resolution changes e.g. going fullscreen. (#8703, #4414) @@ -505,7 +506,7 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL3_SetClipboardText; platform_io.Platform_GetClipboardTextFn = ImGui_ImplSDL3_GetClipboardText; platform_io.Platform_SetImeDataFn = ImGui_ImplSDL3_PlatformSetImeData; - platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url) == 0; }; + platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url); }; // Gamepad handling bd->GamepadMode = ImGui_ImplSDL3_GamepadMode_AutoFirst; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a605dbef1..91a17051c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -58,6 +58,8 @@ Other Changes: context-menus. (#8200, #9015) - Backends: GLFW: fixed building on Linux platforms where Wayland headers are not available. (#9024, #8969, #8921, #8920) [@jagot] +- Backends: SDL3: fixed Platform_OpenInShellFn() return value (the return value + was unused in core but might be used by a direct caller). (#9027) [@achabense] - Backends: Vulkan: added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to Volk (default to "volk.h"). (#9008, #7722, #6582, #4854) [@mwlasiuk] - Backends: WebGPU: update to compile with Dawn and Emscripten's 4.0.10+ diff --git a/imgui.h b/imgui.h index c2ea4aa50..4ecca7f78 100644 --- a/imgui.h +++ b/imgui.h @@ -3942,7 +3942,7 @@ struct ImGuiPlatformIO void* Platform_ClipboardUserData; // Optional: Open link/folder/file in OS Shell - // (default to use ShellExecuteW() on Windows, system() on Linux/Mac) + // (default to use ShellExecuteW() on Windows, system() on Linux/Mac. expected to return false on failure, but some platforms may always return true) bool (*Platform_OpenInShellFn)(ImGuiContext* ctx, const char* path); void* Platform_OpenInShellUserData; From a47064966b713991de3e4e64cca2be6bf076a707 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 22 Oct 2025 13:38:45 +0200 Subject: [PATCH 38/50] Examples: GLFW+WebGPU: fixed cmakefile for example to use legacy path. (#8381) Amend 71447b94f --- examples/example_glfw_wgpu/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_glfw_wgpu/CMakeLists.txt b/examples/example_glfw_wgpu/CMakeLists.txt index 8e164e488..d21bb0919 100644 --- a/examples/example_glfw_wgpu/CMakeLists.txt +++ b/examples/example_glfw_wgpu/CMakeLists.txt @@ -34,7 +34,7 @@ if(EMSCRIPTEN) set(IMGUI_EMSCRIPTEN_GLFW3 "-sUSE_GLFW=3" CACHE STRING "Use -sUSE_GLFW=3 for GLFW implementation" FORCE) endif() set(LIBRARIES glfw) - add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1) + add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1 -DIMGUI_IMPL_WEBGPU_BACKEND_WGPU) else() # Dawn wgpu desktop set(DAWN_FETCH_DEPENDENCIES ON) From 5870b979a870a7364564df1dd50542b494590a0e Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 22 Oct 2025 13:38:45 +0200 Subject: [PATCH 39/50] Examples: GLFW+WebGPU: fixed cmakefile for example to use legacy path. (#8381) Amend 71447b94f --- examples/example_glfw_wgpu/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_glfw_wgpu/CMakeLists.txt b/examples/example_glfw_wgpu/CMakeLists.txt index 8e164e488..d21bb0919 100644 --- a/examples/example_glfw_wgpu/CMakeLists.txt +++ b/examples/example_glfw_wgpu/CMakeLists.txt @@ -34,7 +34,7 @@ if(EMSCRIPTEN) set(IMGUI_EMSCRIPTEN_GLFW3 "-sUSE_GLFW=3" CACHE STRING "Use -sUSE_GLFW=3 for GLFW implementation" FORCE) endif() set(LIBRARIES glfw) - add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1) + add_compile_options(-sDISABLE_EXCEPTION_CATCHING=1 -DIMGUI_DISABLE_FILE_FUNCTIONS=1 -DIMGUI_IMPL_WEBGPU_BACKEND_WGPU) else() # Dawn wgpu desktop set(DAWN_FETCH_DEPENDENCIES ON) From 2a022d997b14ec019cf761ea0c71cdddf6b5029d Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 22 Oct 2025 13:41:45 +0200 Subject: [PATCH 40/50] Examples: GLFW+WebGPU: removed unnecessary ImGui_ImplWGPU_InvalidateDeviceObjects() call during surface resize. (#8381) + Relayout changelog. --- docs/CHANGELOG.txt | 26 +++++++++++++++----------- examples/example_glfw_wgpu/main.cpp | 4 ---- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 91a17051c..bc6b8f3ae 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -56,17 +56,21 @@ Other Changes: - MultiSelect: added ImGuiMultiSelectFlags_NoSelectOnRightClick to disable default right-click processing, which selects item on mouse down and is designed for context-menus. (#8200, #9015) -- Backends: GLFW: fixed building on Linux platforms where Wayland headers - are not available. (#9024, #8969, #8921, #8920) [@jagot] -- Backends: SDL3: fixed Platform_OpenInShellFn() return value (the return value - was unused in core but might be used by a direct caller). (#9027) [@achabense] -- Backends: Vulkan: added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to - Volk (default to "volk.h"). (#9008, #7722, #6582, #4854) [@mwlasiuk] -- Backends: WebGPU: update to compile with Dawn and Emscripten's 4.0.10+ - '--use-port=emdawnwebgpu' ports. (#8381, #8898) [@brutpitt, @trbabb] - When using Emscripten 4.0.10+, backend now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN - instead of IMGUI_IMPL_WEBGPU_BACKEND_WGPU, if neither are specified. - (note: examples application were not updated yet) +- Backends: + - GLFW: fixed building on Linux platforms where Wayland headers + are not available. (#9024, #8969, #8921, #8920) [@jagot] + - SDL3: fixed Platform_OpenInShellFn() return value (the return value + was unused in core but might be used by a direct caller). (#9027) [@achabense] + - Vulkan: added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to + Volk (default to "volk.h"). (#9008, #7722, #6582, #4854) [@mwlasiuk] + - WebGPU: update to compile with Dawn and Emscripten's 4.0.10+ + '--use-port=emdawnwebgpu' ports. (#8381, #8898) [@brutpitt, @trbabb] + When using Emscripten 4.0.10+, backend now defaults to IMGUI_IMPL_WEBGPU_BACKEND_DAWN + instead of IMGUI_IMPL_WEBGPU_BACKEND_WGPU, if neither are specified. + (note: examples application were not updated yet) +- Examples: + - GLFW+WebGPU: removed unnecessary ImGui_ImplWGPU_InvalidateDeviceObjects() call + during surface resize. (#8381) ----------------------------------------------------------------------- diff --git a/examples/example_glfw_wgpu/main.cpp b/examples/example_glfw_wgpu/main.cpp index 874734936..88c504007 100644 --- a/examples/example_glfw_wgpu/main.cpp +++ b/examples/example_glfw_wgpu/main.cpp @@ -179,11 +179,7 @@ int main(int, char**) int width, height; glfwGetFramebufferSize((GLFWwindow*)window, &width, &height); if (width != wgpu_surface_width || height != wgpu_surface_height) - { - ImGui_ImplWGPU_InvalidateDeviceObjects(); // FIXME-OPT: Why doing this? This seems unnecessary and unoptimal. ResizeSurface(width, height); - ImGui_ImplWGPU_CreateDeviceObjects(); - } // Start the Dear ImGui frame ImGui_ImplWGPU_NewFrame(); From b3dab0a406b80d30101b90cde79a93f3344e9a6f Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 22 Oct 2025 13:57:27 +0200 Subject: [PATCH 41/50] Examples: DirectX10, DirectX11, DirectX12: comments about fullscreen mode and swapchain setup. (#8979) --- examples/example_sdl2_directx11/main.cpp | 1 + examples/example_sdl3_directx11/main.cpp | 1 + examples/example_win32_directx10/main.cpp | 1 + examples/example_win32_directx11/main.cpp | 1 + examples/example_win32_directx12/main.cpp | 3 ++- 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/example_sdl2_directx11/main.cpp b/examples/example_sdl2_directx11/main.cpp index e14085dd3..c5a315af4 100644 --- a/examples/example_sdl2_directx11/main.cpp +++ b/examples/example_sdl2_directx11/main.cpp @@ -210,6 +210,7 @@ int main(int, char**) bool CreateDeviceD3D(HWND hWnd) { // Setup swap chain + // This is a basic setup. Optimally could use e.g. DXGI_SWAP_EFFECT_FLIP_DISCARD and handle fullscreen mode differently. See #8979 for suggestions. DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 2; diff --git a/examples/example_sdl3_directx11/main.cpp b/examples/example_sdl3_directx11/main.cpp index 39171c8cd..7107a0574 100644 --- a/examples/example_sdl3_directx11/main.cpp +++ b/examples/example_sdl3_directx11/main.cpp @@ -205,6 +205,7 @@ int main(int, char**) bool CreateDeviceD3D(HWND hWnd) { // Setup swap chain + // This is a basic setup. Optimally could use e.g. DXGI_SWAP_EFFECT_FLIP_DISCARD and handle fullscreen mode differently. See #8979 for suggestions. DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 2; diff --git a/examples/example_win32_directx10/main.cpp b/examples/example_win32_directx10/main.cpp index 6fd10f83d..76c1403b3 100644 --- a/examples/example_win32_directx10/main.cpp +++ b/examples/example_win32_directx10/main.cpp @@ -198,6 +198,7 @@ int main(int, char**) bool CreateDeviceD3D(HWND hWnd) { // Setup swap chain + // This is a basic setup. Optimally could use e.g. DXGI_SWAP_EFFECT_FLIP_DISCARD and handle fullscreen mode differently. See #8979 for suggestions. DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 2; diff --git a/examples/example_win32_directx11/main.cpp b/examples/example_win32_directx11/main.cpp index 5b88007a9..fa3c4883e 100644 --- a/examples/example_win32_directx11/main.cpp +++ b/examples/example_win32_directx11/main.cpp @@ -198,6 +198,7 @@ int main(int, char**) bool CreateDeviceD3D(HWND hWnd) { // Setup swap chain + // This is a basic setup. Optimally could use e.g. DXGI_SWAP_EFFECT_FLIP_DISCARD and handle fullscreen mode differently. See #8979 for suggestions. DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 2; diff --git a/examples/example_win32_directx12/main.cpp b/examples/example_win32_directx12/main.cpp index c8578b54c..5a8dc0381 100644 --- a/examples/example_win32_directx12/main.cpp +++ b/examples/example_win32_directx12/main.cpp @@ -312,6 +312,7 @@ int main(int, char**) bool CreateDeviceD3D(HWND hWnd) { // Setup swap chain + // This is a basic setup. Optimally could handle fullscreen mode differently. See #8979 for suggestions. DXGI_SWAP_CHAIN_DESC1 sd; { ZeroMemory(&sd, sizeof(sd)); @@ -525,7 +526,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) DXGI_SWAP_CHAIN_DESC1 desc = {}; g_pSwapChain->GetDesc1(&desc); HRESULT result = g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), desc.Format, desc.Flags); - assert(SUCCEEDED(result) && "Failed to resize swapchain."); + IM_ASSERT(SUCCEEDED(result) && "Failed to resize swapchain."); CreateRenderTarget(); } return 0; From bc5da9b367ef848a31b572209ff71dc74f60acff Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 22 Oct 2025 13:58:51 +0200 Subject: [PATCH 42/50] Examples: DirectX10: Amends. (#8979) --- examples/example_win32_directx10/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_win32_directx10/main.cpp b/examples/example_win32_directx10/main.cpp index 76c1403b3..086935099 100644 --- a/examples/example_win32_directx10/main.cpp +++ b/examples/example_win32_directx10/main.cpp @@ -198,7 +198,7 @@ int main(int, char**) bool CreateDeviceD3D(HWND hWnd) { // Setup swap chain - // This is a basic setup. Optimally could use e.g. DXGI_SWAP_EFFECT_FLIP_DISCARD and handle fullscreen mode differently. See #8979 for suggestions. + // This is a basic setup. Optimally could use handle fullscreen mode differently. See #8979 for suggestions. DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 2; From b8573a7e33d76705a206fa556929b9ecd5326e01 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 23 Oct 2025 13:54:14 +0200 Subject: [PATCH 43/50] Groups: fixed an issue reporting IsItemEdited() signal after EndGroup() for some widgets e.g. Checkbox(), Selectable(). (#9028) --- docs/CHANGELOG.txt | 4 ++++ imgui.cpp | 3 ++- imgui.h | 2 +- imgui_internal.h | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index bc6b8f3ae..932edd3e8 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -56,6 +56,10 @@ Other Changes: - MultiSelect: added ImGuiMultiSelectFlags_NoSelectOnRightClick to disable default right-click processing, which selects item on mouse down and is designed for context-menus. (#8200, #9015) +- Groups: fixed an issue reporting IsItemEdited() signal after EndGroup() when + triggered by some widgets e.g. Checkbox(), Selectable() and many others, which + cleared ActiveId at the same time as editing. (#9028) + Note that IsItemDeactivatedAfterEdit() was not affected, only IsItemEdited). - Backends: - GLFW: fixed building on Linux platforms where Wayland headers are not available. (#9024, #8969, #8921, #8920) [@jagot] diff --git a/imgui.cpp b/imgui.cpp index b9845a6f1..66e1c0e2d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11518,6 +11518,7 @@ void ImGui::BeginGroup() group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive; group_data.BackupHoveredIdIsAlive = g.HoveredId != 0; group_data.BackupIsSameLine = window->DC.IsSameLine; + group_data.BackupActiveIdHasBeenEditedThisFrame = g.ActiveIdHasBeenEditedThisFrame; group_data.BackupDeactivatedIdIsAlive = g.DeactivatedItemData.IsAlive; group_data.EmitItem = true; @@ -11582,7 +11583,7 @@ void ImGui::EndGroup() g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow; // Forward Edited flag - if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame) + if (g.ActiveIdHasBeenEditedThisFrame && !group_data.BackupActiveIdHasBeenEditedThisFrame) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited; // Forward Deactivated flag diff --git a/imgui.h b/imgui.h index 4ecca7f78..b58f09430 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.5 WIP" -#define IMGUI_VERSION_NUM 19241 +#define IMGUI_VERSION_NUM 19242 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198 diff --git a/imgui_internal.h b/imgui_internal.h index 701652e4b..340f1482a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1173,6 +1173,7 @@ struct IMGUI_API ImGuiGroupData ImVec2 BackupCurrLineSize; float BackupCurrLineTextBaseOffset; ImGuiID BackupActiveIdIsAlive; + bool BackupActiveIdHasBeenEditedThisFrame; bool BackupDeactivatedIdIsAlive; bool BackupHoveredIdIsAlive; bool BackupIsSameLine; From 05531f898eedc7bfde0f07aef99e1434d70e2ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Tassoux?= Date: Mon, 20 Oct 2025 19:00:31 +0200 Subject: [PATCH 44/50] Backends: DirectX12: Fixed an issue in synchronization logic improving rendering throughput for secondary viewports. (#9025, #8961) --- backends/imgui_impl_dx12.cpp | 4 ++-- docs/CHANGELOG.txt | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index ed22e7f08..2470acb38 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -23,6 +23,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-10-23: [Docking] DirectX12: Fixed an issue in synchronization logic improving rendering throughput for secondary viewports. (#8961, #9025) // 2025-10-11: DirectX12: Reuse texture upload buffer and grow it only when necessary. (#9002) // 2025-09-29: DirectX12: Rework synchronization logic. (#8961) // 2025-09-29: DirectX12: Enable swapchain tearing to eliminate viewports framerate throttling. (#8965) @@ -294,8 +295,8 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL // FIXME: We are assuming that this only gets called once per frame! ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); ImGui_ImplDX12_ViewportData* vd = (ImGui_ImplDX12_ViewportData*)draw_data->OwnerViewport->RendererUserData; - vd->FrameIndex++; ImGui_ImplDX12_RenderBuffers* fr = &vd->FrameRenderBuffers[vd->FrameIndex % bd->numFramesInFlight]; + vd->FrameIndex++; // Create and grow vertex/index buffers if needed if (fr->VertexBuffer == nullptr || fr->VertexBufferSize < draw_data->TotalVtxCount) @@ -1280,7 +1281,6 @@ static void ImGui_ImplDX12_SwapBuffers(ImGuiViewport* viewport, void*) ImGui_ImplDX12_ViewportData* vd = (ImGui_ImplDX12_ViewportData*)viewport->RendererUserData; vd->SwapChain->Present(0, bd->tearingSupport ? DXGI_PRESENT_ALLOW_TEARING : 0); - vd->FrameIndex++; } void ImGui_ImplDX12_InitMultiViewportSupport() diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f584079ef..3777db217 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -63,8 +63,12 @@ Other Changes: Docking+Viewports Branch: -- Examples: SDL2+DX11, SDL3+DX11, Win32+DX10, Win32+DX11: fixed one resource - leak from the use of MakeWindowAssociation() in 1.92.4. (#9010, #4350) [@o-3-o] +- Examples: + - SDL2+DX11, SDL3+DX11, Win32+DX10, Win32+DX11: fixed one resource leak + from the use of MakeWindowAssociation() in 1.92.4. (#9010, #4350) [@o-3-o] +- Backends: + - DirectX12: Fixed an issue in synchronization logic improving rendering + throughput for secondary viewports. (#9025, #8961) ----------------------------------------------------------------------- From e571ccf3f431c224e3c71ae98f8fbad8245ec241 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 23 Oct 2025 18:42:12 +0200 Subject: [PATCH 45/50] InputText: removed unnecessary variables. --- imgui_widgets.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 4033203da..910c73d36 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5262,10 +5262,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ callback_data.BufTextLen = state->TextLen; callback_data.BufSize = state->BufCapacity; callback_data.BufDirty = false; - - const int utf8_cursor_pos = callback_data.CursorPos = state->Stb->cursor; - const int utf8_selection_start = callback_data.SelectionStart = state->Stb->select_start; - const int utf8_selection_end = callback_data.SelectionEnd = state->Stb->select_end; + callback_data.CursorPos = state->Stb->cursor; + callback_data.SelectionStart = state->Stb->select_start; + callback_data.SelectionEnd = state->Stb->select_end; // Call user code callback(&callback_data); @@ -5276,9 +5275,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ IM_ASSERT(callback_data.BufSize == state->BufCapacity); IM_ASSERT(callback_data.Flags == flags); const bool buf_dirty = callback_data.BufDirty; - if (callback_data.CursorPos != utf8_cursor_pos || buf_dirty) { state->Stb->cursor = callback_data.CursorPos; state->CursorFollow = true; } - if (callback_data.SelectionStart != utf8_selection_start || buf_dirty) { state->Stb->select_start = (callback_data.SelectionStart == callback_data.CursorPos) ? state->Stb->cursor : callback_data.SelectionStart; } - if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb->select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb->select_start : callback_data.SelectionEnd; } + if (buf_dirty || callback_data.CursorPos != state->Stb->cursor) { state->Stb->cursor = callback_data.CursorPos; state->CursorFollow = true; } + if (buf_dirty || callback_data.SelectionStart != state->Stb->select_start) { state->Stb->select_start = (callback_data.SelectionStart == callback_data.CursorPos) ? state->Stb->cursor : callback_data.SelectionStart; } + if (buf_dirty || callback_data.SelectionEnd != state->Stb->select_end) { state->Stb->select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb->select_start : callback_data.SelectionEnd; } if (buf_dirty) { // Callback may update buffer and thus set buf_dirty even in read-only mode. From 750c5d2a618b39b3e88a5556d72157651c0e5e28 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 23 Oct 2025 18:54:32 +0200 Subject: [PATCH 46/50] InputText: do not require anymore that CursorPos be clamped by user code. (#9029) Add clamping outside of callback code + simplify logic. The previous logic checking for difference was because old code e.g. 21d03edcb0 required a ImTextCountCharsFromUtf8() which is not required since #7925. --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 932edd3e8..3b2587547 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -49,6 +49,8 @@ Other Changes: EndTable() was mistakenly restoring a wrong current table. - InputText: avoid continuously overwriting ownership of ImGuiKey_Enter/_KeypadEnter keys in order to allow e.g. external Shortcut override behavior. (#9004) +- InputText: when using a callback to reduce/manipulate the value of BufTextLen, + we do not require anymore that CursorPos be clamped by user code. (#9029) - InputTextMultiline: fixed a crash when using ImGuiInputTextFlags_WordWrap and resizing the parent window while keeping the multi-line field active (which is most typically achieved when resizing programmatically or via a docking layout diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 910c73d36..97fb208ee 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5274,11 +5274,12 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ IM_ASSERT(callback_data.Buf == callback_buf); // Invalid to modify those fields IM_ASSERT(callback_data.BufSize == state->BufCapacity); IM_ASSERT(callback_data.Flags == flags); - const bool buf_dirty = callback_data.BufDirty; - if (buf_dirty || callback_data.CursorPos != state->Stb->cursor) { state->Stb->cursor = callback_data.CursorPos; state->CursorFollow = true; } - if (buf_dirty || callback_data.SelectionStart != state->Stb->select_start) { state->Stb->select_start = (callback_data.SelectionStart == callback_data.CursorPos) ? state->Stb->cursor : callback_data.SelectionStart; } - if (buf_dirty || callback_data.SelectionEnd != state->Stb->select_end) { state->Stb->select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb->select_start : callback_data.SelectionEnd; } - if (buf_dirty) + if (callback_data.BufDirty || callback_data.CursorPos != state->Stb->cursor) + state->CursorFollow = true; + state->Stb->cursor = ImClamp(callback_data.CursorPos, 0, callback_data.BufTextLen); + state->Stb->select_start = ImClamp(callback_data.SelectionStart, 0, callback_data.BufTextLen); + state->Stb->select_end = ImClamp(callback_data.SelectionEnd, 0, callback_data.BufTextLen); + if (callback_data.BufDirty) { // Callback may update buffer and thus set buf_dirty even in read-only mode. IM_ASSERT(callback_data.BufTextLen == (int)ImStrlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text! From 6add99f8d22b7a3a3d79bc9d3a8bac3f07d4b4f3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 23 Oct 2025 20:00:57 +0200 Subject: [PATCH 47/50] Examples: SDL3+Vulkan: Fixed call to ImGui_ImplVulkanH_CreateOrResizeWindow() during resize. (#9030) Surprisingly it still worked because ImGui_ImplVulkanH_CreateWindowSwapChain() pulls from `cap.currentExtent` when available. --- examples/example_sdl3_vulkan/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_sdl3_vulkan/main.cpp b/examples/example_sdl3_vulkan/main.cpp index 6f67e990d..51de52db0 100644 --- a/examples/example_sdl3_vulkan/main.cpp +++ b/examples/example_sdl3_vulkan/main.cpp @@ -479,7 +479,7 @@ int main(int, char**) if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height)) { ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_height, fb_height, g_MinImageCount, g_SwapChainImageUsage); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, g_SwapChainImageUsage); g_MainWindowData.FrameIndex = 0; g_SwapChainRebuild = false; } From b7e45b3a48a4a447e3e64beef9e775a6a8c8c6eb Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 23 Oct 2025 20:16:44 +0200 Subject: [PATCH 48/50] InputText: rework STB_TEXTEDIT_INSERTCHARS() signature to allow partial insertion (unused). (#9029) To be submitted as a PR to nothings/stb. --- imgui_widgets.cpp | 8 ++++---- imstb_textedit.h | 20 +++++++++++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 97fb208ee..c83158360 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4142,21 +4142,21 @@ static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n) obj->TextLen -= n; } -static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const char* new_text, int new_text_len) +static int STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const char* new_text, int new_text_len) { const bool is_resizable = (obj->Flags & ImGuiInputTextFlags_CallbackResize) != 0; const int text_len = obj->TextLen; IM_ASSERT(pos <= text_len); if (!is_resizable && (new_text_len + obj->TextLen + 1 > obj->BufCapacity)) - return false; + return 0; // Grow internal buffer if needed IM_ASSERT(obj->TextSrc == obj->TextA.Data); if (new_text_len + text_len + 1 > obj->TextA.Size) { if (!is_resizable) - return false; + return 0; obj->TextA.resize(text_len + ImClamp(new_text_len, 32, ImMax(256, new_text_len)) + 1); obj->TextSrc = obj->TextA.Data; } @@ -4170,7 +4170,7 @@ static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const ch obj->TextLen += new_text_len; obj->TextA[obj->TextLen] = '\0'; - return true; + return new_text_len; } // We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols) diff --git a/imstb_textedit.h b/imstb_textedit.h index c41078c8a..583508f0b 100644 --- a/imstb_textedit.h +++ b/imstb_textedit.h @@ -5,7 +5,8 @@ // - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783) // - Added name to struct or it may be forward declared in our code. // - Added UTF-8 support (see https://github.com/nothings/stb/issues/188 + https://github.com/ocornut/imgui/pull/7925) -// Grep for [DEAR IMGUI] to find the changes. +// - Changed STB_TEXTEDIT_INSERTCHARS() to return inserted count (instead of 0/1 bool), allowing partial insertion. +// Grep for [DEAR IMGUI] to find some changes. // - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_* // stb_textedit.h - v1.14 - public domain - Sean Barrett @@ -39,6 +40,7 @@ // // VERSION HISTORY // +// !!!! (2025-10-23) changed STB_TEXTEDIT_INSERTCHARS() to return inserted count (instead of 0/1 bool), allowing partial insertion. // 1.14 (2021-07-11) page up/down, various fixes // 1.13 (2019-02-07) fix bug in undo size management // 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash @@ -147,7 +149,8 @@ // as manually wordwrapping for end-of-line positioning // // STB_TEXTEDIT_DELETECHARS(obj,i,n) delete n characters starting at i -// STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*) +// STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) try to insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*) +// returns number of characters actually inserted. [DEAR IMGUI] // // STB_TEXTEDIT_K_SHIFT a power of two that is or'd in to a keyboard input to represent the shift key // @@ -775,7 +778,8 @@ static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditS stb_textedit_clamp(str, state); stb_textedit_delete_selection(str,state); // try to insert the characters - if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) { + len = STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len); + if (len) { stb_text_makeundo_insert(state, state->cursor, len); state->cursor += len; state->has_preferred_x = 0; @@ -800,13 +804,15 @@ static void stb_textedit_text(IMSTB_TEXTEDIT_STRING* str, STB_TexteditState* sta if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) { stb_text_makeundo_replace(str, state, state->cursor, 1, 1); STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1); - if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) { + text_len = STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len); + if (text_len) { state->cursor += text_len; state->has_preferred_x = 0; } } else { stb_textedit_delete_selection(str, state); // implicitly clamps - if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) { + text_len = STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len); + if (text_len) { stb_text_makeundo_insert(state, state->cursor, text_len); state->cursor += text_len; state->has_preferred_x = 0; @@ -1352,7 +1358,7 @@ static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) // check type of recorded action: if (u.insert_length) { // easy case: was a deletion, so we need to insert n characters - STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length); + u.insert_length = STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length); s->undo_char_point -= u.insert_length; } @@ -1403,7 +1409,7 @@ static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) if (r.insert_length) { // easy case: need to insert n characters - STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length); + r.insert_length = STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length); s->redo_char_point += r.insert_length; } From e6125361f988d6ed94a2e1593ab929e2b8ce1d83 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 23 Oct 2025 20:53:29 +0200 Subject: [PATCH 49/50] InputText: paste does a truncate when not fitting instead of ignoring it. (#9029) --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 30 +++++++++++++++++++----------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3b2587547..4b7cd65c6 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,6 +47,8 @@ Other Changes: result in temporarily incorrect state, which would lead to bugs to side effects in various locations, e.g. GetContentRegionAvail() calls or using clipper. (#9005) EndTable() was mistakenly restoring a wrong current table. +- InputText: when buffer is not resizable, trying to paste contents that + cannot fit will now truncate text instead of ignoring the paste. (#9029) - InputText: avoid continuously overwriting ownership of ImGuiKey_Enter/_KeypadEnter keys in order to allow e.g. external Shortcut override behavior. (#9004) - InputText: when using a callback to reduce/manipulate the value of BufTextLen, diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c83158360..e2a8e9580 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4148,15 +4148,17 @@ static int STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const cha const int text_len = obj->TextLen; IM_ASSERT(pos <= text_len); - if (!is_resizable && (new_text_len + obj->TextLen + 1 > obj->BufCapacity)) + // We support partial insertion (with a mod in stb_textedit.h) + const int avail = obj->BufCapacity - 1 - obj->TextLen; + if (!is_resizable && new_text_len > avail) + new_text_len = avail; // 0 + if (new_text_len == 0) return 0; // Grow internal buffer if needed IM_ASSERT(obj->TextSrc == obj->TextA.Data); - if (new_text_len + text_len + 1 > obj->TextA.Size) + if (text_len + new_text_len + 1 > obj->TextA.Size && is_resizable) { - if (!is_resizable) - return 0; obj->TextA.resize(text_len + ImClamp(new_text_len, 32, ImMax(256, new_text_len)) + 1); obj->TextSrc = obj->TextA.Data; } @@ -4205,7 +4207,8 @@ static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* st state->cursor = state->select_start = state->select_end = 0; if (text_len <= 0) return; - if (ImStb::STB_TEXTEDIT_INSERTCHARS(str, 0, text, text_len)) + int text_len_inserted = ImStb::STB_TEXTEDIT_INSERTCHARS(str, 0, text, text_len); + if (text_len_inserted > 0) { state->cursor = state->select_start = state->select_end = text_len; state->has_preferred_x = 0; @@ -4300,15 +4303,20 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons ImGuiContext& g = *Ctx; ImGuiInputTextState* obj = &g.InputTextState; IM_ASSERT(obj->ID != 0 && g.ActiveId == obj->ID); + const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0; + const bool is_readonly = (Flags & ImGuiInputTextFlags_ReadOnly) != 0; + int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)ImStrlen(new_text); + + // We support partial insertion (with a mod in stb_textedit.h) + const int avail = BufSize - 1 - BufTextLen; + if (!is_resizable && new_text_len > avail) + new_text_len = avail; // 0 + if (new_text_len == 0) + return; // Grow internal buffer if needed - const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0; - const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)ImStrlen(new_text); - if (new_text_len + BufTextLen + 1 > obj->TextA.Size && (Flags & ImGuiInputTextFlags_ReadOnly) == 0) + if (new_text_len + BufTextLen + 1 > obj->TextA.Size && is_resizable && !is_readonly) { - if (!is_resizable) - return; - IM_ASSERT(Buf == obj->TextA.Data); int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1; obj->TextA.resize(new_buf_size + 1); From c72d0b2cbbbc02423e30d3095ca6ce6684ca7284 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 29 Sep 2025 14:57:03 +0200 Subject: [PATCH 50/50] Backends: Vulkan: SwapChainImageUsage assume VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT which is added automatically. (#8946, #8110, #8111, #8686) Merge bad3c14 which was accidentally only pushed to docking. No important side effect. --- backends/imgui_impl_vulkan.cpp | 2 +- examples/example_glfw_vulkan/main.cpp | 5 ++--- examples/example_sdl2_vulkan/main.cpp | 5 ++--- examples/example_sdl3_vulkan/main.cpp | 5 ++--- examples/example_win32_vulkan/main.cpp | 5 ++--- 5 files changed, 9 insertions(+), 13 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index baffb7e51..c62510829 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -1634,7 +1634,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V info.imageFormat = wd->SurfaceFormat.format; info.imageColorSpace = wd->SurfaceFormat.colorSpace; info.imageArrayLayers = 1; - info.imageUsage = (image_usage != 0) ? image_usage : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | image_usage; info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // Assume that graphics family == present family info.preTransform = (cap.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : cap.currentTransform; info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index d9cbfb787..ef307a0b3 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -54,7 +54,6 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static ImGui_ImplVulkanH_Window g_MainWindowData; static uint32_t g_MinImageCount = 2; static bool g_SwapChainRebuild = false; -static VkImageUsageFlags g_SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; static void glfw_error_callback(int error, const char* description) { @@ -240,7 +239,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface // Create SwapChain, RenderPass, Framebuffer, etc. IM_ASSERT(g_MinImageCount >= 2); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, g_SwapChainImageUsage); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0); } static void CleanupVulkan() @@ -457,7 +456,7 @@ int main(int, char**) if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height)) { ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, g_SwapChainImageUsage); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0); g_MainWindowData.FrameIndex = 0; g_SwapChainRebuild = false; } diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index fd845373d..7380edabd 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -49,7 +49,6 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static ImGui_ImplVulkanH_Window g_MainWindowData; static uint32_t g_MinImageCount = 2; static bool g_SwapChainRebuild = false; -static VkImageUsageFlags g_SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; static void check_vk_result(VkResult err) { @@ -231,7 +230,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface // Create SwapChain, RenderPass, Framebuffer, etc. IM_ASSERT(g_MinImageCount >= 2); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, g_SwapChainImageUsage); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0); } static void CleanupVulkan() @@ -477,7 +476,7 @@ int main(int, char**) if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height)) { ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, g_SwapChainImageUsage); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0); g_MainWindowData.FrameIndex = 0; g_SwapChainRebuild = false; } diff --git a/examples/example_sdl3_vulkan/main.cpp b/examples/example_sdl3_vulkan/main.cpp index 51de52db0..37e60de38 100644 --- a/examples/example_sdl3_vulkan/main.cpp +++ b/examples/example_sdl3_vulkan/main.cpp @@ -51,7 +51,6 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static ImGui_ImplVulkanH_Window g_MainWindowData; static uint32_t g_MinImageCount = 2; static bool g_SwapChainRebuild = false; -static VkImageUsageFlags g_SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; static void check_vk_result(VkResult err) { @@ -233,7 +232,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface // Create SwapChain, RenderPass, Framebuffer, etc. IM_ASSERT(g_MinImageCount >= 2); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, g_SwapChainImageUsage); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0); } static void CleanupVulkan() @@ -479,7 +478,7 @@ int main(int, char**) if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height)) { ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, g_SwapChainImageUsage); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0); g_MainWindowData.FrameIndex = 0; g_SwapChainRebuild = false; } diff --git a/examples/example_win32_vulkan/main.cpp b/examples/example_win32_vulkan/main.cpp index cdf4a247e..64a8f9f1d 100644 --- a/examples/example_win32_vulkan/main.cpp +++ b/examples/example_win32_vulkan/main.cpp @@ -47,7 +47,6 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static ImGui_ImplVulkanH_Window g_MainWindowData; static uint32_t g_MinImageCount = 2; static bool g_SwapChainRebuild = false; -static VkImageUsageFlags g_SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; static void check_vk_result(VkResult err) { @@ -229,7 +228,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface // Create SwapChain, RenderPass, Framebuffer, etc. IM_ASSERT(g_MinImageCount >= 2); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, g_SwapChainImageUsage); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0); } static void CleanupVulkan() @@ -550,7 +549,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height)) { ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, g_SwapChainImageUsage); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0); g_MainWindowData.FrameIndex = 0; g_SwapChainRebuild = false; }