From dab63231d888f4a39c4d5729e14296c30cef2bc7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 Sep 2024 11:19:05 +0200 Subject: [PATCH 01/19] Misc: Made it accepted to call SetMouseCursor() with any out-of-bound value, as a way to allow hacking in custom cursors if desirable. --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 10 +++++++--- imgui_demo.cpp | 3 ++- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 2 +- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 903af40c3..b91d55530 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -70,6 +70,8 @@ Other changes: (e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build). This is the first step toward more refactorig. (#7925) [@alektron, @ocornut] - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow. +- Misc: Made it accepted to call SetMouseCursor() with any out-of-bound value, as a way to allow + hacking in custom cursors if desirable. - Fonts: fixed ellipsis "..." rendering width miscalculation bug introduced in 1.91.0. (#7976) [@DDeimos] - TextLinkOpenURL(): modified tooltip to display a verb "Open 'xxxx'". (#7885, #7660) - Backends: SDL2: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190) [@scribam] diff --git a/imgui.cpp b/imgui.cpp index 59a918e86..bdeda3fe7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3702,7 +3702,8 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl void ImGui::RenderMouseCursor(ImVec2 base_pos, float base_scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow) { ImGuiContext& g = *GImGui; - IM_ASSERT(mouse_cursor > ImGuiMouseCursor_None && mouse_cursor < ImGuiMouseCursor_COUNT); + if (mouse_cursor <= ImGuiMouseCursor_None || mouse_cursor >= ImGuiMouseCursor_COUNT) // We intentionally accept out of bound values. + mouse_cursor = ImGuiMouseCursor_Arrow; ImFontAtlas* font_atlas = g.DrawListSharedData.Font->ContainerAtlas; for (ImGuiViewportP* viewport : g.Viewports) { @@ -6198,7 +6199,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si ButtonBehavior(resize_rect, resize_grip_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus); //GetForegroundDrawList(window)->AddRect(resize_rect.Min, resize_rect.Max, IM_COL32(255, 255, 0, 255)); if (hovered || held) - g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE; + SetMouseCursor((resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE); if (held && g.IO.MouseDoubleClicked[0]) { @@ -6244,7 +6245,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si if (hovered && g.HoveredIdTimer <= WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER) hovered = false; if (hovered || held) - g.MouseCursor = (axis == ImGuiAxis_X) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS; + SetMouseCursor((axis == ImGuiAxis_X) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS); if (held && g.IO.MouseDoubleClicked[0]) { // Double-clicking bottom or right border auto-fit on this axis @@ -9296,6 +9297,9 @@ ImGuiMouseCursor ImGui::GetMouseCursor() return g.MouseCursor; } +// We intentionally accept values of ImGuiMouseCursor that are outside our bounds, in case users needs to hack-in a custom cursor value. +// Custom cursors may be handled by custom backends. If you are using a standard backend and want to hack in a custom cursor, you may +// handle it before the backend _NewFrame() call and temporarily set ImGuiConfigFlags_NoMouseCursorChange during the backend _NewFrame() call. void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type) { ImGuiContext& g = *GImGui; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 8c9745dfb..cc21099a8 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7490,7 +7490,8 @@ static void ShowDemoWindowInputs() IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT); ImGuiMouseCursor current = ImGui::GetMouseCursor(); - ImGui::Text("Current mouse cursor = %d: %s", current, mouse_cursors_names[current]); + const char* cursor_name = (current >= ImGuiMouseCursor_Arrow) && (current < ImGuiMouseCursor_COUNT) ? mouse_cursors_names[current] : "N/A"; + ImGui::Text("Current mouse cursor = %d: %s", current, cursor_name); ImGui::BeginDisabled(true); ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", &io.BackendFlags, ImGuiBackendFlags_HasMouseCursors); ImGui::EndDisabled(); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index f247ed6d3..9a6e06a2d 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -4409,7 +4409,7 @@ void ImGui::EndColumns() { ButtonBehavior(column_hit_rect, column_id, &hovered, &held); if (hovered || held) - g.MouseCursor = ImGuiMouseCursor_ResizeEW; + SetMouseCursor(ImGuiMouseCursor_ResizeEW); if (held && !(column->Flags & ImGuiOldColumnFlags_NoResize)) dragging_column = n; } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 14c5af3e4..3576d31fa 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4438,7 +4438,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags); if (hovered) - g.MouseCursor = ImGuiMouseCursor_TextInput; + SetMouseCursor(ImGuiMouseCursor_TextInput); // We are only allowed to access the state if we are already the active widget. ImGuiInputTextState* state = GetInputTextState(id); From 8040c02b32bb176cbdc4ea9b0526e7732f051037 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 Sep 2024 12:05:25 +0200 Subject: [PATCH 02/19] Viewports: fixed an issue where a window manually constrained to the main viewport while crossing over main viewport bounds isn't translated properly. (#7985) Amend 967073ba3 --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 9 +++++---- imgui_internal.h | 3 ++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7c02b3279..6c1343423 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -78,6 +78,8 @@ Other changes: Docking+Viewports Branch: +- Viewports: fixed an issue where a window manually constrained to the main viewport while crossing + over main viewport bounds isn't translated properly. (#7985) - Backends: SDL3: added support for viewport->ParentViewportId field to support parenting windows at OS level. (#7973) [@RT2code] diff --git a/imgui.cpp b/imgui.cpp index e8dc58f32..24653cbdf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -15224,7 +15224,7 @@ static bool ImGui::UpdateTryMergeWindowIntoHostViewports(ImGuiWindow* window) // Translate Dear ImGui windows when a Host Viewport has been moved // (This additionally keeps windows at the same place when ImGuiConfigFlags_ViewportsEnable is toggled!) -void ImGui::TranslateWindowsInViewport(ImGuiViewportP* viewport, const ImVec2& old_pos, const ImVec2& new_pos) +void ImGui::TranslateWindowsInViewport(ImGuiViewportP* viewport, const ImVec2& old_pos, const ImVec2& new_pos, const ImVec2& old_size, const ImVec2& new_size) { ImGuiContext& g = *GImGui; IM_ASSERT(viewport->Window == NULL && (viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows)); @@ -15238,7 +15238,7 @@ void ImGui::TranslateWindowsInViewport(ImGuiViewportP* viewport, const ImVec2& o ImRect test_still_fit_rect(old_pos, old_pos + viewport->Size); ImVec2 delta_pos = new_pos - old_pos; for (ImGuiWindow* window : g.Windows) // FIXME-OPT - if (translate_all_windows || (window->Viewport == viewport && test_still_fit_rect.Contains(window->Rect()))) + if (translate_all_windows || (window->Viewport == viewport && (old_size == new_size || test_still_fit_rect.Contains(window->Rect())))) TranslateWindow(window, delta_pos); } @@ -15415,7 +15415,7 @@ static void ImGui::UpdateViewportsNewFrame() // (This additionally keeps windows at the same place when ImGuiConfigFlags_ViewportsEnable is toggled!) const ImVec2 viewport_delta_pos = viewport->Pos - viewport->LastPos; if ((viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) && (viewport_delta_pos.x != 0.0f || viewport_delta_pos.y != 0.0f)) - TranslateWindowsInViewport(viewport, viewport->LastPos, viewport->Pos); + TranslateWindowsInViewport(viewport, viewport->LastPos, viewport->Pos, viewport->LastSize, viewport->Size); // Update DPI scale float new_dpi_scale; @@ -15525,6 +15525,7 @@ static void ImGui::UpdateViewportsEndFrame() { ImGuiViewportP* viewport = g.Viewports[i]; viewport->LastPos = viewport->Pos; + viewport->LastSize = viewport->Size; if (viewport->LastFrameActive < g.FrameCount || viewport->Size.x <= 0.0f || viewport->Size.y <= 0.0f) if (i > 0) // Always include main viewport in the list continue; @@ -15571,7 +15572,7 @@ ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const viewport->ID = id; viewport->Idx = g.Viewports.Size; viewport->Pos = viewport->LastPos = pos; - viewport->Size = size; + viewport->Size = viewport->LastSize = size; viewport->Flags = flags; UpdateViewportPlatformMonitor(viewport); g.Viewports.push_back(viewport); diff --git a/imgui_internal.h b/imgui_internal.h index 6ddaef372..b68210865 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1968,6 +1968,7 @@ struct ImGuiViewportP : public ImGuiViewport int LastFocusedStampCount; // Last stamp number from when a window hosted by this viewport was focused (by comparing this value between two viewport we have an implicit viewport z-order we use as fallback) ImGuiID LastNameHash; ImVec2 LastPos; + ImVec2 LastSize; float Alpha; // Window opacity (when dragging dockable windows/viewports we make them transparent) float LastAlpha; bool LastFocusedHadNavWindow;// Instead of maintaining a LastFocusedWindow (which may harder to correctly maintain), we merely store weither NavWindow != NULL last time the viewport was focused. @@ -3411,7 +3412,7 @@ namespace ImGui IMGUI_API void CallContextHooks(ImGuiContext* context, ImGuiContextHookType type); // Viewports - IMGUI_API void TranslateWindowsInViewport(ImGuiViewportP* viewport, const ImVec2& old_pos, const ImVec2& new_pos); + IMGUI_API void TranslateWindowsInViewport(ImGuiViewportP* viewport, const ImVec2& old_pos, const ImVec2& new_pos, const ImVec2& old_size, const ImVec2& new_size); IMGUI_API void ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale); IMGUI_API void DestroyPlatformWindow(ImGuiViewportP* viewport); IMGUI_API void SetWindowViewport(ImGuiWindow* window, ImGuiViewportP* viewport); From 510b6adc9bb0cfea012f513e358f3df962fe91b7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 Sep 2024 12:09:02 +0200 Subject: [PATCH 03/19] CI: disable month-long PVS Studio warning about expiring licence. --- .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 69df5cdf8..99b058c91 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 -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log + 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 plog-converter -a 'GA:1,2;OP:1' -d V1071 -t errorfile -w pvs-studio.log From 44a74509af96b7ff1a65eb84fda0c690ecc81fcf Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 Sep 2024 13:56:25 +0200 Subject: [PATCH 04/19] Backends: Win32: fixed direct calls to platform_io.Platform_SetWindowPos()/Platform_SetWindowSize() on windows created by application (typically main viewport). --- backends/imgui_impl_win32.cpp | 19 +++++++++++++++---- docs/CHANGELOG.txt | 2 ++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 816003509..1e9c58bbd 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -1158,11 +1158,20 @@ static ImVec2 ImGui_ImplWin32_GetWindowPos(ImGuiViewport* viewport) return ImVec2((float)pos.x, (float)pos.y); } +static void ImGui_ImplWin32_UpdateWin32StyleFromWindow(ImGuiViewport* viewport) +{ + ImGui_ImplWin32_ViewportData* vd = (ImGui_ImplWin32_ViewportData*)viewport->PlatformUserData; + vd->DwStyle = ::GetWindowLongW(vd->Hwnd, GWL_STYLE); + vd->DwExStyle = ::GetWindowLongW(vd->Hwnd, GWL_EXSTYLE); +} + static void ImGui_ImplWin32_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos) { ImGui_ImplWin32_ViewportData* vd = (ImGui_ImplWin32_ViewportData*)viewport->PlatformUserData; IM_ASSERT(vd->Hwnd != 0); RECT rect = { (LONG)pos.x, (LONG)pos.y, (LONG)pos.x, (LONG)pos.y }; + if (viewport->Flags & ImGuiViewportFlags_OwnedByApp) + ImGui_ImplWin32_UpdateWin32StyleFromWindow(viewport); // Not our window, poll style before using ::AdjustWindowRectEx(&rect, vd->DwStyle, FALSE, vd->DwExStyle); ::SetWindowPos(vd->Hwnd, nullptr, rect.left, rect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); } @@ -1181,6 +1190,8 @@ static void ImGui_ImplWin32_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) ImGui_ImplWin32_ViewportData* vd = (ImGui_ImplWin32_ViewportData*)viewport->PlatformUserData; IM_ASSERT(vd->Hwnd != 0); RECT rect = { 0, 0, (LONG)size.x, (LONG)size.y }; + if (viewport->Flags & ImGuiViewportFlags_OwnedByApp) + ImGui_ImplWin32_UpdateWin32StyleFromWindow(viewport); // Not our window, poll style before using ::AdjustWindowRectEx(&rect, vd->DwStyle, FALSE, vd->DwExStyle); // Client to Screen ::SetWindowPos(vd->Hwnd, nullptr, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); } @@ -1227,14 +1238,14 @@ static void ImGui_ImplWin32_SetWindowAlpha(ImGuiViewport* viewport, float alpha) IM_ASSERT(alpha >= 0.0f && alpha <= 1.0f); if (alpha < 1.0f) { - DWORD style = ::GetWindowLongW(vd->Hwnd, GWL_EXSTYLE) | WS_EX_LAYERED; - ::SetWindowLongW(vd->Hwnd, GWL_EXSTYLE, style); + DWORD ex_style = ::GetWindowLongW(vd->Hwnd, GWL_EXSTYLE) | WS_EX_LAYERED; + ::SetWindowLongW(vd->Hwnd, GWL_EXSTYLE, ex_style); ::SetLayeredWindowAttributes(vd->Hwnd, 0, (BYTE)(255 * alpha), LWA_ALPHA); } else { - DWORD style = ::GetWindowLongW(vd->Hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED; - ::SetWindowLongW(vd->Hwnd, GWL_EXSTYLE, style); + DWORD ex_style = ::GetWindowLongW(vd->Hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED; + ::SetWindowLongW(vd->Hwnd, GWL_EXSTYLE, ex_style); } } diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6c1343423..e0442dcdb 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -80,6 +80,8 @@ Docking+Viewports Branch: - Viewports: fixed an issue where a window manually constrained to the main viewport while crossing over main viewport bounds isn't translated properly. (#7985) +- Backends: Win32: fixed direct calls to platform_io.Platform_SetWindowPos()/Platform_SetWindowSize() + on windows created by application (typically main viewport). - Backends: SDL3: added support for viewport->ParentViewportId field to support parenting windows at OS level. (#7973) [@RT2code] From b53d91a4c40b69ec1d7e95e44863c8c921ed2f11 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 Sep 2024 14:15:43 +0200 Subject: [PATCH 05/19] InputText: optimization for large text: using memchr() instead of strchr() shaves 0.2 ms on 865k multi-line text case. Approximately 20%. (#7925) --- docs/CHANGELOG.txt | 2 +- imgui_widgets.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b91d55530..069b60388 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,7 +68,7 @@ Other changes: - InputText: internal refactoring to simplify and optimize the code. The ImWchar buffer has been removed. Simplifications allowed to implement new optimizations for handling very large text buffers (e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build). - This is the first step toward more refactorig. (#7925) [@alektron, @ocornut] + This is the first step toward more refactoring. (#7925) [@alektron, @ocornut] - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow. - Misc: Made it accepted to call SetMouseCursor() with any out-of-bound value, as a way to allow hacking in custom cursors if desirable. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3576d31fa..64156b40d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5095,6 +5095,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort) // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8. const char* text_begin = state->TextA.Data; + const char* text_end = text_begin + state->CurLenA; ImVec2 cursor_offset, select_start_offset; { @@ -5119,7 +5120,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter. searches_remaining += is_multiline ? 1 : 0; int line_count = 0; - for (const char* s = text_begin; (s = strchr(s, '\n')) != NULL; s++) // FIXME-OPT: memchr() would be faster? + for (const char* s = text_begin; (s = (const char*)memchr(s, '\n', (size_t)(text_end - s))) != NULL; s++) { line_count++; if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; if (--searches_remaining <= 0) break; } From aef07aea27472b9a678967404d06ea7ab6d71fb9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 Sep 2024 14:36:25 +0200 Subject: [PATCH 06/19] InputText: minor tidying up of selection search loop (no need to imply it runs in single line mode) --- imgui_widgets.cpp | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 64156b40d..26f617806 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5100,33 +5100,30 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ { // Find lines numbers straddling 'cursor' (slot 0) and 'select_start' (slot 1) positions. - const char* searches_input_ptr[2] = { NULL, NULL }; int searches_result_line_no[2] = { -1000, -1000 }; - int searches_remaining = 0; + const char* searches_input_ptr[2] = { NULL, NULL }; if (render_cursor) { searches_input_ptr[0] = text_begin + state->Stb->cursor; searches_result_line_no[0] = -1; - searches_remaining++; } if (render_selection) { searches_input_ptr[1] = text_begin + ImMin(state->Stb->select_start, state->Stb->select_end); searches_result_line_no[1] = -1; - searches_remaining++; } - // Iterate all lines to find our line numbers - // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter. - searches_remaining += is_multiline ? 1 : 0; - int line_count = 0; - for (const char* s = text_begin; (s = (const char*)memchr(s, '\n', (size_t)(text_end - s))) != NULL; s++) + // Count lines and find line number for cursor and selection ends + int line_count = 1; + if (is_multiline) { - line_count++; - if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; if (--searches_remaining <= 0) break; } - if (searches_result_line_no[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_no[1] = line_count; if (--searches_remaining <= 0) break; } + for (const char* s = text_begin; (s = (const char*)memchr(s, '\n', (size_t)(text_end - s))) != NULL; s++) + { + if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; } + if (searches_result_line_no[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_no[1] = line_count; } + line_count++; + } } - line_count++; if (searches_result_line_no[0] == -1) searches_result_line_no[0] = line_count; if (searches_result_line_no[1] == -1) From 7ac50bf77d08aaf569acc00feacd7eb44785f241 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 Sep 2024 14:42:58 +0200 Subject: [PATCH 07/19] InputText: more tidying up of selection search loop. --- imgui_widgets.cpp | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 26f617806..c5ee2734a 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5099,19 +5099,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ ImVec2 cursor_offset, select_start_offset; { - // Find lines numbers straddling 'cursor' (slot 0) and 'select_start' (slot 1) positions. - int searches_result_line_no[2] = { -1000, -1000 }; - const char* searches_input_ptr[2] = { NULL, NULL }; - if (render_cursor) - { - searches_input_ptr[0] = text_begin + state->Stb->cursor; - searches_result_line_no[0] = -1; - } - if (render_selection) - { - searches_input_ptr[1] = text_begin + ImMin(state->Stb->select_start, state->Stb->select_end); - searches_result_line_no[1] = -1; - } + // Find lines numbers straddling cursor and selection min position + int cursor_line_no = render_cursor ? -1 : -1000; + int selmin_line_no = render_selection ? -1 : -1000; + const char* cursor_ptr = render_cursor ? text_begin + state->Stb->cursor : NULL; + const char* selmin_ptr = render_selection ? text_begin + ImMin(state->Stb->select_start, state->Stb->select_end) : NULL; // Count lines and find line number for cursor and selection ends int line_count = 1; @@ -5119,23 +5111,23 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ { for (const char* s = text_begin; (s = (const char*)memchr(s, '\n', (size_t)(text_end - s))) != NULL; s++) { - if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; } - if (searches_result_line_no[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_no[1] = line_count; } + if (cursor_line_no == -1 && s >= cursor_ptr) { cursor_line_no = line_count; } + if (selmin_line_no == -1 && s >= selmin_ptr) { selmin_line_no = line_count; } line_count++; } } - if (searches_result_line_no[0] == -1) - searches_result_line_no[0] = line_count; - if (searches_result_line_no[1] == -1) - searches_result_line_no[1] = line_count; + if (cursor_line_no == -1) + cursor_line_no = line_count; + if (selmin_line_no == -1) + selmin_line_no = line_count; // Calculate 2d position by finding the beginning of the line and measuring distance - cursor_offset.x = InputTextCalcTextSize(&g, ImStrbol(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x; - cursor_offset.y = searches_result_line_no[0] * g.FontSize; - if (searches_result_line_no[1] >= 0) + cursor_offset.x = InputTextCalcTextSize(&g, ImStrbol(cursor_ptr, text_begin), cursor_ptr).x; + cursor_offset.y = cursor_line_no * g.FontSize; + if (selmin_line_no >= 0) { - select_start_offset.x = InputTextCalcTextSize(&g, ImStrbol(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x; - select_start_offset.y = searches_result_line_no[1] * g.FontSize; + select_start_offset.x = InputTextCalcTextSize(&g, ImStrbol(selmin_ptr, text_begin), selmin_ptr).x; + select_start_offset.y = selmin_line_no * g.FontSize; } // Store text height (note that we haven't calculated text width at all, see GitHub issues #383, #1224) From 4925695ae882f628d149ebcc8bd17471dd2c3efb Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 Sep 2024 14:52:42 +0200 Subject: [PATCH 08/19] InputText: optimize InputTextCalcTextLenAndLineCount() for inactive multiline path. (#7925) --- imgui_widgets.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c5ee2734a..4156ce8af 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3822,16 +3822,22 @@ bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, si return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data); } +// This is only used in the path where the multiline widget is inactivate. static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end) { int line_count = 0; const char* s = text_begin; - while (char c = *s++) // We are only matching for \n so we can ignore UTF-8 decoding - if (c == '\n') - line_count++; - s--; - if (s[0] != '\n' && s[0] != '\r') + while (true) + { + const char* s_eol = strchr(s, '\n'); line_count++; + if (s_eol == NULL) + { + s = s + strlen(s); + break; + } + s = s_eol + 1; + } *out_text_end = s; return line_count; } From 1ac162f2b083819663fe12b7217c40abdaf501cb Mon Sep 17 00:00:00 2001 From: Aaron C Gaudette Date: Mon, 16 Sep 2024 16:07:02 +0200 Subject: [PATCH 09/19] Backends: WGPU: add IMGUI_IMPL_WEBGPU_BACKEND_DAWN/IMGUI_IMPL_WEBGPU_BACKEND_WGPU to support more targets. (#7977, #7969, #6602, #6188, #7523) --- backends/imgui_impl_wgpu.cpp | 29 +++++++++++++++++++++++ backends/imgui_impl_wgpu.h | 7 ++++++ docs/CHANGELOG.txt | 2 ++ examples/example_glfw_wgpu/CMakeLists.txt | 5 ++++ 4 files changed, 43 insertions(+) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index bf741e1a4..503ac8efd 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -16,6 +16,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-09-16: Added support for optional IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU define to handle ever-changing native implementations. (#7977) // 2024-01-22: Added configurable PipelineMultisampleState struct. (#7240) // 2024-01-22: (Breaking) ImGui_ImplWGPU_Init() now takes a ImGui_ImplWGPU_InitInfo structure instead of variety of parameters, allowing for easier further changes. // 2024-01-22: Fixed pipeline layout leak. (#7245) @@ -35,6 +36,18 @@ // 2021-02-18: Change blending equation to preserve alpha in output buffer. // 2021-01-28: Initial version. +// 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 + #include "imgui.h" #ifndef IMGUI_DISABLE #include "imgui_impl_wgpu.h" @@ -245,7 +258,11 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData(); WGPUShaderModuleWGSLDescriptor wgsl_desc = {}; +#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN + wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL; +#else wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; +#endif wgsl_desc.code = wgsl_source; WGPUShaderModuleDescriptor desc = {}; @@ -660,7 +677,11 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() // Create depth-stencil State WGPUDepthStencilState depth_stencil_state = {}; depth_stencil_state.format = bd->depthStencilFormat; +#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN + depth_stencil_state.depthWriteEnabled = WGPUOptionalBool_False; +#else depth_stencil_state.depthWriteEnabled = false; +#endif depth_stencil_state.depthCompare = WGPUCompareFunction_Always; depth_stencil_state.stencilFront.compare = WGPUCompareFunction_Always; depth_stencil_state.stencilFront.failOp = WGPUStencilOperation_Keep; @@ -730,7 +751,15 @@ 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(__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"; +#else io.BackendRendererName = "imgui_impl_webgpu"; +#endif io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. bd->initInfo = *init_info; diff --git a/backends/imgui_impl_wgpu.h b/backends/imgui_impl_wgpu.h index 87d9580bf..e6835dee9 100644 --- a/backends/imgui_impl_wgpu.h +++ b/backends/imgui_impl_wgpu.h @@ -2,6 +2,13 @@ // 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.) +// 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. +// 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. +//#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN +//#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU + // Implemented features: // [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 069b60388..95df895c4 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -77,6 +77,8 @@ Other changes: - Backends: SDL2: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190) [@scribam] - Backends: GLFW+Emscripten: use OSX behaviors automatically when using contrib glfw port. (#7965, #7915) [@ypujante] +- Backends: WebGPU: Added support for optional IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU + defines to handle ever-changing native implementations. (#7977, #7969, #6602, #6188, #7523) [@acgaudette] ----------------------------------------------------------------------- VERSION 1.91.1 (Released 2024-09-04) diff --git a/examples/example_glfw_wgpu/CMakeLists.txt b/examples/example_glfw_wgpu/CMakeLists.txt index 6be95af44..8e164e488 100644 --- a/examples/example_glfw_wgpu/CMakeLists.txt +++ b/examples/example_glfw_wgpu/CMakeLists.txt @@ -79,6 +79,11 @@ add_executable(example_glfw_wgpu ${IMGUI_DIR}/imgui_tables.cpp ${IMGUI_DIR}/imgui_widgets.cpp ) +IF(NOT EMSCRIPTEN) + target_compile_definitions(example_glfw_wgpu PUBLIC + "IMGUI_IMPL_WEBGPU_BACKEND_DAWN" + ) +endif() target_include_directories(example_glfw_wgpu PUBLIC ${IMGUI_DIR} ${IMGUI_DIR}/backends From 8ba7efb738d6ee992ef81b451162591e43badbcf Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 Sep 2024 17:22:31 +0200 Subject: [PATCH 10/19] Backends: Win32: fixed an issue where a viewport destroyed while clicking would hog mouse tracking and temporary lead to incorrect update of HoveredWindow. (#7971) --- backends/imgui_impl_win32.cpp | 13 ++++++++++++- docs/CHANGELOG.txt | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 1e9c58bbd..825e4a488 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -23,6 +23,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2024-09-16: [Docking] Inputs: fixed an issue where a viewport destroyed while clicking would hog mouse tracking and temporary lead to incorrect update of HoveredWindow. (#7971) // 2024-07-08: Inputs: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN. (#7768) // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys. // 2023-09-25: Inputs: Synthesize key-down event on key-up for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit it (same behavior as GLFW/SDL). @@ -114,7 +115,7 @@ struct ImGui_ImplWin32_Data { HWND hWnd; HWND MouseHwnd; - int MouseTrackedArea; // 0: not tracked, 1: client are, 2: non-client area + int MouseTrackedArea; // 0: not tracked, 1: client area, 2: non-client area int MouseButtonsDown; INT64 Time; INT64 TicksPerSecond; @@ -705,6 +706,16 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA } return 0; } + case WM_DESTROY: + if (bd->MouseHwnd == hwnd && bd->MouseTrackedArea != 0) + { + TRACKMOUSEEVENT tme_cancel = { sizeof(tme_cancel), TME_CANCEL, hwnd, 0 }; + ::TrackMouseEvent(&tme_cancel); + bd->MouseHwnd = nullptr; + bd->MouseTrackedArea = 0; + io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); + } + return 0; case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e0442dcdb..dd9202fbb 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -82,6 +82,8 @@ Docking+Viewports Branch: over main viewport bounds isn't translated properly. (#7985) - Backends: Win32: fixed direct calls to platform_io.Platform_SetWindowPos()/Platform_SetWindowSize() on windows created by application (typically main viewport). +- Backends: Win32: fixed an issue where a viewport destroyed while clicking would hog + mouse tracking and temporary lead to incorrect update of HoveredWindow. (#7971) - Backends: SDL3: added support for viewport->ParentViewportId field to support parenting windows at OS level. (#7973) [@RT2code] From 08b1496b7e566eecf1b870bce1eed57522c6593c Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 Sep 2024 17:22:31 +0200 Subject: [PATCH 11/19] Backends: Win32: fixed an issue where a viewport destroyed while clicking would hog mouse tracking and temporary lead to incorrect update of HoveredWindow. (#7971) # Conflicts: # backends/imgui_impl_win32.cpp # docs/CHANGELOG.txt --- backends/imgui_impl_win32.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 0e48d8636..758e70d01 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -107,7 +107,7 @@ struct ImGui_ImplWin32_Data { HWND hWnd; HWND MouseHwnd; - int MouseTrackedArea; // 0: not tracked, 1: client are, 2: non-client area + int MouseTrackedArea; // 0: not tracked, 1: client area, 2: non-client area int MouseButtonsDown; INT64 Time; INT64 TicksPerSecond; @@ -629,6 +629,16 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA } return 0; } + case WM_DESTROY: + if (bd->MouseHwnd == hwnd && bd->MouseTrackedArea != 0) + { + TRACKMOUSEEVENT tme_cancel = { sizeof(tme_cancel), TME_CANCEL, hwnd, 0 }; + ::TrackMouseEvent(&tme_cancel); + bd->MouseHwnd = nullptr; + bd->MouseTrackedArea = 0; + io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); + } + return 0; case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: From 6ce26ef11d52d57845d0f06d84dcbfbc0f8d006b Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 17 Sep 2024 12:25:21 +0200 Subject: [PATCH 12/19] AddFont: added assert to better detect uninitialized struct. (#7993) --- imgui_draw.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index a681059bb..79270f1a1 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2499,13 +2499,14 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); IM_ASSERT(font_cfg->FontData != NULL && font_cfg->FontDataSize > 0); - IM_ASSERT(font_cfg->SizePixels > 0.0f); + IM_ASSERT(font_cfg->SizePixels > 0.0f && "Is ImFontConfig struct correctly initialized?"); + IM_ASSERT(font_cfg->OversampleH > 0 && font_cfg->OversampleV > 0 && "Is ImFontConfig struct correctly initialized?"); // Create new font if (!font_cfg->MergeMode) Fonts.push_back(IM_NEW(ImFont)); else - IM_ASSERT(!Fonts.empty() && "Cannot use MergeMode for the first font"); // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font. + IM_ASSERT(Fonts.Size > 0 && "Cannot use MergeMode for the first font"); // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font. ConfigData.push_back(*font_cfg); ImFontConfig& new_font_cfg = ConfigData.back(); From 1ab1e3c65639e361bde50996599baa288c3f3c2a Mon Sep 17 00:00:00 2001 From: RT2 Date: Sun, 15 Sep 2024 19:57:37 +0200 Subject: [PATCH 13/19] Backends: SDL3: rework implementation of ImGuiViewportFlags_NoTaskBarIcon. (#7989) --- backends/imgui_impl_sdl3.cpp | 14 ++++++-------- docs/CHANGELOG.txt | 1 + 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 5e05f0b03..5135b75a7 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -951,10 +951,7 @@ static void ImGui_ImplSDL3_CreateWindow(ImGuiViewport* viewport) sdl_flags |= SDL_GetWindowFlags(bd->Window); sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? SDL_WINDOW_BORDERLESS : 0; sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? 0 : SDL_WINDOW_RESIZABLE; -#if !defined(_WIN32) - // See SDL hack in ImGui_ImplSDL3_ShowWindow(). sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoTaskBarIcon) ? SDL_WINDOW_UTILITY : 0; -#endif sdl_flags |= (viewport->Flags & ImGuiViewportFlags_TopMost) ? SDL_WINDOW_ALWAYS_ON_TOP : 0; vd->Window = SDL_CreateWindow("No Title Yet", (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags); SDL_SetWindowParent(vd->Window, vd->ParentWindow); @@ -992,13 +989,14 @@ static void ImGui_ImplSDL3_ShowWindow(ImGuiViewport* viewport) #if defined(_WIN32) HWND hwnd = (HWND)viewport->PlatformHandleRaw; - // SDL hack: Hide icon from task bar - // Note: SDL 3.0.0+ has a SDL_WINDOW_UTILITY flag which is supported under Windows but the way it create the window breaks our seamless transition. - if (viewport->Flags & ImGuiViewportFlags_NoTaskBarIcon) + // SDL hack: Show icon in task bar (#7989) + // Note: SDL_WINDOW_UTILITY can be used to control task bar visibility, but on Windows, it does not affect child windows. + if (!(viewport->Flags & ImGuiViewportFlags_NoTaskBarIcon)) { LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE); - ex_style &= ~WS_EX_APPWINDOW; - ex_style |= WS_EX_TOOLWINDOW; + ex_style |= WS_EX_APPWINDOW; + ex_style &= ~WS_EX_TOOLWINDOW; + ::ShowWindow(hwnd, SW_HIDE); ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style); } #endif diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index dd9202fbb..5903423a1 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -86,6 +86,7 @@ Docking+Viewports Branch: mouse tracking and temporary lead to incorrect update of HoveredWindow. (#7971) - Backends: SDL3: added support for viewport->ParentViewportId field to support parenting windows at OS level. (#7973) [@RT2code] +- Backends: SDL3: rework implementation of _NoTaskBarIcon. (#7989) [@RT2code] ----------------------------------------------------------------------- VERSION 1.91.1 (Released 2024-09-04) From 11fba027e506beca7a2a726b73577b5e8938d64d Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 17 Sep 2024 16:35:55 +0200 Subject: [PATCH 14/19] Tables: using table->InnerClipRect more consistently. Fixes an assertion with tables with borders when clipped by parent. (#6765, #3752, #7428) --- docs/CHANGELOG.txt | 1 + imgui_tables.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 95df895c4..8d640533c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -70,6 +70,7 @@ Other changes: (e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build). This is the first step toward more refactoring. (#7925) [@alektron, @ocornut] - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow. +- Tables: fixes an assertion with tables with borders when clipped by parent. (#6765, #3752, #7428) - Misc: Made it accepted to call SetMouseCursor() with any out-of-bound value, as a way to allow hacking in custom cursors if desirable. - Fonts: fixed ellipsis "..." rendering width miscalculation bug introduced in 1.91.0. (#7976) [@DDeimos] diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 9a6e06a2d..e82e8777f 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1261,7 +1261,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) if (table->Flags & ImGuiTableFlags_NoClip) table->DrawSplitter->SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP); else - inner_window->DrawList->PushClipRect(inner_window->InnerClipRect.Min, inner_window->InnerClipRect.Max, false); + inner_window->DrawList->PushClipRect(inner_window->InnerClipRect.Min, inner_window->InnerClipRect.Max, false); // FIXME: use table->InnerClipRect? } // Process hit-testing on resizing borders. Actual size change will be applied in EndTable() @@ -2011,7 +2011,7 @@ void ImGui::TableEndRow(ImGuiTable* table) { for (int column_n = 0; column_n < table->ColumnsCount; column_n++) table->Columns[column_n].NavLayerCurrent = ImGuiNavLayer_Main; - const float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y); + const float y0 = ImMax(table->RowPosY2 + 1, table->InnerClipRect.Min.y); table_instance->LastFrozenHeight = y0 - table->OuterRect.Min.y; if (unfreeze_rows_actual) @@ -2020,8 +2020,8 @@ void ImGui::TableEndRow(ImGuiTable* table) table->IsUnfrozenRows = true; // BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect - table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y); - table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y; + table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, table->InnerClipRect.Max.y); + table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = table->InnerClipRect.Max.y; table->Bg2DrawChannelCurrent = table->Bg2DrawChannelUnfrozen; IM_ASSERT(table->Bg2ClipRectForDrawCmd.Min.y <= table->Bg2ClipRectForDrawCmd.Max.y); From 71714eab5367d2fa119e36be30148278e0d5974f Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 17 Sep 2024 18:09:02 +0200 Subject: [PATCH 15/19] Tables: fixed assertion related to inconsistent outer clipping when sizes are not rounded. (#7957) --- docs/CHANGELOG.txt | 3 ++- imgui.h | 2 +- imgui_tables.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8d640533c..566e42608 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -70,7 +70,8 @@ Other changes: (e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build). This is the first step toward more refactoring. (#7925) [@alektron, @ocornut] - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow. -- Tables: fixes an assertion with tables with borders when clipped by parent. (#6765, #3752, #7428) +- Tables: fixed assertion related to inconsistent outer clipping when sizes are not rounded. (#7957) [@eclbtownsend] +- Tables: fixed assertion with tables with borders when clipped by parent. (#6765, #3752, #7428) - Misc: Made it accepted to call SetMouseCursor() with any out-of-bound value, as a way to allow hacking in custom cursors if desirable. - Fonts: fixed ellipsis "..." rendering width miscalculation bug introduced in 1.91.0. (#7976) [@DDeimos] diff --git a/imgui.h b/imgui.h index 095c25002..854d210e1 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.2 WIP" -#define IMGUI_VERSION_NUM 19114 +#define IMGUI_VERSION_NUM 19115 #define IMGUI_HAS_TABLE /* diff --git a/imgui_tables.cpp b/imgui_tables.cpp index e82e8777f..d9844586b 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -328,7 +328,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG // - always performing the GetOrAddByKey() O(log N) query in g.Tables.Map[]. const bool use_child_window = (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0; const ImVec2 avail_size = GetContentRegionAvail(); - const ImVec2 actual_outer_size = CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f); + const ImVec2 actual_outer_size = ImTrunc(CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f)); const ImRect outer_rect(outer_window->DC.CursorPos, outer_window->DC.CursorPos + actual_outer_size); const bool outer_window_is_measuring_size = (outer_window->AutoFitFramesX > 0) || (outer_window->AutoFitFramesY > 0); // Doesn't apply to AlwaysAutoResize windows! if (use_child_window && IsClippedEx(outer_rect, 0) && !outer_window_is_measuring_size) From dad9f45e3ed9968b7873f3ed4a41ac0339befafa Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 17 Sep 2024 18:27:31 +0200 Subject: [PATCH 16/19] Windows: fixed an issue where double-click to collapse could be triggered even while another item is active. (#7841, #7369) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 566e42608..9e31a1011 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -72,6 +72,8 @@ Other changes: - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow. - Tables: fixed assertion related to inconsistent outer clipping when sizes are not rounded. (#7957) [@eclbtownsend] - Tables: fixed assertion with tables with borders when clipped by parent. (#6765, #3752, #7428) +- Windows: fixed an issue where double-click to collapse could be triggered even while another + item is active, if the item didn't use the left mouse button. (#7841) - Misc: Made it accepted to call SetMouseCursor() with any out-of-bound value, as a way to allow hacking in custom cursors if desirable. - Fonts: fixed ellipsis "..." rendering width miscalculation bug introduced in 1.91.0. (#7976) [@DDeimos] diff --git a/imgui.cpp b/imgui.cpp index bdeda3fe7..369e582d7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6948,9 +6948,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse)) { - // We don't use a regular button+id to test for double-click on title bar (mostly due to legacy reason, could be fixed), so verify that we don't have items over the title bar. + // We don't use a regular button+id to test for double-click on title bar (mostly due to legacy reason, could be fixed), + // so verify that we don't have items over the title bar. ImRect title_bar_rect = window->TitleBarRect(); - if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max)) + if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && g.ActiveId == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max)) if (g.IO.MouseClickedCount[0] == 2 && GetKeyOwner(ImGuiKey_MouseLeft) == ImGuiKeyOwner_NoOwner) window->WantCollapseToggle = true; if (window->WantCollapseToggle) From 6aade6912a107204d15ebe7171434ee21a91c629 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 17 Sep 2024 18:52:12 +0200 Subject: [PATCH 17/19] Inputs: SetNextItemShortcut() with ImGuiInputFlags_Tooltip doesn't show tooltip when item is active. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9e31a1011..475daa596 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -65,6 +65,7 @@ Other changes: - Nav: pressing any keyboard key while holding Alt disable toggling nav layer on Alt release. (#4439) - MultiSelect+Tables: fixed an issue where box-select would skip items while drag-scrolling in a table with outer borders. (#7970, #7821). +- Inputs: SetNextItemShortcut() with ImGuiInputFlags_Tooltip doesn't show tooltip when item is active. - InputText: internal refactoring to simplify and optimize the code. The ImWchar buffer has been removed. Simplifications allowed to implement new optimizations for handling very large text buffers (e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build). diff --git a/imgui.cpp b/imgui.cpp index 369e582d7..9dddb55c2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4343,7 +4343,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag // Display shortcut (only works with mouse) // (ImGuiItemStatusFlags_HasShortcut in LastItemData denotes we want a tooltip) - if (id == g.LastItemData.ID && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasShortcut)) + if (id == g.LastItemData.ID && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasShortcut) && g.ActiveId != id) if (IsItemHovered(ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_DelayNormal)) SetTooltip("%s", GetKeyChordName(g.LastItemData.Shortcut)); } From e648dbb59d24c29a2e2ac964777822e96befd808 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 17 Sep 2024 20:34:54 +0200 Subject: [PATCH 18/19] Tables: fixed auto-width columns when using synced-instances of same table. (#7218) Amend d3c3514a5 --- docs/CHANGELOG.txt | 2 ++ imgui_tables.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 475daa596..de022c1ae 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -71,6 +71,8 @@ Other changes: (e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build). This is the first step toward more refactoring. (#7925) [@alektron, @ocornut] - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow. +- Tables: fixed auto-width columns when using synced-instances of same table. The previous fix + done in v1.90.5 was incomplete. (#7218) - Tables: fixed assertion related to inconsistent outer clipping when sizes are not rounded. (#7957) [@eclbtownsend] - Tables: fixed assertion with tables with borders when clipped by parent. (#6765, #3752, #7428) - Windows: fixed an issue where double-click to collapse could be triggered even while another diff --git a/imgui_tables.cpp b/imgui_tables.cpp index d9844586b..c3fb531ef 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -866,7 +866,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) // Calculate ideal/auto column width (that's the width required for all contents to be visible without clipping) // Combine width from regular rows + width from headers unless requested not to. - if (!column->IsPreserveWidthAuto) + if (!column->IsPreserveWidthAuto && table->InstanceCurrent == 0) column->WidthAuto = TableGetColumnWidthAuto(table, column); // Non-resizable columns keep their requested width (apply user value regardless of IsPreserveWidthAuto) From f7ba6453980824aa4a7d096841576285efa7f6ec Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 17 Sep 2024 21:07:15 +0200 Subject: [PATCH 19/19] InputText: fixed not filling callback's SelectionEnd. (#7925) Broken by abd07f6 --- imgui_widgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 4156ce8af..27610228d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4977,7 +4977,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ 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 = state->Stb->select_end; + const int utf8_selection_end = callback_data.SelectionEnd = state->Stb->select_end; // Call user code callback(&callback_data);