# How to Integrate Gamepad Navigation and Input Handling with Dear ImGui

> Learn to integrate gamepad navigation and input with Dear ImGui. Enable ImGuiConfigFlags NavEnableGamepad and feed gamepad events for seamless control.

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

---

**Enable `ImGuiConfigFlags_NavEnableGamepad` in your `ImGuiIO` configuration and ensure your backend sets `ImGuiBackendFlags_HasGamepad` while feeding `ImGuiKey_Gamepad*` events via `AddKeyEvent` or `AddKeyAnalogEvent` each frame.**

Dear ImGui (ocornut/imgui) provides a built-in navigation system that processes keyboard, mouse, and gamepad inputs through a unified architecture. To integrate gamepad navigation, you must configure the **ImGuiIO** structure to enable gamepad support and ensure your platform backend translates hardware signals into ImGui key events. This guide demonstrates the complete pipeline from configuration flags to per-frame event submission using the official SDL2 backend as a reference implementation.

## Understanding the Gamepad Architecture in Dear ImGui

The gamepad integration relies on a three-layer architecture that separates platform detection from core navigation logic. This design allows the core library to remain platform-agnostic while delegating hardware-specific polling to the backend layer.

### The Application and IO Layer

The **ImGuiIO** structure exposed in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) (around line 400) serves as the primary interface. Your application sets configuration flags here to activate gamepad navigation, while the backend reports hardware availability through backend flags.

### The Backend Layer

Platform-specific code in files like [`backends/imgui_impl_sdl2.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_sdl2.cpp) detects connected controllers, samples axes and buttons, and translates these into standard **ImGuiKey** events. This layer calls `ImGui_ImplSDL2_UpdateGamepads` (around line 888) or equivalent functions each frame.

### The Core Navigation Layer

Internal structures in [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h) and the navigation engine in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) consume the key events, build directional navigation graphs, and move focus between widgets based on directional input. The `ImGuiNavItemData` structure defined at line 167 of [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h) stores candidate items during navigation traversal.

## Enabling Gamepad Navigation in Your Application

Before your main loop begins, activate gamepad support by modifying the **ConfigFlags** field in the ImGuiIO structure. This initialization step prepares the context to process gamepad events but requires backend cooperation to function.

Set the master flag once immediately after creating the ImGui context:

```cpp
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;  // Defined in imgui.h (L1730)

```

This flag instructs Dear ImGui to query for `ImGuiKey_Gamepad*` events each frame. However, navigation will not function until the backend advertises that a gamepad is present:

```cpp
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;  // Set by the backend (L1748)

```

The `ImGuiBackendFlags_HasGamepad` flag is typically managed automatically by official backends when they detect hardware connections. You can inspect this flag to show gamepad-specific UI hints when hardware is available.

## Implementing the Backend Layer (SDL2 Example)

The SDL2 backend in [`backends/imgui_impl_sdl2.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_sdl2.cpp) demonstrates the standard implementation pattern through three distinct phases. Each phase handles detection, analog sampling, or event submission.

### Detecting Controller Connections

During the new-frame update, the backend checks for connected gamepads using `SDL_GameControllerOpen` and `SDL_GameControllerClose`. When hardware is detected, it sets `io.BackendFlags |= ImGuiBackendFlags_HasGamepad` around line 855 of [`imgui_impl_sdl2.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_sdl2.cpp).

### Sampling Analog Axes

Modern Dear ImGui versions use `AddKeyAnalogEvent` rather than the deprecated `io.NavInputs[]` array. The backend reads SDL joystick axes and maps them to directional keys with analog values:

```cpp
// Simplified example from ImGui_ImplSDL2_UpdateGamepads (L888)
io.AddKeyAnalogEvent(ImGuiKey_GamepadLStickLeft, value > deadzone, value);

```

### Submitting Button Events

For digital buttons, the backend calls `AddKeyEvent` with the corresponding gamepad key enum. This bridges SDL controller buttons to the standard `ImGuiKey_GamepadFaceDown` and related constants defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) around line 1638:

```cpp
io.AddKeyEvent(ImGuiKey_GamepadFaceDown, pressed);  // Typically the "A" button
io.AddKeyEvent(ImGuiKey_GamepadFaceRight, pressed); // Typically the "B" button

```

All event submission occurs within `ImGui_ImplSDL2_NewFrame()`, which must be called once per frame before any ImGui rendering commands. This function aggregates all platform inputs and prepares the ImGui context for the frame update.

## Core Navigation Consumption

Once events reach the core library in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp), the navigation engine processes them through internal structures defined in [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h). The engine maintains state in **ImGuiContext** navigation fields such as `NavMoveRequest` and `NavItemData`.

When the system receives `ImGuiKey_GamepadDpad*` or stick events, it calculates directional movement and updates the focused widget accordingly. The navigation system respects **ImGuiWindowFlags_NoNavInputs** for disabling navigation per-window and **ImGuiItemFlags_NoNav** for specific widgets.

## Handling Gamepad Input in UI Code

After enabling the configuration flags, standard widgets automatically respond to gamepad navigation without additional code. Focus movement occurs via the D-pad or left stick, traversing the directional navigation graph between buttons, sliders, and other interactive elements.

Activation happens when the user presses `ImGuiKey_GamepadFaceDown` (typically the A button), which triggers the same action as a left-click or Enter key. Cancellation maps `ImGuiKey_GamepadFaceRight` (typically B) to the Escape key behavior.

For manual handling, query specific gamepad states directly using the `IsKeyPressed` API. This allows custom logic when standard navigation behavior is insufficient for your gameplay interface:

```cpp
if (ImGui::IsKeyPressed(ImGuiKey_GamepadFaceDown)) {
    // Custom activation logic
}
if (ImGui::IsKeyPressed(ImGuiKey_GamepadDpadUp)) {
    // Custom directional handling
}

```

## Customizing Gamepad Behavior

Dear ImGui exposes several IO fields to adjust gamepad behavior without modifying backend code. These controls affect button mapping and input processing at the application level.

### Swapping A/B Layouts

Set `io.ConfigNavSwapGamepadButtons = true` to invert the FaceDown and FaceRight mapping, accommodating Nintendo-style controller layouts where the rightmost face button confirms and the bottom button cancels. This field is declared in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) around line 2451 and takes effect immediately without restarting.

### Analog Navigation Speed

Adjust responsiveness by tuning values passed to `AddKeyAnalogEvent` in your backend, applying custom dead-zones before event submission. This keeps application-specific sensitivity logic out of the core library while maintaining analog movement speeds.

### Manual Gamepad Mode

For platforms lacking auto-detection, use backend-specific functions like `ImGui_ImplSDL2_SetGamepadMode()` with `ImGui_ImplSDL2_GamepadMode_Manual` to force gamepad availability. This bypasses the automatic connection detection in SDL2 and allows fixed controller assignments.

## Summary

- Enable `ImGuiConfigFlags_NavEnableGamepad` in `ImGuiIO.ConfigFlags` to activate the navigation system.
- Ensure your backend sets `ImGuiBackendFlags_HasGamepad` and feeds events via `AddKeyEvent` and `AddKeyAnalogEvent`.
- Reference [`backends/imgui_impl_sdl2.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_sdl2.cpp) (lines 855-888) for production-ready detection and polling logic.
- Use `ConfigNavSwapGamepadButtons` to swap confirm/cancel layouts for different controller families.
- Query `ImGuiKey_Gamepad*` enums manually when implementing custom gamepad-driven interactions.

## Frequently Asked Questions

### Does Dear ImGui support gamepad navigation out of the box?

Yes, the core library in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) includes a complete navigation engine that processes gamepad events once properly configured. However, you must enable `ImGuiConfigFlags_NavEnableGamepad` in your IO configuration, and your platform backend must detect hardware and submit `ImGuiKey_Gamepad*` events through the `AddKeyEvent` API.

### Which gamepad buttons map to ImGui actions?

By default, `ImGuiKey_GamepadFaceDown` (typically the A button on Xbox controllers) activates the focused widget, while `ImGuiKey_GamepadFaceRight` (typically B) functions as Escape. Directional navigation uses the `ImGuiKey_GamepadDpad*` and `ImGuiKey_GamepadLStick*` enums defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h).

### How do I handle gamepad dead zones when integrating with Dear ImGui?

Apply dead-zone calculations in your backend before calling `AddKeyAnalogEvent`, discarding small axial values that represent stick drift rather than intentional input. The SDL2 backend in [`imgui_impl_sdl2.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_sdl2.cpp) demonstrates this pattern by filtering raw axis values before submitting them to the ImGui IO queue.

### Can I use gamepad navigation alongside keyboard and mouse?

Yes, Dear ImGui's navigation system processes all input types simultaneously without conflicts. You can enable `ImGuiConfigFlags_NavEnableGamepad` while keeping keyboard navigation active via `ImGuiConfigFlags_NavEnableKeyboard`, allowing seamless switching between controller and traditional input methods.