Implementing Docking Windows with the Dear ImGui Docking Branch: A Complete Guide
Enable ImGuiConfigFlags_DockingEnable in your ImGuiIO configuration before the first frame, create a host window containing ImGui::DockSpace(), and use the DockBuilder API to programmatically define split layouts for persistent, professional workspace arrangements.
The Dear ImGui docking system available in the ocornut/imgui repository transforms floating tool windows into a customizable, IDE-like workspace. Defined primarily in imgui.h and implemented in imgui.cpp, this feature allows developers to create split panels, tab groups, and multi-window layouts that persist across application sessions.
Enabling the Docking System
Docking is disabled by default. You must set the configuration flag in your ImGuiIO structure before calling ImGui::NewFrame() for the first time.
In imgui.h (around line 1210), the flag is defined as:
enum ImGuiConfigFlags_ {
// ...
ImGuiConfigFlags_DockingEnable = 1 << 6,
// ...
};
Enable it during initialization:
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
// Optional: Allow windows to be dragged outside the main viewport as native OS windows
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
Creating a DockSpace Container
A DockSpace is an invisible container that owns a screen region where other windows can dock. In imgui.cpp (around line 17270), the ImGui::DockSpace() function creates this container using an ImGuiID identifier.
Create a full-screen host window and embed a DockSpace inside it:
// Host window flags prevent it from being docked itself while filling the entire viewport
ImGuiWindowFlags host_flags =
ImGuiWindowFlags_NoTitleBar |
ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoDocking |
ImGuiWindowFlags_NoBringToFrontOnFocus |
ImGuiWindowFlags_NoNavFocus;
ImGui::Begin("DockSpace Host", nullptr, host_flags);
ImGuiID dockspace_id = ImGui::GetID("MyMainDockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_None);
ImGui::End();
Key Implementation Details:
- The
ImGuiIDcan be generated from any stable string usingImGui::GetID()or from a pointer constant. - Pass
ImVec2(0.0f, 0.0f)as the size to fill the entire parent window. - The host window typically uses
ImGuiWindowFlags_NoDockingto prevent itself from being docked into other windows, while theDockSpaceinside accepts docked children.
Programmatic Layout Control with DockBuilder
The DockBuilder API (implemented around line 17820 in imgui.cpp) allows you to define split layouts procedurally before the user interacts with them. This is essential for creating deterministic default layouts.
The builder uses an internal node tree stored in ImGuiContext::DockContext. Use these functions to construct layouts:
ImGui::DockBuilderRemoveNode(dockspace_id)– Clears existing layout data.ImGui::DockBuilderAddNode(dockspace_id, flags)– Creates a root node.ImGui::DockBuilderSplitNode(node_id, split_dir, split_ratio, &out_id_at_dir, &out_id_opposite_dir)– Splits a node vertically or horizontally.ImGui::DockBuilderDockWindow(window_name, node_id)– Assigns a window to a specific node.ImGui::DockBuilderFinish(dockspace_id)– Finalizes the layout construction.
Example: Creating a Left-Right Split with Tabs
static bool layout_initialized = false;
if (!layout_initialized)
{
ImGuiID dockspace_id = ImGui::GetID("MyMainDockSpace");
// Clear any existing layout
ImGui::DockBuilderRemoveNode(dockspace_id);
ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_None);
// Split the dockspace into left (30%) and right (70%) nodes
ImGuiID dock_left, dock_right;
ImGui::DockBuilderSplitNode(
dockspace_id,
ImGuiDir_Left,
0.30f,
&dock_left,
&dock_right
);
// Assign windows to specific dock nodes
ImGui::DockBuilderDockWindow("Scene Hierarchy", dock_left);
ImGui::DockBuilderDockWindow("Inspector", dock_right);
ImGui::DockBuilderDockWindow("Console", dock_right); // Will tab with Inspector
ImGui::DockBuilderFinish(dockspace_id);
layout_initialized = true;
}
Multi-Viewport Support
When you enable ImGuiConfigFlags_ViewportsEnable, docked windows can be dragged outside the main application window to become native OS windows. This requires platform backend support (implemented in imgui_impl_glfw.cpp or similar) and works seamlessly with the docking system.
Update your main loop to handle multiple viewports:
// After ImGui::Render()
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
}
Persisting User Layouts
Dear ImGui automatically serializes the docking state to the .ini file specified by io.IniFilename (default: imgui.ini). This persistence includes:
- Window positions and sizes
- Dock node splits and ratios
- Tab bar ordering
To load a specific layout programmatically, use:
ImGui::LoadIniSettingsFromMemory(ini_data, ini_size);
// or
ImGui::LoadIniSettingsFromDisk("custom_layout.ini");
Complete Implementation Example
This self-contained example demonstrates a full docking implementation:
void ShowDockingSpace()
{
ImGuiIO& io = ImGui::GetIO();
// Enable docking (do this once during app initialization)
if (!(io.ConfigFlags & ImGuiConfigFlags_DockingEnable))
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
static bool opt_fullscreen = true;
static bool opt_padding = false;
static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;
// Window flags for the host
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
if (opt_fullscreen)
{
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->WorkPos);
ImGui::SetNextWindowSize(viewport->WorkSize);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
}
if (!opt_padding)
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("DockSpace Demo", nullptr, window_flags);
if (!opt_padding)
ImGui::PopStyleVar();
if (opt_fullscreen)
ImGui::PopStyleVar(2);
// Submit the DockSpace
if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
{
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
}
// Create dockable windows
ImGui::Begin("Properties");
ImGui::Text("Camera settings...");
ImGui::End();
ImGui::Begin("Viewport");
ImGui::Text("Main 3D view...");
ImGui::End();
ImGui::End(); // DockSpace Host
}
Troubleshooting Common Issues
Windows float instead of docking: Verify that ImGuiConfigFlags_DockingEnable is set before the first ImGui::NewFrame() call. Check that the target window does not have ImGuiWindowFlags_NoDocking set unless you explicitly want to prevent docking for that specific window.
DockSpace does not fill the window: Ensure you call ImGui::SetNextWindowSize() with the viewport size before ImGui::Begin(), or use ImVec2(0.0f, 0.0f) as the size argument to ImGui::DockSpace().
Layout resets on restart: If the layout does not persist, confirm that io.IniFilename is not set to NULL and that you have write permissions to the working directory. The docking state saves automatically based on io.IniSavingRate.
Build errors referencing DockSpace: Ensure you are using the docking branch or a release version that includes docking (available in recent master versions). The ImGui::DockSpace() function is not present in non-docking builds.
Summary
- Enable docking by setting
ImGuiConfigFlags_DockingEnableinImGuiIO::ConfigFlagsbefore the first frame, as defined inimgui.h. - Create a container using
ImGui::DockSpace()fromimgui.cppwith a uniqueImGuiIDinside a host window. - Define layouts using the
DockBuilderAPI (DockBuilderSplitNode,DockBuilderDockWindow, etc.) to create deterministic split views. - Support multi-viewport dragging by enabling
ImGuiConfigFlags_ViewportsEnableand updating platform windows after rendering. - Persist configurations automatically via the
.inifile system or manually usingSaveIniSettingsToDisk().
Frequently Asked Questions
How do I enable docking in Dear ImGui?
Set the ImGuiConfigFlags_DockingEnable flag in your ImGuiIO configuration before the first call to ImGui::NewFrame(). In imgui.h, this flag is defined within the ImGuiConfigFlags_ enumeration. You must also ensure you are compiling against a version of Dear ImGui that supports docking (the docking branch or recent master).
What is the DockBuilder API used for?
The DockBuilder API provides procedural control over the docking layout, allowing you to programmatically split nodes, create tabs, and assign windows to specific docking zones. Functions like DockBuilderSplitNode() and DockBuilderDockWindow() (implemented in imgui.cpp) create the internal ImGuiDockNode tree structure that determines where windows appear.
How do I persist docking layouts between sessions?
Dear ImGui automatically saves docking layouts to the file specified by io.IniFilename (typically imgui.ini) whenever the IniSavingRate timer triggers or the context shuts down. To manually save or load layouts, use ImGui::SaveIniSettingsToDisk() or ImGui::LoadIniSettingsFromDisk().
Why do my windows fail to dock into the DockSpace?
Verify that the ImGuiConfigFlags_DockingEnable flag is active and that your windows are created without the ImGuiWindowFlags_NoDocking flag. Additionally, ensure you are calling ImGui::Begin() for the windows after the ImGui::DockSpace() call in the same frame, and that the DockSpace is visible.
Can docked windows become separate native windows?
Yes, when you enable both ImGuiConfigFlags_DockingEnable and ImGuiConfigFlags_ViewportsEnable, users can drag docked tabs outside the main application window. This creates native OS windows automatically, provided your platform backend (such as imgui_impl_glfw.cpp or imgui_impl_win32.cpp) supports multi-viewport rendering.
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 →