How to Implement Multi-Window and Multi-Viewport in Dear ImGui
To enable multi-viewport support in Dear ImGui, set io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable, ensure your backend supports ImGuiBackendFlags_PlatformHasViewports, and call ImGui::UpdatePlatformWindows() followed by ImGui::RenderPlatformWindowsDefault() after your main render loop.
Dear ImGui (ocornut/imgui) can render multiple OS-level windows—called viewports—from a single ImGui context. This feature allows users to drag ImGui windows outside the main application boundary, creating native platform windows dynamically. Implementing multi-window and multi-viewport in ImGui requires specific configuration flags, backend support, and explicit rendering steps in your application loop.
Understanding the Multi-Viewport Architecture
Core Components and Configuration
The multi-viewport system relies on three primary structures defined in imgui.h:
-
ImGuiIO::ConfigFlags– SettingImGuiConfigFlags_ViewportsEnable(declared around lines 213–218) activates the feature at runtime. Without this flag, ImGui operates in single-window mode regardless of backend capabilities. -
ImGuiViewport– This struct (defined at lines 4017–4038 inimgui.h) represents a platform window. It stores size, position, DPI scale, and the platform-specific handle (PlatformHandle) such as anHWNDon Windows orGLFWwindow*on GLFW. -
ImGuiBackendFlags– Backends signal viewport support throughImGuiBackendFlags_PlatformHasViewportsand optionallyImGuiBackendFlags_RendererHasViewports(lines 4420–4425 inimgui.h). The platform backend creates and manages native windows, while the renderer backend handles the GPU resources for each viewport.
Platform Backend Responsibilities
Platform-specific code lives entirely within the backends. Files like backends/imgui_impl_glfw.cpp and backends/imgui_impl_win32.cpp implement the required platform-window callbacks:
- Creating native windows when a viewport is spawned
- Updating window position, size, and DPI scale
- Forwarding mouse and keyboard events to the correct viewport
This decoupling ensures ImGui core never touches graphics APIs or OS window systems directly.
The Rendering Lifecycle with Viewports
When viewports are enabled, the render loop expands beyond the standard ImGui::Render() call. According to the implementation in imgui.cpp (lines 7756–7770), the lifecycle becomes:
- Update –
ImGui::UpdatePlatformWindows()creates or updates extra OS windows - Render –
ImGui::RenderPlatformWindowsDefault()generates draw data for each viewport - Present – Each viewport's draw data is submitted to the GPU
Implementation Guide
Enabling Viewport Support
Activate the feature immediately after creating the ImGui context:
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
Without this flag, the viewport functions exist but remain inactive, and all windows render within the main application window.
Complete GLFW and OpenGL3 Example
This minimal implementation demonstrates the full integration:
#include "imgui.h"
#include "backends/imgui_impl_glfw.h"
#include "backends/imgui_impl_opengl3.h"
#include <GLFW/glfw3.h>
int main()
{
// Initialize GLFW and create main window
glfwInit();
GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui Viewports", nullptr, nullptr);
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
// Create ImGui context and enable viewports
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
// Initialize backends
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init("#version 130");
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
// Start frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// UI code - windows can be dragged out to become OS windows
ImGui::Begin("Demo Window");
ImGui::Text("Drag this title bar outside the main window");
ImGui::End();
// Render main viewport
ImGui::Render();
int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
// Handle additional viewports
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
}
glfwSwapBuffers(window);
}
// Cleanup
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
The critical additions are UpdatePlatformWindows() and RenderPlatformWindowsDefault() after the standard render call. The same OpenGL3 backend handles all viewports automatically—no additional renderer code is required.
Custom Backend Integration
If implementing a custom platform or renderer (such as for WGPU or a proprietary engine), you must provide callback functions through ImGuiPlatformIO:
// Platform callbacks
void MyPlatform_CreateWindow(ImGuiViewport* vp);
void MyPlatform_DestroyWindow(ImGuiViewport* vp);
void MyPlatform_SetWindowPos(ImGuiViewport* vp, ImVec2 pos);
void MyPlatform_GetWindowPos(ImGuiViewport* vp, ImVec2* out_pos);
void MyPlatform_SetWindowSize(ImGuiViewport* vp, ImVec2 size);
// Renderer callback
void MyPlatform_RenderWindow(ImGuiViewport* vp, ImDrawData* draw_data);
Register these callbacks after initializing your backend:
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Platform_CreateWindow = MyPlatform_CreateWindow;
platform_io.Platform_DestroyWindow = MyPlatform_DestroyWindow;
platform_io.Platform_SetWindowPos = MyPlatform_SetWindowPos;
platform_io.Platform_GetWindowPos = MyPlatform_GetWindowPos;
platform_io.Platform_SetWindowSize = MyPlatform_SetWindowSize;
platform_io.Platform_RenderWindow = MyPlatform_RenderWindow;
Once registered, ImGui::UpdatePlatformWindows() and ImGui::RenderPlatformWindowsDefault() will invoke your implementations for each active viewport.
Key Source Files and References
imgui.h– ContainsImGuiViewportdefinition,ImGuiConfigFlags_ViewportsEnable, andImGuiBackendFlagsenumimgui.cpp– ImplementsUpdatePlatformWindows()andRenderPlatformWindowsDefault()around lines 7756–7770backends/imgui_impl_glfw.cpp– GLFW platform implementation creating nativeGLFWwindow*objects for viewportsbackends/imgui_impl_win32.cpp– Windows platform implementation usingHWNDfor viewport windowsbackends/imgui_impl_opengl3.cpp– OpenGL renderer supporting multiple viewport framebuffersexamples/example_glfw_opengl3/main.cpp– Reference implementation showing viewports in practicedocs/BACKENDS.md– Official documentation listing which backends support the multi-viewport feature
Summary
- Enable viewports by setting
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnableimmediately after creating the context - Verify backend support – Your platform backend must set
ImGuiBackendFlags_PlatformHasViewportsinio.BackendFlags - Add viewport rendering – Call
ImGui::UpdatePlatformWindows()andImGui::RenderPlatformWindowsDefault()after your mainRender()call - Handle DPI scaling – Each
ImGuiViewportstores its ownScalefield; queryImGui::GetMainViewport()->WorkPosfor positioning - Test by dragging – Any ImGui window can become a separate OS window by dragging its title bar outside the main window bounds
Frequently Asked Questions
What backends support multi-viewport in Dear ImGui?
The official GLFW, Win32, and SDL2 platform backends support multi-viewport when ImGuiBackendFlags_PlatformHasViewports is set. The OpenGL3, DirectX 11/12, and Vulkan renderers support multi-viewport rendering. Check docs/BACKENDS.md in the repository for the current support matrix, as third-party backends vary in viewport capability.
Why won't my ImGui window detach into a separate OS window?
First, verify that io.ConfigFlags includes ImGuiConfigFlags_ViewportsEnable before calling NewFrame(). Second, confirm your backend sets ImGuiBackendFlags_PlatformHasViewports during initialization. Finally, ensure you are calling both ImGui::UpdatePlatformWindows() and ImGui::RenderPlatformWindowsDefault() in your render loop—missing either prevents viewport creation or rendering.
Can I implement multi-viewport with a custom game engine renderer?
Yes, but you must implement the ImGuiPlatformIO callbacks. Your platform layer needs to create and destroy native windows, handle window movement and resizing, and forward input events. Your renderer must output to the correct framebuffer or swapchain for each viewport's PlatformHandle. Reference imgui_impl_win32.cpp for a complete implementation pattern.
Does multi-viewport work with docking enabled?
Yes. The docking branch (and later merged versions) integrates seamlessly with multi-viewport. When both features are enabled, docked windows remain within their containing viewport, while dragging a window tab outside any viewport boundary automatically creates a new OS-level window. The ImGuiViewport struct tracks the parent-child relationships through the ParentViewportId field.
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 →