From af987eb1176fb4c11a6f0a4f2550d9907d113df5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 20 Apr 2025 11:24:30 +0200 Subject: [PATCH 1/5] Backends: DX12: build fix for Clang. (#8582) --- backends/imgui_impl_dx12.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 202bac3b0..b6425cf52 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -535,7 +535,7 @@ bool ImGui_ImplDX12_CreateDeviceObjects() return false; } - PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignatureFn = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)::GetProcAddress(d3d12_dll, "D3D12SerializeRootSignature"); + PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignatureFn = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)(void*)::GetProcAddress(d3d12_dll, "D3D12SerializeRootSignature"); if (D3D12SerializeRootSignatureFn == nullptr) return false; From bf0f586b69ec9f082164c8fe39068952beadf304 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 22 Apr 2025 11:21:02 +0200 Subject: [PATCH 2/5] Platform IME: added ImGuiPlatformImeData::WantTextInput, ViewportId. Backends: SDL3: honor WantTextInput. (#8584, #7492, #6341) --- backends/imgui_impl_sdl3.cpp | 6 ++++-- docs/CHANGELOG.txt | 6 ++++++ imgui.cpp | 4 +++- imgui.h | 12 +++++++----- imgui_internal.h | 4 ++-- imgui_widgets.cpp | 8 +++++--- 6 files changed, 27 insertions(+), 13 deletions(-) diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index c2dd81085..e4e64721a 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-04-22: IME: honor ImGuiPlatformImeData->WantTextInput as an alternative way to call SDL_StartTextInput(), without IME being necessarily visible. // 2025-04-09: Don't attempt to call SDL_CaptureMouse() on drivers where we don't call SDL_GetGlobalMouseState(). (#8561) // 2025-03-30: Update for SDL3 api changes: Revert SDL_GetClipboardText() memory ownership change. (#8530, #7801) // 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set. @@ -150,7 +151,7 @@ static void ImGui_ImplSDL3_PlatformSetImeData(ImGuiContext*, ImGuiViewport* view ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); SDL_WindowID window_id = (SDL_WindowID)(intptr_t)viewport->PlatformHandle; SDL_Window* window = SDL_GetWindowFromID(window_id); - if ((data->WantVisible == false || bd->ImeWindow != window) && bd->ImeWindow != nullptr) + if ((!(data->WantVisible || data->WantTextInput) || bd->ImeWindow != window) && bd->ImeWindow != nullptr) { SDL_StopTextInput(bd->ImeWindow); bd->ImeWindow = nullptr; @@ -163,9 +164,10 @@ static void ImGui_ImplSDL3_PlatformSetImeData(ImGuiContext*, ImGuiViewport* view r.w = 1; r.h = (int)data->InputLineHeight; SDL_SetTextInputArea(window, &r, 0); - SDL_StartTextInput(window); bd->ImeWindow = window; } + if (data->WantVisible || data->WantTextInput) + SDL_StartTextInput(window); } // Not static to allow third-party code to use that if they want to (but undocumented) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 197fe9bb0..d78e8104f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -91,6 +91,10 @@ Other changes: would use a +1 offset instead of advancing to the next UTF-8 codepoint. (#8540) - Style, InputText: added ImGuiCol_InputTextCursor to configure color of the InputText cursor/caret. (#7031) +- Platform IME: added ImGuiPlatformImeData::ViewportId info (backported from Docking branch). +- Platform IME: added ImGuiPlatformImeData::WantTextInput which might set independently + of WantVisible. This is set in the same structure because activating text input generally + requires providing a window to the backend. (#8584, #6341) - Misc: added extra operators to ImVec4 in IMGUI_DEFINE_MATH_OPERATORS block. (#8510) [@gan74] - Backends: SDL2, SDL3, OSX: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set. (#8508) @@ -99,6 +103,8 @@ Other changes: the same white-list as SDL_GetGlobalMouseState(). (#8561) [@vs49688] - Backends: SDL3: Update for SDL3 api changes: revert SDL_GetClipboardText() memory ownership change. (#8530, #7801) [@Green-Sky] +- Backends: SDL3: honor ImGuiPlatformImeData->WantTextInput as an alternative + way to call SDL_StartTextInput(), without IME being necessarily visible. (#8584) - Backends: SDLGPU3: Made ImGui_ImplSDLGPU3_PrepareDrawData() reuse GPU Transfer Buffers which were unusually slow to recreate every frame. Much faster now. (#8534) [@ocornut, @TheMode] - Backends: Vulkan: Deep-copy ImGui_ImplVulkan_InitInfo::PipelineRenderingCreateInfo's diff --git a/imgui.cpp b/imgui.cpp index 90d4bbfa9..ad9132f23 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5362,7 +5362,7 @@ void ImGui::NewFrame() // Platform IME data: reset for the frame g.PlatformImeDataPrev = g.PlatformImeData; - g.PlatformImeData.WantVisible = false; + g.PlatformImeData.WantVisible = g.PlatformImeData.WantTextInput = false; // Mouse wheel scrolling, scale UpdateMouseWheel(); @@ -5654,9 +5654,11 @@ void ImGui::EndFrame() if (g.PlatformIO.Platform_SetImeDataFn != NULL && memcmp(ime_data, &g.PlatformImeDataPrev, sizeof(ImGuiPlatformImeData)) != 0) { IMGUI_DEBUG_LOG_IO("[io] Calling Platform_SetImeDataFn(): WantVisible: %d, InputPos (%.2f,%.2f)\n", ime_data->WantVisible, ime_data->InputPos.x, ime_data->InputPos.y); + IM_ASSERT(ime_data->ViewportId == IMGUI_VIEWPORT_DEFAULT_ID); // master branch ImGuiViewport* viewport = GetMainViewport(); g.PlatformIO.Platform_SetImeDataFn(&g, viewport, ime_data); } + g.WantTextInputNextFrame = ime_data->WantTextInput ? 1 : 0; // Hide implicit/fallback "Debug" window if it hasn't been used g.WithinFrameScopeWithImplicitWindow = false; diff --git a/imgui.h b/imgui.h index 989ae5ebc..af72083e3 100644 --- a/imgui.h +++ b/imgui.h @@ -3626,14 +3626,16 @@ struct ImGuiPlatformIO void* Renderer_RenderState; }; -// (Optional) Support for IME (Input Method Editor) via the platform_io.Platform_SetImeDataFn() function. +// (Optional) Support for IME (Input Method Editor) via the platform_io.Platform_SetImeDataFn() function. Handler is called during EndFrame(). struct ImGuiPlatformImeData { - bool WantVisible; // A widget wants the IME to be visible - ImVec2 InputPos; // Position of the input cursor - float InputLineHeight; // Line height + bool WantVisible; // A widget wants the IME to be visible. + bool WantTextInput; // A widget wants text input, not necessarily IME to be visible. This is automatically set to the upcoming value of io.WantTextInput. + ImVec2 InputPos; // Position of input cursor (for IME). + float InputLineHeight; // Line height (for IME). + ImGuiID ViewportId; // ID of platform window/viewport. - ImGuiPlatformImeData() { memset(this, 0, sizeof(*this)); } + ImGuiPlatformImeData() { memset(this, 0, sizeof(*this)); } }; //----------------------------------------------------------------------------- diff --git a/imgui_internal.h b/imgui_internal.h index 1d217553b..2c147e397 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2360,7 +2360,7 @@ struct ImGuiContext ImGuiTypingSelectState TypingSelectState; // State for GetTypingSelectRequest() // Platform support - ImGuiPlatformImeData PlatformImeData; // Data updated by current frame + ImGuiPlatformImeData PlatformImeData; // Data updated by current frame. Will be applied at end of the frame. For some backends, this is required to have WantVisible=true in order to receive text message. ImGuiPlatformImeData PlatformImeDataPrev; // Previous frame data. When changed we call the platform_io.Platform_SetImeDataFn() handler. // Settings @@ -2428,7 +2428,7 @@ struct ImGuiContext float FramerateSecPerFrameAccum; int WantCaptureMouseNextFrame; // Explicit capture override via SetNextFrameWantCaptureMouse()/SetNextFrameWantCaptureKeyboard(). Default to -1. int WantCaptureKeyboardNextFrame; // " - int WantTextInputNextFrame; + int WantTextInputNextFrame; // Copied in EndFrame() from g.PlatformImeData.WanttextInput. Needs to be set for some backends (SDL3) to emit character inputs. ImVector TempBuffer; // Temporary text buffer char TempKeychordName[64]; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 984bf5f06..c0a34db34 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5161,8 +5161,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Otherwise request text input ahead for next frame. if (g.ActiveId == id && clear_active_id) ClearActiveID(); - else if (g.ActiveId == id) - g.WantTextInputNextFrame = 1; // Render frame if (!is_multiline) @@ -5343,11 +5341,15 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_InputTextCursor), 1.0f); // FIXME-DPI: Cursor thickness (#7031) // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.) - if (!is_readonly) + // This is required for some backends (SDL3) to start emitting character/text inputs. + // As per #6341, make sure we don't set that on the deactivating frame. + if (!is_readonly && g.ActiveId == id) { g.PlatformImeData.WantVisible = true; + g.PlatformImeData.WantTextInput = true; g.PlatformImeData.InputPos = ImVec2(cursor_screen_pos.x - 1.0f, cursor_screen_pos.y - g.FontSize); g.PlatformImeData.InputLineHeight = g.FontSize; + g.PlatformImeData.ViewportId = window->Viewport->ID; } } } From 7c6ce12fa487c7684ac56be8e40c2a1c57c39602 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 22 Apr 2025 11:24:02 +0200 Subject: [PATCH 3/5] Platform IME: minor amend to bf0f586 (#8584) --- imgui_widgets.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c0a34db34..6a6d1e6ad 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5345,11 +5345,12 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // As per #6341, make sure we don't set that on the deactivating frame. if (!is_readonly && g.ActiveId == id) { - g.PlatformImeData.WantVisible = true; - g.PlatformImeData.WantTextInput = true; - g.PlatformImeData.InputPos = ImVec2(cursor_screen_pos.x - 1.0f, cursor_screen_pos.y - g.FontSize); - g.PlatformImeData.InputLineHeight = g.FontSize; - g.PlatformImeData.ViewportId = window->Viewport->ID; + ImGuiPlatformImeData* ime_data = &g.PlatformImeData; // (this is a public struct, passed to io.Platform_SetImeDataFn() handler) + ime_data->WantVisible = true; + ime_data->WantTextInput = true; + ime_data->InputPos = ImVec2(cursor_screen_pos.x - 1.0f, cursor_screen_pos.y - g.FontSize); + ime_data->InputLineHeight = g.FontSize; + ime_data->ViewportId = window->Viewport->ID; } } } From dcf0d8cab68bcf90156077211740836d95d683ad Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 22 Apr 2025 18:34:56 +0200 Subject: [PATCH 4/5] Tables: fixed TableHeader() eager vertical clipping of text. (#6236) --- 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 d78e8104f..a3892a06b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -76,6 +76,8 @@ Other changes: - The feature is unlikely to ever work properly when using a coarse clipper such as ImGuiListClipper. - TreeNode: fixed incorrect clipping of arrow/bullet when using ImGuiTreeNodeFlags_SpanAllColumns. +- Tables: fixed TableHeader() eager vertical clipping of text which may be noticeable + with FramePadding.y was too small. (#6236) - Tabs: fixes small issues with how "..." ellipsis moved depending on visibility of Close Button or Unsaved Document marker. (#8387) - Nav: fixed assertion when holding gamepad FaceLeft/West button to open diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 077d54b14..6a84dba36 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -3275,7 +3275,7 @@ void ImGui::TableHeader(const char* label) // Render clipped label. Clipping here ensure that in the majority of situations, all our header cells will // be merged into a single draw call. //window->DrawList->AddCircleFilled(ImVec2(ellipsis_max, label_pos.y), 40, IM_COL32_WHITE); - RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, label_pos.y + label_height + g.Style.FramePadding.y), ellipsis_max, label, label_end, &label_size); + RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, bb.Max.y), ellipsis_max, label, label_end, &label_size); const bool text_clipped = label_size.x > (ellipsis_max - label_pos.x); if (text_clipped && hovered && g.ActiveId == 0) From 6a42d6b339e0c86cdf0bce866bf390496155df69 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 23 Apr 2025 14:39:59 +0200 Subject: [PATCH 5/5] Added wp TextAligned() TextAlignedV(), TextAlignedExV() to internal API. (#7024) --- imgui.h | 2 +- imgui_internal.h | 7 ++++++- imgui_widgets.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index af72083e3..64049bed6 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.0 WIP" -#define IMGUI_VERSION_NUM 19193 +#define IMGUI_VERSION_NUM 19194 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index 2c147e397..cc5c488ba 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3443,8 +3443,13 @@ namespace ImGui IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, const ImRect& outer, const ImRect& inner, ImU32 col, float rounding); - // Widgets + // Widgets: Text IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0); + IMGUI_API void TextAligned(float align_x, const char* fmt, ...); // FIXME-WIP: Works but API is likely to be reworked. This is designed for 1 item on the line. (#7024) + IMGUI_API void TextAlignedV(float align_x, const char* fmt, va_list args); + IMGUI_API void TextAlignedExV(float align_x, float avail_x, const char* fmt, va_list args); + + // Widgets IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0); IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0); IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 6a6d1e6ad..6e19c22ed 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -339,6 +339,52 @@ void ImGui::TextWrappedV(const char* fmt, va_list args) PopTextWrapPos(); } +void ImGui::TextAligned(float align_x, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + TextAlignedV(align_x, fmt, args); + va_end(args); +} + +// align_x: 0.0f = left, 0.5f = center, 1.0f = right. +// FIXME-WIP: Works but API is likely to be reworked. This is designed for 1 item on the line. (#7024) +void ImGui::TextAlignedV(float align_x, const char* fmt, va_list args) +{ + TextAlignedExV(align_x, GetContentRegionAvail().x, fmt, args); +} + +void ImGui::TextAlignedExV(float align_x, float avail_x, const char* fmt, va_list args) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + + const char* text, *text_end; + ImFormatStringToTempBufferV(&text, &text_end, fmt, args); + const ImVec2 text_size = CalcTextSize(text, text_end); + + ImVec2 pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); + ImVec2 pos_max(pos.x + avail_x, window->ClipRect.Max.y); + ImVec2 size(ImMin(avail_x, text_size.x), text_size.y); + window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, pos.x + text_size.x); + window->DC.IdealMaxPos.x = ImMax(window->DC.IdealMaxPos.x, pos.x + text_size.x); + if (align_x > 0.0f && text_size.x < avail_x) + { + pos.x += ImTrunc((avail_x - text_size.x) * align_x); + window->DC.CursorPos = pos; + } + RenderTextEllipsis(window->DrawList, pos, pos_max, pos_max.x, text, text_end, &text_size); + + const ImVec2 backup_max_pos = window->DC.CursorMaxPos; + ItemSize(size); + ItemAdd(ImRect(pos, pos + size), 0); + window->DC.CursorMaxPos.x = backup_max_pos.x; // Cancel out extending content size because right-aligned text would otherwise mess it up. + + if (avail_x < text_size.x && IsItemHovered(ImGuiHoveredFlags_NoNavOverride | ImGuiHoveredFlags_AllowWhenDisabled | ImGuiHoveredFlags_ForTooltip)) + SetTooltip("%.*s", (int)(text_end - text), text); +} + void ImGui::LabelText(const char* label, const char* fmt, ...) { va_list args;