# How to Enable and Implement Multi-Viewport Support for Secondary ImGui Windows

> Unlock multi-viewport support for secondary ImGui windows. Learn to enable viewport flags and update your main loop for seamless window management in your ImGui applications.

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

---

**Enable multi-viewport support in Dear ImGui by setting the `ImGuiConfigFlags_ViewportsEnable` flag in `ImGuiIO::ConfigFlags`, then ensure your main loop calls `ImGui::UpdatePlatformWindows()` and `ImGui::RenderPlatformWindowsDefault()` after rendering the primary viewport.**

The multi-viewport feature in the [ocornut/imgui](https://github.com/ocornut/imgui) repository allows secondary ImGui windows to break out of the main application frame and become independent native OS windows. This capability requires coordination between the core ImGui context defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h), platform-specific backend implementations in the `backends/` directory, and your rendering loop. When properly configured, you can drag any ImGui window outside the main viewport to automatically spawn a separate native window that can be moved, resized, and layered independently.

## Understanding Multi-Viewport Architecture

Multi-viewport support spans three distinct layers in the ImGui architecture. Understanding these layers clarifies why specific configuration steps are necessary for secondary windows to function as independent OS windows.

### Configuration Layer

At the highest level, the **ImGuiIO** structure controls global behavior through bit flags. The system checks `io.ConfigFlags` for `ImGuiConfigFlags_ViewportsEnable` to determine whether to instantiate the viewport subsystem. This flag is defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) alongside other configuration options.

### Platform Abstraction Layer

When viewports are enabled, ImGui delegates window management to the **ImGuiPlatformIO** interface. This abstraction layer contains function pointers for native window operations. The official backends in [`backends/imgui_impl_win32.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_win32.cpp), [`backends/imgui_impl_glfw.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_glfw.cpp), and [`backends/imgui_impl_sdl2.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_sdl2.cpp) provide concrete implementations for these callbacks.

### Rendering Infrastructure

Each viewport maintains its own **ImDrawData** instance. The rendering backend must support drawing from arbitrary draw lists, not just the main viewport's data. The official rendering backends like [`backends/imgui_impl_opengl3.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_opengl3.cpp) and [`backends/imgui_impl_vulkan.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_vulkan.cpp) handle this automatically by iterating over all active viewports.

## Enabling the Viewports Feature

Activation requires a single line of code during initialization. After creating the ImGui context, access the IO structure and set the configuration flag:

```cpp
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;

```

This modification must occur before the first call to `ImGui::NewFrame()`. Once enabled, ImGui treats every `ImGui::Begin()`/`ImGui::End()` block as a potential candidate for externalization when dragged beyond the main window boundaries.

## Platform Backend Requirements

For secondary viewports to materialize as OS windows, the platform backend must implement the **PlatformIO** callbacks. The `ImGuiPlatformIO` structure, accessible via `ImGui::GetPlatformIO()`, requires the following function pointers:

- **Platform_CreateWindow** / **Platform_DestroyWindow**: Native window lifecycle management
- **Platform_GetWindowPos** / **Platform_SetWindowPos**: Position queries and updates
- **Platform_GetWindowSize** / **Platform_SetWindowSize**: Dimension handling  
- **Platform_SetWindowFocus** / **Platform_GetWindowFocus**: Focus state management
- **Platform_GetWindowMinimized**: Minimization state detection
- **Platform_SetWindowTitle** / **Platform_GetWindowTitle**: Text updates
- **Platform_SetWindowAlpha**: Optional opacity control

The Win32 backend in [`backends/imgui_impl_win32.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_win32.cpp) demonstrates a complete implementation using `CreateWindowEx`, `SetWindowPos`, and related Win32 APIs. Similarly, [`backends/imgui_impl_glfw.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_glfw.cpp) maps these callbacks to GLFW window functions, while [`backends/imgui_impl_sdl2.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_sdl2.cpp) uses SDL2 window management routines.

## Rendering Backend Integration

Platform backends handle window creation, but the rendering backend must actually draw the content. When `ImGuiConfigFlags_ViewportsEnable` is active, your main loop requires additional steps after the standard render call.

The canonical rendering pattern looks like this:

```cpp
while (!glfwWindowShouldClose(main_window))
{
    // Start frame
    ImGui_ImplOpenGL3_NewFrame();
    ImGui_ImplGlfw_NewFrame();
    ImGui::NewFrame();

    // Build UI
    ImGui::Begin("Draggable Window");
    ImGui::Text("Drag me outside the main window");
    ImGui::End();

    // Render main viewport
    ImGui::Render();
    ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

    // Handle secondary viewports
    if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
    {
        ImGui::UpdatePlatformWindows();        // Create/destroy OS windows
        ImGui::RenderPlatformWindowsDefault(); // Render each viewport
    }

    glfwSwapBuffers(main_window);
    glfwPollEvents();
}

```

The `UpdatePlatformWindows()` function, implemented in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp), iterates over viewports and invokes the PlatformIO callbacks to synchronize native window states. `RenderPlatformWindowsDefault()` then calls the rendering backend for each secondary viewport's draw data.

## Implementation Examples

### Win32 and OpenGL 3 Setup

For Windows applications using OpenGL, initialize both the platform and renderer support:

```cpp
// Initialization
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;

ImGui_ImplWin32_Init(hwnd);
ImGui_ImplOpenGL3_Init("#version 150");

// Main loop
while (running)
{
    MSG msg;
    while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    ImGui_ImplOpenGL3_NewFrame();
    ImGui_ImplWin32_NewFrame();
    ImGui::NewFrame();

    ImGui::ShowDemoWindow();

    ImGui::Render();
    ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

    if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
    {
        ImGui::UpdatePlatformWindows();
        ImGui::RenderPlatformWindowsDefault();
    }

    SwapBuffers(hDC);
}

```

### SDL2 and OpenGL 3 Setup

SDL2 follows an identical pattern with different initialization calls:

```cpp
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;

ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
ImGui_ImplOpenGL3_Init("#version 150");

// Per-frame
ImGui_ImplSDL2_NewFrame(window);
ImGui_ImplOpenGL3_NewFrame();
ImGui::NewFrame();

// ... UI code ...

ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
    ImGui::UpdatePlatformWindows();
    ImGui::RenderPlatformWindowsDefault();
}

```

### Custom Platform Backend Skeleton

When writing a custom backend for an unsupported platform, populate the PlatformIO structure:

```cpp
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();

platform_io.Platform_CreateWindow = [](ImGuiViewport* vp) {
    // Create native window using OS API
};

platform_io.Platform_DestroyWindow = [](ImGuiViewport* vp) {
    // Destroy native window
};

platform_io.Platform_SetWindowPos = [](ImGuiViewport* vp, ImVec2 pos) {
    // Set native window position
};

platform_io.Platform_GetWindowPos = [](ImGuiViewport* vp) {
    // Return current position
};

// ... implement remaining callbacks ...

```

## Common Pitfalls

Several issues commonly prevent multi-viewport from functioning correctly:

**Missing Callbacks.** If the platform backend omits required PlatformIO functions, ImGui logs warnings to the console and secondary viewports fail to appear. Verify all function pointers are assigned in `ImGui::GetPlatformIO()`.

**DPI Scaling Errors.** On high-DPI displays, `Platform_GetWindowPos` and `Platform_GetWindowSize` must return values in **pixels**, not logical coordinates. Mismatched units cause viewports to appear at incorrect positions or scales.

**Input Routing.** Secondary viewports require event forwarding. The official backends automatically route mouse and keyboard events from all OS windows to ImGui, but custom implementations must manually call `ImGui::GetIO().AddMousePosEvent()` and equivalent functions for each viewport.

**Context Management.** OpenGL backends using multiple contexts require careful handling of `Platform_RenderWindow` and `Platform_SwapBuffers` callbacks. The default implementation in [`imgui_impl_opengl3.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_opengl3.cpp) manages context activation automatically, but custom renderers may need explicit `glMakeCurrent` calls.

## Summary

- Enable multi-viewport by setting `ImGuiConfigFlags_ViewportsEnable` in `ImGuiIO::ConfigFlags` immediately after context creation
- Ensure your platform backend implements all required `ImGuiPlatformIO` callbacks (create, destroy, move, resize native windows)
- Add `UpdatePlatformWindows()` and `RenderPlatformWindowsDefault()` calls to the end of your main render loop
- Official backends in [`backends/imgui_impl_win32.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_win32.cpp), [`backends/imgui_impl_glfw.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_glfw.cpp), and [`backends/imgui_impl_sdl2.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_sdl2.cpp) provide complete reference implementations
- Each viewport generates independent `ImDrawData` that your renderer must support drawing

## Frequently Asked Questions

### Why do secondary viewports not appear when I drag windows outside the main area?

Check that `ImGuiConfigFlags_ViewportsEnable` is actually set in the `ConfigFlags` before the first `NewFrame()` call. Also verify your platform backend implements all required `ImGuiPlatformIO` callbacks. Missing callbacks generate warning messages in the standard error output explaining which function is undefined.

### Do I need a special version of Dear ImGui to use multi-viewport?

Multi-viewport support is available in the master branch of the [ocornut/imgui](https://github.com/ocornut/imgui) repository. Earlier versions required the separate docking branch, but since docking merged into master, the feature is standard. Ensure you use a recent version that includes the `ImGuiPlatformIO` structure in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h).

### Can I use multi-viewport with my custom renderer?

Yes, provided your rendering code can accept and draw any `ImDrawData` instance, not just the main viewport's data. You must implement the PlatformIO callbacks for window management on your target OS, or use an existing platform backend while providing only the custom renderer. The rendering loop must call `RenderPlatformWindowsDefault()` to process secondary viewports.

### How does input handling work for secondary viewports?

The platform backend is responsible for routing input events from all native windows to ImGui. In [`backends/imgui_impl_glfw.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_glfw.cpp) and [`backends/imgui_impl_win32.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_win32.cpp), event handlers iterate over all viewports and translate OS events into ImGui's internal event queue using functions like `AddMousePosEvent()` and `AddKeyEvent()`. If writing a custom backend, ensure your window procedure or event loop handles messages for all created viewport windows, not just the main application window.