# Handling Keyboard and Mouse Input Events Through Dear ImGuiIO: A Complete Guide

> Master Dear ImGuiIO to seamlessly handle keyboard and mouse input events. This guide simplifies UI interaction by explaining the centralized I/O hub and how backends populate it each frame.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: how-to-guide
- Published: 2026-07-14

---

**Dear ImGui processes all keyboard, mouse, and text input through the `ImGuiIO` structure, which acts as a centralized I/O hub that backends populate via `Add*` functions and the UI queries each frame to drive interaction.**

The `ImGuiIO` structure is the single data-exchange point between your application and Dear ImGui. Whether you are using a standard backend like GLFW or building a custom integration for a proprietary engine, understanding how to feed input events through `ImGuiIO` is essential for responsive UI navigation.

## The ImGuiIO Structure: Your Input Pipeline

The `ImGuiIO` structure is declared in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) (around line 2430) and serves as the authoritative source for all input state. Rather than modifying internal arrays directly, your backend calls specific `Add*` methods to queue events, making the system frame-rate independent and robust against low-framerate scenarios.

Key member groups inside `ImGuiIO` include:

- **Configuration flags** (`ConfigFlags`, `BackendFlags`) – Declare which optional features are active, such as `ImGuiConfigFlags_NavEnableKeyboard`.
- **Input queues** – The `Add*` functions that backends call: `AddKeyEvent`, `AddKeyAnalogEvent`, `AddMousePosEvent`, `AddMouseButtonEvent`, `AddMouseWheelEvent`, and `AddInputCharacter`.
- **Output flags** (`WantCaptureMouse`, `WantCaptureKeyboard`, `WantTextInput`) – Signals set by ImGui during `NewFrame()` that tell your application whether to consume or forward subsequent input events.
- **State caches** (`MousePos`, `MouseDown[]`, `KeysData[]`) – Read-only snapshots filled by the `Add*` calls and consumed by widgets.

## How Official Backends Translate Native Events

Standard backends like the GLFW implementation in [`imgui_impl_glfw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_glfw.cpp) demonstrate the canonical pattern for event translation. Each native callback maps platform-specific codes to the `ImGuiKey` enumeration, then pushes the data into `ImGuiIO`.

### Keyboard Input Mapping

The `ImGui_ImplGlfw_KeyCallback` function translates GLFW keycodes using `ImGui_ImplGlfw_KeyToImGuiKey`, then submits the event:

```cpp
io.AddKeyEvent(imgui_key, (action == GLFW_PRESS));
io.SetKeyEventNativeData(imgui_key, keycode, scancode);   // legacy support

```

This pattern appears at lines 494-498 in [`imgui_impl_glfw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_glfw.cpp). Modifier keys are handled separately via `ImGui_ImplGlfw_UpdateKeyModifiers` (lines 10-14), which calls `io.AddKeyEvent` for each `ImGuiMod_*` flag to ensure `Ctrl`, `Shift`, `Alt`, and `Super` states are current.

### Mouse Movement and Buttons

For cursor position, the backend forwards coordinates directly:

```cpp
io.AddMousePosEvent((float)x, (float)y);

```

Mouse button states are submitted similarly (lines 29-31):

```cpp
io.AddMouseButtonEvent(button, action == GLFW_PRESS);

```

### Scroll and Text Input

Scroll events are processed in `ImGui_ImplGlfw_ScrollCallback` (lines 44-46):

```cpp
io.AddMouseWheelEvent((float)xoffset, (float)yoffset);

```

Unicode text input is captured via `ImGui_ImplGlfw_CharCallback` (lines 50-51):

```cpp
io.AddInputCharacter(c);

```

## Event Queuing and Trickling

Starting with **v1.87**, Dear ImGui supports the `ConfigInputTrickleEventQueue` configuration. This feature automatically distributes events that occur between frames—such as a rapid mouse-down and mouse-up sequence—across multiple `NewFrame()` calls. 

Your backend does not implement this logic; it simply calls the `Add*` functions. ImGui timestamps each entry internally and releases them sequentially to prevent input loss during low-framerate situations. This makes the library resilient when the application runs at 30 FPS but the input device polls at 1000 Hz.

## Consuming Input in Your Application

After calling `ImGui::NewFrame()`, inspect the output flags to determine whether ImGui wants exclusive access to input events:

```cpp
if (io.WantCaptureMouse) {
    // ImGui is hovering a window or widget; do not send this event to your game
}

if (io.WantCaptureKeyboard) {
    // An InputText is active; consume keyboard events here
}

```

This design allows seamless integration where ImGui overlays do not interfere with underlying game logic unless intentionally focused.

## Implementing a Custom Backend

For platforms without official support, implement the same pattern used in [`imgui_impl_glfw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_glfw.cpp). You only need to map native codes to `ImGuiKey` and call the appropriate `Add*` methods:

```cpp
void MyApp_OnKey(int nativeKey, bool down)
{
    ImGuiIO& io = ImGui::GetIO();
    ImGuiKey imgui_key = MyMapNativeToImGuiKey(nativeKey);
    io.AddKeyEvent(imgui_key, down);
}

```

A minimal manual feeding example (no backend) looks like this:

```cpp
void FeedImGuiInput()
{
    ImGuiIO& io = ImGui::GetIO();

    // Keyboard: press/release 'A'
    io.AddKeyEvent(ImGuiKey_A, true);
    io.AddKeyEvent(ImGuiKey_A, false);

    // Mouse: move to (400,300)
    io.AddMousePosEvent(400.0f, 300.0f);

    // Left button click
    io.AddMouseButtonEvent(0, true);   // 0 = ImGuiMouseButton_Left
    io.AddMouseButtonEvent(0, false);

    // Wheel scroll up
    io.AddMouseWheelEvent(0.0f, 1.0f);
}

```

For raw Win32 integration, your window procedure would look similar to this:

```cpp
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    ImGuiIO& io = ImGui::GetIO();

    switch (msg)
    {
    case WM_KEYDOWN:
    case WM_SYSKEYDOWN:
        io.AddKeyEvent(ImGuiKey_FromVirtualKey((int)wParam), true);
        break;
    case WM_KEYUP:
    case WM_SYSKEYUP:
        io.AddKeyEvent(ImGuiKey_FromVirtualKey((int)wParam), false);
        break;
    case WM_MOUSEMOVE:
        io.AddMousePosEvent((float)GET_X_LPARAM(lParam), (float)GET_Y_LPARAM(lParam));
        break;
    case WM_LBUTTONDOWN:
        io.AddMouseButtonEvent(ImGuiMouseButton_Left, true);
        break;
    case WM_LBUTTONUP:
        io.AddMouseButtonEvent(ImGuiMouseButton_Left, false);
        break;
    case WM_MOUSEWHEEL:
        io.AddMouseWheelEvent(0.0f, (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA);
        break;
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

```

## Summary

- **`ImGuiIO` in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)** is the central structure for all input handling in Dear ImGui.
- Backends call `AddKeyEvent`, `AddMousePosEvent`, `AddMouseButtonEvent`, and `AddMouseWheelEvent` rather than modifying internal state directly.
- The **trickle queue** (`ConfigInputTrickleEventQueue`) automatically handles high-frequency input on low-framerate applications without backend changes.
- Check **`io.WantCaptureMouse`** and **`io.WantCaptureKeyboard`** after `ImGui::NewFrame()` to determine whether to consume or forward events.
- Custom backends follow the same pattern as [`imgui_impl_glfw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_glfw.cpp): map native codes to `ImGuiKey`, then submit via `Add*` functions.

## Frequently Asked Questions

### How do I handle modifier keys like Ctrl and Shift in Dear ImGui?

Modifier keys are treated as regular keys in the `ImGuiKey` enumeration (e.g., `ImGuiMod_Ctrl`, `ImGuiMod_Shift`). Your backend should call `io.AddKeyEvent(ImGuiMod_Ctrl, true)` when the control key is pressed, typically inside your key callback or a dedicated update function like `ImGui_ImplGlfw_UpdateKeyModifiers` shown in the GLFW backend.

### What is the difference between `AddKeyEvent` and `AddKeyAnalogEvent`?

`AddKeyEvent` submits a boolean pressed/released state for digital keys, while `AddKeyAnalogEvent` submits a float value between 0.0 and 1.0 for analog inputs like gamepad triggers or analog sticks. Most keyboard and mouse integrations use `AddKeyEvent` exclusively.

### Why should I use `Add*` functions instead of writing directly to `io.KeysData[]`?

Direct array access is unsupported and breaks internal consistency. The `Add*` functions handle timestamping, trickle-queue management, and legacy compatibility. According to the Dear ImGui source, these functions are the only supported API for submitting input, ensuring frame-rate independence and correct behavior with `ConfigInputTrickleEventQueue`.

### How do I prevent ImGui from capturing mouse events when clicking through to my game?

After calling `ImGui::NewFrame()`, check `io.WantCaptureMouse`. If this flag is false, the mouse is not over any ImGui window or widget, and you should process the event in your application. If true, ImGui owns the input for that frame, and you should skip sending it to your game logic.