Handling IME for International Text Input in Dear ImGui: A Complete Guide

Dear ImGui supports Input Method Editor (IME) integration through platform-specific backends that forward OS composition events to the input buffer, enabling CJK and complex script input.

Dear ImGui provides built-in infrastructure for handling IME for international text input, allowing users to type Chinese, Japanese, Korean, and other complex scripts. The implementation spans both the core library in ocornut/imgui and platform-specific backend files that translate native OS events into ImGui input. Understanding this architecture is essential for applications that require robust multilingual text entry beyond basic ASCII input.

Core IME Architecture in ImGui

The IME system centers on the ImGuiPlatformImeData structure stored within ImGuiIO, which acts as the communication bridge between ImGui's input handling and the operating system's text composition services.

ImGuiIO and PlatformImeData

In imgui.cpp at line 5810, the ImGuiIO structure contains an ImGuiPlatformImeData field that tracks the current cursor position and the WantTextInput flag. This flag signals to platform backends when to activate or deactivate the IME composition window. The PlatformImeData structure also includes a Ready boolean and Pos vector that determines where the OS should display the candidate window relative to the active text widget.

Per-Frame IME State Management

At the beginning of every frame, ImGui clears the IME data to ensure fresh state for the current input context (line 6102 in imgui.cpp). After the UI construction phase completes, ImGui calls the platform-specific IME update function between lines 6102-6105 to notify the OS of cursor movements. This two-phase approach ensures that the composition window position updates only after the final widget layout is determined.

When IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS is not defined, ImGui automatically installs a default Win32 IME handler at lines 16349-16385 in imgui.cpp that forwards composition results to the input buffer using ImmSetCompositionWindow.

Platform Backend Implementations

Platform backends handle the translation of native IME events into ImGui's character input system. Each major platform implements specific message handlers or event callbacks to capture composition strings.

Win32 Backend (WM_IME_COMPOSITION)

The Win32 backend in backends/imgui_impl_win32.cpp processes WM_IME_COMPOSITION messages at line 800 to capture ongoing text composition. When the GCS_RESULTSTR flag indicates a completed composition, the backend forwards the final string to ImGui via io.AddInputCharacterUTF16. For legacy MBCS applications, the backend also handles WM_IME_CHAR at line 808, converting ANSI characters to Unicode before injection.

SDL2 and SDL3 Backends

The SDL2 backend enables native IME UI support through the SDL_HINT_IME_SHOW_UI hint, which example projects set before window creation in examples/example_sdl2_opengl3/main.cpp. At lines 117-124 in backends/imgui_impl_sdl2.cpp, the backend monitors ImGuiPlatformImeData::WantTextInput to call SDL_StartTextInput or SDL_StopTextInput, opening and closing the IME composition window on mobile and desktop platforms.

The SDL3 backend follows a similar pattern but adds guards against double-calling SDL_StartTextInput at lines 117-124 in backends/imgui_impl_sdl3.cpp, while also respecting WantTextInput for on-screen keyboard activation.

Enabling IME in Your Application

To activate IME support in your Dear ImGui application, you must configure both the core library flags and the platform backend state.

First, ensure your platform backend is compiled into the project (e.g., #include "backends/imgui_impl_win32.cpp"). Do not define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS unless implementing custom IME handling.

Next, set the configuration flags in your initialization code:

ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;  // Required for IME cursor
io.ConfigFlags |= ImGuiConfigFlags_EnableIme;          // Explicitly enable IME (since v1.91)

After laying out UI elements that require text input, update the ImGuiPlatformImeData structure to position the composition window:

ImGuiPlatformImeData& ime = io.PlatformImeData;
ime.Ready = true;
ime.Pos = ImGui::GetCursorScreenPos();  // Position for IME candidate window
ime.WantTextInput = true;               // Request text input activation

ImGui automatically calls the backend's update function during ImGui::Render(), which notifies the OS of the cursor location.

Code Examples

The following examples demonstrate complete IME integration for Win32 and SDL2 platforms.

Win32 Integration Example

#include "imgui.h"
#include "backends/imgui_impl_win32.cpp"
#include "backends/imgui_impl_opengl3.cpp"

int main()
{
    // Initialize window and OpenGL context...
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();
    io.ConfigFlags |= ImGuiConfigFlags_EnableIme;

    while (!glfwWindowShouldClose(window))
    {
        ImGui_ImplWin32_NewFrame();
        ImGui_ImplOpenGL3_NewFrame();
        ImGui::NewFrame();

        static char buf[256] = "";
        ImGui::InputText("Japanese Input", buf, sizeof(buf));

        if (ImGui::IsItemActive())
        {
            ImGuiPlatformImeData& ime = io.PlatformImeData;
            ime.Ready = true;
            ime.Pos = ImGui::GetItemRectMax();
            ime.WantTextInput = true;
        }

        ImGui::Render();
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
        // Swap buffers and poll events...
    }
}

SDL2 Native IME UI

// Must be called before SDL_CreateWindow
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");

SDL_Window* window = SDL_CreateWindow("IME Example", 
    SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 
    1280, 720, SDL_WINDOW_OPENGL);

ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_EnableIme;

Summary

  • ImGuiPlatformImeData in ImGuiIO stores cursor position and WantTextInput flags that control IME activation
  • The core library resets IME state each frame at line 6102 in imgui.cpp and triggers platform updates after UI layout
  • Win32 backends handle WM_IME_COMPOSITION at line 800 and WM_IME_CHAR at line 808 in imgui_impl_win32.cpp
  • SDL2/3 backends use SDL_StartTextInput and SDL_StopTextInput at lines 117-124, controlled by the WantTextInput flag
  • Enable IME explicitly by setting ImGuiConfigFlags_EnableIme in the io.ConfigFlags (available since Dear ImGui 1.91)
  • Position the candidate window by updating io.PlatformImeData.Pos when text widgets are active

Frequently Asked Questions

How do I enable IME support in Dear ImGui?

Set the ImGuiConfigFlags_EnableIme flag in ImGuiIO::ConfigFlags and ensure your platform backend (Win32, SDL2, or SDL3) is properly integrated. For Win32, avoid defining IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS to use the built-in handlers at lines 16349-16385 in imgui.cpp.

Why is the IME composition window not appearing?

Verify that io.PlatformImeData.WantTextInput is set to true when your text widget is active, and that io.PlatformImeData.Pos contains valid screen coordinates. For SDL2, ensure you called SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1") before creating the window.

Does Dear ImGui support mobile on-screen keyboards via IME?

Yes. The SDL2 and SDL3 backends automatically call SDL_StartTextInput and SDL_StopTextInput based on the WantTextInput flag, which triggers the on-screen keyboard on mobile platforms. This implementation is located at lines 117-124 in both imgui_impl_sdl2.cpp and imgui_impl_sdl3.cpp.

How do I position the IME candidate window correctly?

Update io.PlatformImeData.Pos with the screen coordinates where the composition window should appear, typically at the cursor location or the end of the active text field. Set io.PlatformImeData.Ready = true and io.PlatformImeData.WantTextInput = true after calling ImGui::InputText() or similar widgets, and ImGui will forward this position to the OS during the render phase.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →