Platform IME: added ImGuiPlatformImeData::WantTextInput, ViewportId. Backends: SDL3: honor WantTextInput. (#8584, #7492, #6341)

This commit is contained in:
ocornut
2025-04-22 11:21:02 +02:00
parent af987eb117
commit bf0f586b69
6 changed files with 27 additions and 13 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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;

12
imgui.h
View File

@@ -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)); }
};
//-----------------------------------------------------------------------------

View File

@@ -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<char> TempBuffer; // Temporary text buffer
char TempKeychordName[64];

View File

@@ -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;
}
}
}