How to Configure DPI Scaling and Handle High-DPI Displays in Dear ImGui

TLDR: Enable per-process DPI awareness via ImGui_ImplWin32_EnableDpiAwareness() (or platform equivalent), set io.ConfigDpiScaleFonts and io.ConfigDpiScaleViewports to true in imgui.h, and apply scaling factors via io.FontScaleDpi or ImGuiStyle::ScaleAllSizes() to render crisp text and UI elements on high-DPI monitors.

Dear ImGui (ocornut/imgui) requires explicit configuration to render properly on high-DPI (retina) displays, as the library does not automatically detect monitor DPI. By combining platform-specific DPI awareness calls with ImGui's built-in scaling flags, you can ensure your interface remains sharp and readable across standard and high-resolution displays.

Enable System-Level DPI Awareness

Before creating any OS window or ImGui context, your application must declare itself DPI-aware to the operating system. On Windows, the Win32 backend provides a dedicated helper function that handles the necessary API calls.

Call ImGui_ImplWin32_EnableDpiAwareness() (defined in backends/imgui_impl_win32.cpp around line 836) before ImGui::CreateContext() and window creation:

// Must be the first DPI-related call, before any window creation
ImGui_ImplWin32_EnableDpiAwareness();

// Then create context and windows
ImGui::CreateContext();
// ... backend initialization

This function internally calls Windows APIs such as SetProcessDpiAwarenessContext or SetProcessDpiAwareness depending on Windows version availability. For other platforms (macOS, Linux), you must use the appropriate native API (e.g., NSHighResolutionCapable in Info.plist for macOS) before initializing your graphics backend.

Configure Automatic DPI Scaling in ImGuiIO

Once the process is DPI-aware, configure ImGui to automatically respond to monitor scale changes via the ImGuiIO structure. In imgui.h (around line 2314), two key flags control this behavior:

ImGuiIO& io = ImGui::GetIO();
io.ConfigDpiScaleFonts = true;      // Scale fonts when monitor DPI changes
io.ConfigDpiScaleViewports = true;   // Scale ImGui windows/viewports on DPI change (docking branch)

When ConfigDpiScaleFonts is enabled, ImGui automatically updates the io.FontScaleDpi value based on the current monitor's DPI queried from the backend (e.g., via ImGui_ImplWin32_GetDpiScaleForMonitor()). The ConfigDpiScaleViewports flag enables automatic window scaling in multi-viewport/docking builds when the application window moves between monitors with different DPI settings.

Scale Fonts and UI Elements

ImGui provides two primary methods for scaling your interface: dynamic per-frame font scaling for text, and static style scaling for UI element sizes.

Dynamic Font Scaling

For text rendering, you can either rely on the automatic io.FontScaleDpi multiplier or manually push scaled fonts:

// Option 1: Use the global DPI scale factor (set automatically if ConfigDpiScaleFonts is true)
io.FontScaleDpi = 2.0f;  // 200% scaling for high-DPI monitor

// Option 2: Push a specific scaled font size
float scale = 2.0f;
ImGui::PushFont(nullptr, 42.0f * scale);  // 42pt * DPI scale
ImGui::Text("Large text on high-DPI display");
ImGui::PopFont();

Fixed UI Scaling with ScaleAllSizes

For single-viewport applications or when you want a fixed UI size regardless of monitor, use ImGuiStyle::ScaleAllSizes(). This method, implemented in imgui.cpp (around line 1598), bakes a scale factor into all style dimensions (padding, spacing, sizes) once at initialization:

ImGuiStyle& style = ImGui::GetStyle();
float fixed_scale = 1.5f;  // 150% UI size
style.ScaleAllSizes(fixed_scale);

// Optionally also set the font scale
style.FontScaleDpi = fixed_scale;

Note: When using ConfigDpiScaleViewports (docking branch), ImGui automatically handles UI scaling when viewports move between monitors, making manual ScaleAllSizes adjustments unnecessary for multi-monitor setups.

Backend-Specific High-DPI Window Creation

Most example backends request high-DPI framebuffers during window creation. When using SDL2, include the SDL_WINDOW_ALLOW_HIGHDPI flag:

SDL_Window* window = SDL_CreateWindow("Demo",
    SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
    1280, 720,
    SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
    
// Windows-specific additional awareness
::SetProcessDPIAware();

The Win32/OpenGL3 example (examples/example_win32_opengl3/main.cpp, line 76) demonstrates combining SDL2 high-DPI flags with ImGui's ScaleAllSizes for a complete setup.

Summary

  • Enable DPI awareness first: Call ImGui_ImplWin32_EnableDpiAwareness() (Win32) or platform equivalent before window creation and context initialization.
  • Configure automatic scaling: Set io.ConfigDpiScaleFonts and io.ConfigDpiScaleViewports to true to leverage automatic DPI detection from the backend.
  • Apply font scaling: Use io.FontScaleDpi for global text scaling or ImGui::PushFont() with calculated sizes for specific widgets.
  • Bake UI sizes: Call style.ScaleAllSizes(factor) for single-viewport applications requiring fixed scaling factors.
  • Request high-DPI framebuffers: Use backend-specific flags like SDL_WINDOW_ALLOW_HIGHDPI when creating OS windows.

Frequently Asked Questions

What is the difference between ConfigDpiScaleFonts and ConfigDpiScaleViewports?

ConfigDpiScaleFonts tells ImGui to automatically adjust the font scale multiplier when the application detects a DPI change, affecting text rendering size. ConfigDpiScaleViewports (relevant for the docking branch) tells ImGui to automatically scale entire window dimensions and positions when viewports move between monitors with different DPI settings. Enable both for complete automated handling in multi-monitor setups.

Do I need the docking branch to handle DPI scaling?

No. While ConfigDpiScaleViewports requires the docking branch for automatic per-viewport scaling, you can achieve high-DPI support in the main branch by manually calling ScaleAllSizes() and setting io.FontScaleDpi based on your platform's DPI queries. The docking branch simply automates the recalculation when windows move between monitors.

How do I handle DPI changes when moving windows between monitors?

In a standard single-viewport build, you must manually detect monitor changes via your platform API (e.g., WM_DPICHANGED on Windows), then recalculate and reapply ScaleAllSizes() and io.FontScaleDpi. In the docking branch with ConfigDpiScaleViewports enabled, ImGui handles this automatically using the backend's per-monitor DPI queries (such as ImGui_ImplWin32_GetDpiScaleForMonitor()).

Why do my fonts look blurry on high-DPI displays?

Blurry fonts typically occur when the application renders to a low-resolution framebuffer that is then upscaled by the OS. Ensure you request a high-DPI framebuffer using backend-specific flags (e.g., SDL_WINDOW_ALLOW_HIGHDPI for SDL2) and that your process is marked DPI-aware before window creation. Additionally, verify that your font atlas is rebuilt with appropriate pixel sizes multiplied by the DPI scale factor.

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 →