diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 3ddd4a7f7..0a8647794 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-11-05: Fixed an issue with missing characters events when an already active text field changes viewports. (#9054) // 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. @@ -112,6 +113,8 @@ struct ImGui_ImplSDL3_Data // IME handling SDL_Window* ImeWindow; + ImGuiPlatformImeData ImeData; + bool ImeDirty; // Mouse handling Uint32 MouseWindowID; @@ -139,6 +142,9 @@ static ImGui_ImplSDL3_Data* ImGui_ImplSDL3_GetBackendData() return ImGui::GetCurrentContext() ? (ImGui_ImplSDL3_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr; } +// Forward Declarations +static void ImGui_ImplSDL3_UpdateIme(); + // Functions static const char* ImGui_ImplSDL3_GetClipboardText(ImGuiContext*) { @@ -154,16 +160,38 @@ static void ImGui_ImplSDL3_SetClipboardText(ImGuiContext*, const char* text) SDL_SetClipboardText(text); } -static void ImGui_ImplSDL3_PlatformSetImeData(ImGuiContext*, ImGuiViewport* viewport, ImGuiPlatformImeData* data) +static ImGuiViewport* ImGui_ImplSDL3_GetViewportForWindowID(SDL_WindowID window_id) { ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); - SDL_WindowID window_id = (SDL_WindowID)(intptr_t)viewport->PlatformHandle; - SDL_Window* window = SDL_GetWindowFromID(window_id); + return (window_id == bd->WindowID) ? ImGui::GetMainViewport() : nullptr; +} + +static void ImGui_ImplSDL3_PlatformSetImeData(ImGuiContext*, ImGuiViewport*, ImGuiPlatformImeData* data) +{ + ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); + bd->ImeData = *data; + bd->ImeDirty = true; + ImGui_ImplSDL3_UpdateIme(); +} + +// We discard viewport passed via ImGuiPlatformImeData and always call SDL_StartTextInput() on SDL_GetKeyboardFocus(). +static void ImGui_ImplSDL3_UpdateIme() +{ + ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); + ImGuiPlatformImeData* data = &bd->ImeData; + SDL_Window* window = SDL_GetKeyboardFocus(); + + // Stop previous input if ((!(data->WantVisible || data->WantTextInput) || bd->ImeWindow != window) && bd->ImeWindow != nullptr) { SDL_StopTextInput(bd->ImeWindow); bd->ImeWindow = nullptr; } + if ((!bd->ImeDirty && bd->ImeWindow == window) || (window == NULL)) + return; + + // Start/update current input + bd->ImeDirty = false; if (data->WantVisible) { SDL_Rect r; @@ -340,13 +368,6 @@ static void ImGui_ImplSDL3_UpdateKeyModifiers(SDL_Keymod sdl_key_mods) io.AddKeyEvent(ImGuiMod_Super, (sdl_key_mods & SDL_KMOD_GUI) != 0); } - -static ImGuiViewport* ImGui_ImplSDL3_GetViewportForWindowID(SDL_WindowID window_id) -{ - ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); - return (window_id == bd->WindowID) ? ImGui::GetMainViewport() : nullptr; -} - // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. @@ -835,6 +856,7 @@ void ImGui_ImplSDL3_NewFrame() ImGui_ImplSDL3_UpdateMouseData(); ImGui_ImplSDL3_UpdateMouseCursor(); + ImGui_ImplSDL3_UpdateIme(); // Update game controllers (if enabled and available) ImGui_ImplSDL3_UpdateGamepads(); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 4450c9baf..aa9feda65 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -86,6 +86,8 @@ Other Changes: 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] + - SDL3: fixed an issue with missing characters events when an already active text + field changes viewports. (#9054) - Vulkan: added IMGUI_IMPL_VULKAN_VOLK_FILENAME to configure path to Volk (default to "volk.h"). (#9008, #7722, #6582, #4854) [@mwlasiuk] - WebGPU: added various internal/optional helpers to wrap some of the diff --git a/imgui.cpp b/imgui.cpp index 46a6fd79d..05ae2f026 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5870,9 +5870,9 @@ void ImGui::EndFrame() ImGuiPlatformImeData* ime_data = &g.PlatformImeData; 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(); + IMGUI_DEBUG_LOG_IO("[io] Calling Platform_SetImeDataFn(): WantVisible: %d, InputPos (%.2f,%.2f) for Viewport 0x%08X\n", ime_data->WantVisible, ime_data->InputPos.x, ime_data->InputPos.y, viewport->ID); g.PlatformIO.Platform_SetImeDataFn(&g, viewport, ime_data); } g.WantTextInputNextFrame = ime_data->WantTextInput ? 1 : 0;