How to Handle DPI Scaling in Dear ImGui Applications: A Complete Implementation Guide

Dear ImGui handles DPI scaling through a three-layer architecture that requires OS-level DPI awareness, ImGuiIO configuration flags such as io.ConfigDpiScaleFonts, and runtime scaling factors including style.FontScaleDpi that the application must wire together before the first frame.

Dear ImGui (ocornut/imgui) provides robust support for high-DPI monitors through a deliberate design that separates platform responsibilities from UI scaling logic. To handle DPI scaling in Dear ImGui applications effectively, you must coordinate three distinct layers: operating system declarations, backend configuration flags, and internal style variables that control font rasterization and widget geometry.

The Three-Layer DPI Architecture

DPI scaling in Dear ImGui is intentionally split into three independent concerns that your application must connect:

  1. OS-Level DPI Awareness: Prevents the operating system from automatically bitmap-scaling your window, which would produce blurry output. On Windows, this is implemented in ImGui_ImplWin32_EnableDpiAwareness() inside backends/imgui_impl_win32.cpp#L24-L30. On SDL2, you use the SDL_WINDOW_ALLOW_HIGHDPI flag, while GLFW relies on GLFW_SCALE_TO_MONITOR.

  2. ImGuiIO Configuration Flags: Boolean switches that tell Dear ImGui to automatically update scaling variables when the monitor DPI changes. According to docs/FAQ.md#L792, setting io.ConfigDpiScaleFonts to true enables automatic overwriting of style.FontScaleDpi, while io.ConfigDpiScaleViewports additionally scales platform windows in the docking branch.

  3. Internal Scaling Factors: Runtime values multiplied into geometry calculations. These include g.Style._MainScale (accessed via GetScale() in imgui_internal.h#L3348), style.FontScaleDpi (declared in imgui.h#L2314), and io.MouseCursorScale (defined in imgui.h#L2375). These are initialized in imgui.cpp#L1511 and applied to window sizes at imgui.cpp#L9217.

This separation exists because OS awareness is required to get a 1:1 framebuffer, while ImGui’s internal flags provide the library freedom to decide when and how to apply scaling without breaking user customizations.

Step 1: Enable OS-Level DPI Awareness

You must declare DPI awareness before creating your window. Failure to do so results in the OS scaling the framebuffer automatically, making Dear ImGui’s own scaling redundant and producing blurry fonts.

  • Windows: Call ImGui_ImplWin32_EnableDpiAwareness() prior to CreateWindow(). This helper uses SetProcessDpiAwarenessContext() when available, falling back to SetProcessDPIAware() on older systems.

  • SDL2: Pass the SDL_WINDOW_ALLOW_HIGHDPI flag to SDL_CreateWindow(), as demonstrated in examples/example_sdl2_opengl3/main.cpp#L84.

  • GLFW: Set glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE) before window creation, or rely on the default high-DPI handling shown in examples/example_glfw_opengl3/main.cpp#L92.

  • macOS: The native backend already supports HiDPI; no extra call is required.

Step 2: Configure Automatic DPI Scaling

Once the window is DPI-aware, enable Dear ImGui’s automatic scaling in the docking branch by setting two flags in your initialization code:

ImGuiIO& io = ImGui::GetIO();
io.ConfigDpiScaleFonts     = true;  // Auto-updates style.FontScaleDpi
io.ConfigDpiScaleViewports = true;  // Also scales platform windows

When io.ConfigDpiScaleFonts is enabled, Dear ImGui automatically overwrites style.FontScaleDpi whenever the monitor DPI changes, as noted in the initialization code at imgui.cpp#L1511. If you prefer manual control, leave these as false and assign style.FontScaleDpi yourself, as shown in examples/example_win32_opengl3/main.cpp#L77.

Step 3: Understand Internal Scaling Factors

Dear ImGui applies three distinct scales during rendering:

  • Global UI Scale (g.Style._MainScale): Retrieved via GetScale() in imgui_internal.h#L3348, this factor affects widget thickness, window padding, and layout spacing.

  • Font DPI Scale (style.FontScaleDpi): Declared in imgui.h#L2314, this multiplier is applied to text geometry during glyph rasterization. It allows fonts to scale independently of the global UI scale.

  • Mouse Cursor Scale (io.MouseCursorScale): Defined in imgui.h#L2375, this scales software-rendered mouse cursors to match the DPI.

You can set an initial manual base scale before the auto-scale system kicks in:

ImGuiStyle& style = ImGui::GetStyle();
style.FontScaleDpi = 1.5f;  // Start at 150% font size

Handling Per-Monitor DPI Changes

For applications that span multiple monitors with different DPIs, query the scale factor each frame or when the window moves. The Win32 backend provides ImGui_ImplWin32_GetDpiScaleForMonitor() for this purpose. Internally, Dear ImGui stores the current monitor’s scale in g.CurrentDpiScale (see imgui.cpp#L4700), which the docking branch uses to update viewport scaling automatically when io.ConfigDpiScaleViewports is enabled.

If you are not using the docking branch, manually multiply the OS-reported DPI scale (e.g., from SDL’s SDL_GetWindowDisplayScale or GLFW’s glfwGetWindowContentScale) into style.FontScaleDpi and io.MouseCursorScale during your main loop.

Complete Cross-Platform Implementation

The following snippet demonstrates the full initialization flow for Win32, SDL2, and GLFW backends:

// ------------------------------------------------------------
// 1. Create a DPI-aware window (platform-specific)
// ------------------------------------------------------------
#if defined(_WIN32)
    // Win32 – ask Windows to make the process DPI-aware
    ImGui_ImplWin32_EnableDpiAwareness();   // → backends/imgui_impl_win32.cpp
    // Create your Win32 window as usual (hwnd)
#elif defined(__APPLE__) && defined(__MACH__)
    // macOS – the native backend already supports HiDPI; no extra call needed
    // Create NSWindow/GLFW window normally
#else
    // SDL2 example (works for both SDL2 and SDL3)
    SDL_Window* window = SDL_CreateWindow(
        "My ImGui App",
        SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        1280, 720,
        SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
#endif

// ------------------------------------------------------------
// 2. Initialise ImGui (common to all back-ends)
// ------------------------------------------------------------
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();

// Enable ImGui's own DPI handling (requires docking branch)
// This will automatically rewrite style.FontScaleDpi whenever the monitor DPI changes.
io.ConfigDpiScaleFonts     = true;   // scales fonts
io.ConfigDpiScaleViewports = true;   // also scales platform windows (if you use viewports)

// Optional: set a manual base scale before the auto-scale runs
ImGuiStyle& style = ImGui::GetStyle();
style.FontScaleDpi = 1.2f;           // start at 120% font size

// ------------------------------------------------------------
// 3. Backend-specific init (example for Win32)
// ------------------------------------------------------------
#if defined(_WIN32)
    ImGui_ImplWin32_Init(hwnd);
#elif defined(__APPLE__) && defined(__MACH__)
    ImGui_ImplOSX_Init();
#else
    ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
#endif

// ------------------------------------------------------------
// 4. Main loop – ImGui will now use the DPI-aware scalings automatically
// ------------------------------------------------------------
while (!done)
{
    // Platform event handling...
    ImGui_Impl..._NewFrame();
    ImGui::NewFrame();

    // Your UI code here
    ImGui::Text("DPI-aware window");

    ImGui::Render();
    ImGui_Impl..._RenderDrawData(ImGui::GetDrawData());
}

Summary

  • OS awareness comes first: Call ImGui_ImplWin32_EnableDpiAwareness() or use SDL_WINDOW_ALLOW_HIGHDPI before creating the window to prevent OS-level bitmap scaling.
  • Enable automatic handling: Set io.ConfigDpiScaleFonts and io.ConfigDpiScaleViewports to true in the docking branch to let Dear ImGui manage style.FontScaleDpi automatically.
  • Three scales control rendering: g.Style._MainScale for UI geometry, style.FontScaleDpi for text, and io.MouseCursorScale for cursors.
  • Manual fallback: If not using the docking branch, query the monitor DPI via your platform API and assign the scale factor to style.FontScaleDpi directly.

Frequently Asked Questions

Does DPI scaling require the docking branch of Dear ImGui?

The automatic scaling flags io.ConfigDpiScaleFonts and io.ConfigDpiScaleViewports are only available in the docking branch. If you are using the master branch, you must manually calculate the DPI scale using ImGui_ImplWin32_GetDpiScaleForMonitor() or equivalent platform functions, then assign the value to style.FontScaleDpi each frame.

Why do my fonts appear blurry even after calling EnableDpiAwareness?

Blurriness indicates that the OS is still bitmap-scaling your framebuffer. Verify that you called ImGui_ImplWin32_EnableDpiAwareness() before creating the window, and ensure your graphics API backend (OpenGL, DirectX, Vulkan) is creating a backbuffer at the full native resolution rather than a scaled resolution.

How do I calculate the correct scale factor for a specific monitor?

On Windows, use ImGui_ImplWin32_GetDpiScaleForMonitor() provided in the Win32 backend. For SDL2, call SDL_GetWindowDisplayScale(window). For GLFW, use glfwGetWindowContentScale(window, &xscale, &yscale). Multiply this value by your base style.FontScaleDpi to get the final scale.

Can I use different scale factors for different viewports when using multi-viewports?

Yes. When io.ConfigDpiScaleViewports is enabled in the docking branch, Dear ImGui automatically applies per-viewport scaling based on the monitor each viewport resides on. The internal variable g.CurrentDpiScale (see imgui.cpp#L4700) tracks this per-viewport value, ensuring that platform windows render at the correct DPI regardless of which monitor they occupy.

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 →