How to Implement Multi-Viewport Support in Dear ImGui: Complete Setup Guide
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, 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 within the ImGuiConfigFlags_ enum at lines 1710–1724【https://github.com/ocornut/imgui/blob/master/imgui.h#L1710-L1724】.
// 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 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.
// 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:
// 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_ViewportsEnablein yourImGuiIOconfiguration immediately after callingImGui::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 - Call
ImGui::UpdatePlatformWindows()andImGui::RenderPlatformWindowsDefault()after your mainImGui::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
PlatformHandleRawmember ofImGuiViewportfor 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 and GLFW backend in 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, 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.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →