Dear ImGui Input Handling Integration: A Complete Technical Guide to Platform Backends
Dear ImGui collects raw keyboard, mouse, focus and text events through the ImGuiIO API, which platform backends populate via Add*Event functions before each NewFrame() call.
Dear ImGui input handling integration relies on a clear separation between the core library and platform-specific code. The ocornut/imgui repository implements this architecture through the ImGuiIO structure defined in imgui.h, which acts as a centralized input queue that backends fill with native windowing events every frame. Understanding this contract is essential for implementing custom backends or modifying existing ones like GLFW, Win32, or SDL.
The ImGuiIO Input Queue API
The heart of Dear ImGui input handling is the ImGuiIO structure, which exposes a set of "Add" functions that backends must call to forward platform events. These functions are defined in imgui.h and push data into internal queues consumed during NewFrame().
Core Input Functions
According to the source code in imgui.h, backends must populate the following event types:
AddKeyEvent/AddKeyAnalogEvent– Queue key-down/up states or analog values (gamepad triggers, joystick axes)AddMousePosEvent– Queue mouse cursor position updates (pass-FLT_MAXto signal no mouse)AddMouseButtonEvent– Queue mouse button state changesAddMouseWheelEvent– Queue horizontal and vertical scroll deltasAddFocusEvent– Queue application focus gain/loss eventsAddInputCharacter/AddInputCharacterUTF16/AddInputCharactersUTF8– Queue Unicode text input forInputText()widgets
Internally, these calls populate fields within ImGuiIO:
ImWchar16 InputQueueSurrogate; // Used only by AddInputCharacterUTF16()
ImVector<ImWchar> InputQueueCharacters; // Holds characters consumed by InputText()
These queues are cleared automatically at the end of each frame, ensuring frame-accurate input that preserves event ordering.
Platform Backend Integration Pattern
All official backends in the ocornut/imgui repository follow an identical integration pattern. A backend must store a pointer to its data structure (e.g., ImGui_ImplGlfw_Data), install callbacks with the native windowing library, and forward events to ImGuiIO inside those callbacks.
GLFW Backend Example
In backends/imgui_impl_glfw.cpp, the character input callback demonstrates this pattern:
void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
if (bd->PrevUserCallbackChar && ImGui_ImplGlfw_ShouldChainCallback(bd, window))
bd->PrevUserCallbackChar(window, c); // Preserve user-provided callback
ImGuiIO& io = ImGui::GetIO(bd->Context);
io.AddInputCharacter(c); // Forward text input to Dear ImGui
}
Win32 Backend Example
Similarly, backends/imgui_impl_win32.cpp handles WM_CHAR messages:
case WM_CHAR:
// 2019-05-11: Don't filter the value before forwarding
io.AddInputCharacter((unsigned int)wParam); // Forward text input
break;
Both implementations also forward mouse movement (WM_MOUSEMOVE or glfwSetCursorPosCallback) and button events using the corresponding AddMousePosEvent and AddMouseButtonEvent functions.
Frame Input Processing Flow
Understanding the execution order is critical for correct Dear ImGui input handling integration:
- Platform callbacks fire when the operating system delivers events (window messages, GLFW callbacks, etc.)
- Each callback pushes data into
ImGuiIOfields via theAdd*Eventfunctions - The application calls
ImGui::NewFrame(), which reads queued input, updates internal state, and clears the queues - UI widgets like
InputText()consume characters fromInputQueueCharactersduring the frame
This queue-based design guarantees reliable text entry, mouse dragging, and key repeat handling regardless of platform event timing.
Customizing and Extending Input
Injecting Synthetic Events
To programmatically inject input for automated testing or macros, call the Add*Event functions directly from your application code:
ImGuiIO& io = ImGui::GetIO();
io.AddInputCharacter('A'); // Adds 'A' to the next InputText widget
io.AddKeyEvent(ImGuiKey_Space, true); // Simulates Space key press
Filtering Text Input
To filter or modify characters before they reach widgets, use the ImGuiInputTextFlags_CallbackCharFilter flag on InputText() and adjust EventChar within your callback function.
High-DPI and Multi-Monitor Support
For high-DPI setups, backends typically scale mouse coordinates before calling AddMousePosEvent. The Win32 and GLFW backends handle this by querying monitor DPI and applying scaling factors to raw cursor positions.
Complete Implementation Example
The following pattern shows a complete GLFW-based input pipeline:
// 1. Initialise ImGui and backend
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init("#version 150");
// 2. Main loop
while (!glfwWindowShouldClose(window))
{
glfwPollEvents(); // Triggers ImGui_ImplGlfw_* callbacks
// 3. Start frame (processes queued input)
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// 4. UI code consumes input automatically
static char buf[128] = "";
ImGui::InputText("Label", buf, IM_ARRAYSIZE(buf));
// 5. Render
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
}
Key Source Files
imgui.h– DefinesImGuiIO, input queues, andAdd*Eventfunction signaturesbackends/imgui_impl_glfw.cpp– GLFW mouse, keyboard, and text input integrationbackends/imgui_impl_win32.cpp– Win32 window message handling (WM_*events)imgui.cpp– Core implementation ofNewFrame()and input queue processingimgui_demo.cpp– Reference implementations ofInputTextand event handling
Summary
- ImGuiIO is the central contract between Dear ImGui and platform backends, defined in
imgui.h - Backends call
AddKeyEvent,AddMousePosEvent,AddInputCharacter, and related functions to queue raw input - Input queues are cleared every frame during
NewFrame(), ensuring frame-accurate event processing - Official backends in
backends/imgui_impl_glfw.cppandbackends/imgui_impl_win32.cppdemonstrate the callback-to-queue pattern - Synthetic events can be injected directly via
ImGuiIOfor testing or automation
Frequently Asked Questions
How do I handle high-DPI mouse coordinates in Dear ImGui?
Scale mouse coordinates before calling io.AddMousePosEvent(). The official GLFW and Win32 backends query monitor DPI settings and apply scaling factors to raw cursor positions, ensuring UI elements align correctly with the mouse cursor on high-DPI displays.
Can I inject synthetic input events for automated testing?
Yes. Obtain the ImGuiIO reference via ImGui::GetIO() and call any Add*Event function directly from your test code. For example, io.AddInputCharacter('A') queues a character for the next InputText widget, while io.AddKeyEvent(ImGuiKey_Enter, true) simulates a key press.
What is the correct order of operations for input handling?
Platform callbacks must fire before ImGui::NewFrame(). The typical sequence is: (1) Poll native events (glfwPollEvents, PeekMessage), (2) callbacks populate ImGuiIO queues, (3) call NewFrame() to process input, (4) render UI. Reversing steps 2 and 3 results in one-frame input latency.
How do I filter characters entering an InputText widget?
Use the ImGuiInputTextFlags_CallbackCharFilter flag when calling InputText(), then modify EventChar in your callback function. This intercepts characters after they enter InputQueueCharacters but before the widget consumes them, allowing you to block specific inputs or convert characters programmatically.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →