# How to Implement Multi-Viewport Support in Dear ImGui: Complete Setup Guide

> Master multi-viewport support in Dear ImGui with this guide. Learn to enable viewports, implement platform callbacks, and render secondary windows for enhanced UI flexibility.

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

---

**Enable multi-viewport support in Dear ImGui by setting `ImGuiConfigFlags_ViewportsEnable` in your ImGuiIO configuration, ensuring your platform backend implements viewport-specific callbacks, and calling `ImGui::UpdatePlatformWindows()` followed by `ImGui::RenderPlatformWindowsDefault()` after your main render loop to handle secondary OS windows.**

Dear ImGui, maintained by ocornut/imgui, supports rendering UI elements across multiple native operating system windows through its **multi-viewport** feature. When activated, this allows ImGui windows to be dragged outside the main application window into independent floating OS windows while maintaining full interactivity and input routing. Implementing this feature requires specific configuration flags, backend cooperation for platform window management, and proper integration into your render loop.

## What is Multi-Viewport Support?

Multi-viewport support allows Dear ImGui to render its UI onto several native OS windows simultaneously. Internally, each viewport is represented by an `ImGuiViewport` object that owns a platform-specific window (HWND on Windows, X11/Wayland window on Linux, or NSWindow on macOS). When the `ImGuiConfigFlags_ViewportsEnable` flag is active, ImGui creates a **primary viewport** (the one that owns the main rendering context) and, on demand, additional **secondary viewports** for any ImGui window dragged outside the main window boundaries.

According to the source code in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp), the primary viewport object is allocated with `IM_NEW` during the first frame and stored in the global viewport list `g.Viewports`, later returned by `GetMainViewport()`【https://github.com/ocornut/imgui/blob/master/imgui.cpp#L4483】【https://github.com/ocornut/imgui/blob/master/imgui.cpp#L16052】.

## Enabling Multi-Viewport Support

### Setting the Configuration Flag

After creating the ImGui context, you must enable the viewport flag in your ImGuiIO configuration before the first frame. This flag is defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) within the `ImGuiConfigFlags_` enum at lines 1710–1724【https://github.com/ocornut/imgui/blob/master/imgui.h#L1710-L1724】.

```cpp
// After ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;   // Enables multi-viewport support

```

### Platform Backend Requirements

Each platform backend (Win32, GLFW, SDL, etc.) must implement window creation, destruction, and event forwarding for secondary viewports. The Win32 backend implementation in [`backends/imgui_impl_win32.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_win32.cpp) specifically notes that the **docking** branch contains the multi-viewport code required for this functionality【https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_win32.cpp#L139】.

Backends typically register callbacks such as `io.AddMouseViewportEvent()` to route mouse input to the correct viewport. Without backend support, the configuration flag alone will not create native OS windows.

## Rendering Multiple Viewports

### Primary and Secondary Viewport Management

When a window is dragged outside the main work area, `ImGui::SetWindowViewport` binds the window to a new viewport object and updates its position via `window->Viewport->Pos`【https://github.com/ocornut/imgui/blob/master/imgui.cpp#L16058】. During `ImGui::Render()`, the function `UpdateViewportsNewFrame()` iterates over `g.Viewports` (including the primary one) and prepares draw data for each viewport, stored in `draw_data->OwnerViewport`【https://github.com/ocornut/imgui/blob/master/imgui.cpp#L5957】.

### The Viewport Update and Render Loop

You must explicitly update and render secondary viewports after your main ImGui render call. This ensures platform windows are created and drawn correctly.

```cpp
// Standard frame begin
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplWin32_NewFrame();  // Or your platform backend
ImGui::NewFrame();

// Your UI code here
ImGui::Begin("My Window");
ImGui::Text("Drag me outside the main window!");
ImGui::End();

// Standard rendering
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

// Multi-viewport specific: Update and render secondary viewports
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
    ImGui::UpdatePlatformWindows();         // Create/update platform windows
    ImGui::RenderPlatformWindowsDefault();  // Render secondary viewports
}

```

## Accessing Viewport Data and Native Handles

You can query the main viewport using `ImGui::GetMainViewport()` to position windows relative to the primary monitor. For direct rendering to a specific viewport, use `ImGui::GetForegroundDrawList(viewport)`【https://github.com/ocornut/imgui/blob/master/imgui.cpp#L5309-L5311】.

For advanced use cases such as native window embedding, each `ImGuiViewport` contains a `void* PlatformHandleRaw` field that backends fill with the native window handle, replacing the older `ImeWindowHandle` field【https://github.com/ocornut/imgui/blob/master/imgui.cpp#L660-L665】.

## Complete Implementation Example

Here is a complete initialization and render loop example using the Win32 and OpenGL3 backends:

```cpp
// 1. Setup
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;  // Enable multi-viewport

// 2. Initialize backends
ImGui_ImplWin32_Init(hwnd);
ImGui_ImplOpenGL3_Init("#version 130");

// 3. Main loop
while (running)
{
    // Start frame
    ImGui_ImplOpenGL3_NewFrame();
    ImGui_ImplWin32_NewFrame();
    ImGui::NewFrame();

    // Create UI that can be dragged to new OS windows
    ImGui::Begin("Draggable Window");
    ImGui::Text("This window can become a native OS window");
    if (ImGui::Button("Click Me")) { /* ... */ }
    ImGui::End();

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

    // Handle multi-viewport rendering
    if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
    {
        ImGui::UpdatePlatformWindows();
        ImGui::RenderPlatformWindowsDefault();
    }
}

```

## Summary

- Enable `ImGuiConfigFlags_ViewportsEnable` in your `ImGuiIO` configuration immediately after calling `ImGui::CreateContext()`
- Ensure your platform backend (Win32, GLFW, SDL, etc.) supports viewport-specific window management, as the Win32 implementation does in [`backends/imgui_impl_win32.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_win32.cpp)
- Call `ImGui::UpdatePlatformWindows()` and `ImGui::RenderPlatformWindowsDefault()` after your main `ImGui::Render()` loop to process secondary viewports
- Access viewport-specific draw lists using `ImGui::GetForegroundDrawList(viewport)` to render directly to specific OS windows
- Query native window handles through the `PlatformHandleRaw` member of `ImGuiViewport` for platform-specific integration or embedding

## Frequently Asked Questions

### Does multi-viewport support work on all operating systems?

Yes. As implemented in ocornut/imgui, multi-viewport support functions across Windows, Linux, and macOS provided your platform backend implements the required viewport management callbacks. The Win32 backend in [`backends/imgui_impl_win32.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_win32.cpp) and GLFW backend in [`backends/imgui_impl_glfw.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_glfw.cpp) both provide complete implementations for creating platform windows and forwarding input events.

### Why do my ImGui windows not create separate OS windows when dragged outside?

This occurs when `ImGuiConfigFlags_ViewportsEnable` is not set in `io.ConfigFlags` before the first call to `ImGui::NewFrame()`, or when your platform backend lacks the viewport-specific implementations. Verify that you are using a backend from the docking branch that includes the `UpdatePlatformWindows()` and `RenderPlatformWindowsDefault()` functions, and that you are calling these functions in your render loop.

### Can I manually create viewports for embedding native windows?

Yes. According to the source code in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp), you can instantiate `ImGuiViewport` objects directly and assign native window handles to the `PlatformHandleRaw` field. This allows you to render ImGui content into existing OS windows or embedded views rather than relying on automatic window creation when dragging.

### What is the performance impact of enabling multi-viewport support?

The CPU overhead within ImGui is minimal because the library batches draw commands per viewport during `UpdateViewportsNewFrame()`. Each viewport maintains its own draw data accessible via `draw_data->OwnerViewport`. However, each secondary viewport consumes additional OS resources (HWND, X11 window, etc.), incurring standard platform-level window management costs proportional to the number of floating windows.