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

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 (lines 1710-1724), the ImGuiConfigFlags_ViewportsEnable enum value is defined to activate the feature.

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 at line 4483, the primary viewport is created using IM_NEW:

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 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 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 (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 and 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():

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 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 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 at lines 5309-5311:

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:

// 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):

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
  • The primary viewport is allocated via IM_NEW in 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 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 (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) provides access to the native window handle for platform-specific rendering integration.

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 →