# Setting Up Multi-Viewport Support in Dear ImGui for Multiple Windows

> Learn to set up multi-viewport support in Dear ImGui. Make your ImGui windows native OS windows with simple flag and function calls for enhanced application flexibility.

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

---

**Enable the `ImGuiConfigFlags_ViewportsEnable` flag in your `ImGuiIO` configuration, ensure your platform backend supports viewport creation, and call `ImGui::UpdatePlatformWindows()` followed by `ImGui::RenderPlatformWindowsDefault()` in your render loop to allow Dear ImGui windows to exist as separate native OS windows.**

Dear ImGui (ocornut/imgui) supports rendering UI across multiple native operating system windows through its multi-viewport feature. When enabled, windows dragged outside the main application boundaries automatically spawn independent platform windows (HWND on Windows, X11/Wayland on Linux) while remaining part of a single unified ImGui context. This article explains the initialization steps, backend requirements, and rendering procedures required to implement multi-viewport support based on the current master and docking branch source code.

## Enable the Multi-Viewport Configuration Flag

Multi-viewport support begins with setting a single configuration flag immediately after creating your ImGui context. In [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) (lines 1710-1724), the `ImGuiConfigFlags_ViewportsEnable` enum value is defined to activate the feature.

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

```

Without this flag, all ImGui windows remain contained within the bounds of your single main application window regardless of their position.

## Viewport Object Lifecycle and the Primary Viewport

Once the flag is enabled, ImGui allocates viewport objects using the internal `ImGuiViewportP` structure. In [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) at line 4483, the primary viewport is created using `IM_NEW`:

```cpp
ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)();

```

This object is stored in the global `g.Viewports` vector. You can retrieve the primary viewport at any time using `ImGui::GetMainViewport()`, implemented in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) at line 16052. This viewport owns the main rendering context and typically corresponds to your application's initial OS window.

## Dynamic Window-to-Viewport Association

When a user drags an ImGui window outside the main work area, the framework automatically manages viewport creation. The function `ImGui::SetWindowViewport()`, found in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) at line 16058, binds the window to a new viewport object and updates the window's position via `window->Viewport->Pos`.

This process is transparent to user code; ImGui handles the platform window creation and destruction as windows move between monitors or back into the main viewport.

## Backend Requirements for Platform Window Management

Each platform backend (Win32, GLFW, SDL) must implement specific callbacks to support secondary viewports. The Win32 backend implementation in [`imgui_impl_win32.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_win32.cpp) (see the comment at line 139) emphasizes that the **docking** branch contains the necessary multi-viewport code.

Required backend responsibilities include:

- **Window creation/destruction**: Spawning actual OS windows when viewports are requested
- **Event forwarding**: Routing mouse and keyboard events to the correct viewport via `io.AddMouseViewportEvent()`
- **Rendering context management**: Ensuring each viewport has access to the graphics device context

The GLFW and SDL backends provide similar implementations in [`imgui_impl_glfw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_glfw.cpp) and [`imgui_impl_sdl.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_sdl.cpp) respectively.

## Rendering Across Multiple Viewports

During your render loop, you must explicitly update and render secondary viewports. The standard pattern involves calling two specific functions after your main `ImGui::Render()`:

```cpp
ImGui::Render();  // Renders main viewport

if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
    ImGui::UpdatePlatformWindows();        // Create/update platform windows
    ImGui::RenderPlatformWindowsDefault(); // Render secondary viewports
}

```

Internally, `UpdateViewportsNewFrame()` iterates over `g.Viewports` (including the primary one) and prepares draw data. Each viewport's draw data stores an `OwnerViewport` pointer (referenced in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) at line 5957) to ensure rendering commands target the correct window.

## Advanced Viewport API and Native Handles

For advanced use cases such as embedding ImGui into existing native windows, you can access platform-specific handles. Each `ImGuiViewport` contains a `void* PlatformHandleRaw` field (defined in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) lines 660-665) that backends fill with the native window handle (HWND, Window, etc.).

You can also draw directly onto specific viewports using `ImGui::GetForegroundDrawList(viewport)`, implemented in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) at lines 5309-5311:

```cpp
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
ImDrawList* draw_list = ImGui::GetForegroundDrawList(main_viewport);
draw_list->AddText(ImVec2(10, 10), IM_COL32_WHITE, "Overlay text");

```

## Complete Implementation Example

The following example demonstrates a complete Win32/OpenGL setup with multi-viewport support enabled:

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

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

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

    // Your UI code - windows can be dragged out to new OS windows
    ImGui::Begin("Main Window");
    ImGui::Text("Drag this window outside the main area");
    ImGui::End();

    ImGui::Begin("Secondary Window");
    ImGui::Text("I can become my own OS window!");
    ImGui::End();

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

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

```

To manually create a secondary viewport for embedding (rare but useful for advanced integration):

```cpp
ImGuiViewport* secondary = ImGui::CreateViewport();
secondary->Pos = ImVec2(800, 100);
secondary->Size = ImVec2(400, 300);
secondary->Flags = ImGuiViewportFlags_NoTaskBarIcon;
secondary->PlatformHandleRaw = (void*)my_native_hwnd;  // Your existing window handle

```

## Summary

Key implementation details for multi-viewport support in Dear ImGui:

- Set `ImGuiConfigFlags_ViewportsEnable` in `io.ConfigFlags` immediately after context creation, as defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)
- The primary viewport is allocated via `IM_NEW` in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) and accessible through `GetMainViewport()`
- Windows automatically trigger new viewport creation via `SetWindowViewport()` when dragged outside the main area
- Platform backends (Win32, GLFW, SDL) must implement window creation and event forwarding; the docking branch contains the required implementations
- Call `UpdatePlatformWindows()` and `RenderPlatformWindowsDefault()` in your render loop to service secondary viewports
- Access native window handles through `PlatformHandleRaw` for custom embedding scenarios

## Frequently Asked Questions

### How do I enable multi-viewport support in Dear ImGui?

Add the `ImGuiConfigFlags_ViewportsEnable` flag to your `ImGuiIO::ConfigFlags` immediately after calling `ImGui::CreateContext()`. This flag is defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) and triggers the internal viewport management system. Without this flag, all ImGui windows remain constrained to the main application window regardless of their position.

### What backends support multi-viewport functionality?

The official Win32, GLFW, and SDL backends support multi-viewport in the docking branch. The Win32 backend at [`imgui_impl_win32.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_win32.cpp) (line 139) specifically notes that the docking branch is required for this feature. Your backend must implement platform window creation, destruction, and event routing to handle secondary viewports properly.

### Why are my windows not creating separate OS windows when dragged outside?

Ensure you are calling both `ImGui::UpdatePlatformWindows()` and `ImGui::RenderPlatformWindowsDefault()` in your main loop after `ImGui::Render()`. Also verify that your backend implementation supports viewports—some minimal backend examples do not implement the required platform window callbacks. Finally, check that `ImGuiConfigFlags_ViewportsEnable` is actually set in your configuration flags before the first frame.

### How do I render content directly to a specific viewport?

Use `ImGui::GetForegroundDrawList(viewport)` and pass the desired `ImGuiViewport*` pointer, or use `ImGui::SetNextWindowViewport(viewport_id)` before creating a window. The `PlatformHandleRaw` field in `ImGuiViewport` (lines 660-665 in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp)) provides access to the native window handle for platform-specific rendering integration.