How to Manage ImGui Docking and Tab Windows: A Complete Guide to the Built-In Docking System

Enable ImGuiConfigFlags_DockingEnable in the ImGuiIO configuration, create a host dock space with ImGui::DockSpace(), and use ImGuiTabBarFlags_DockingEnable when building tab bars so that windows and tabs can be dragged, split, and persisted between sessions.

Dear ImGui (ocornut/imgui) ships with a built-in docking system that lets you create IDE-style layouts without external dependencies. Learning how to manage ImGui docking and tab windows starts with three configuration and API calls that activate dock nodes, host spaces, and tab grouping. The entire implementation is compiled from the master branch and exposed through headers and functions found in imgui.h and imgui.cpp.

Enable Docking with ImGuiConfigFlags_DockingEnable

Set the flag on the IO object during setup. This flag is declared in imgui.h and activates the docking code path compiled under the IMGUI_HAS_DOCK preprocessor guard.

ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;

Create a Dock Space Host Window

Call ImGui::DockSpace() inside a host window to allocate a region that receives dockable windows. The convenience wrapper ImGui::DockSpaceOverViewport() is also available. In imgui.cpp, the DockSpace() implementation handles node allocation and layout resolution.

ImGui::Begin("MainDockSpace", nullptr,
             ImGuiWindowFlags_NoTitleBar |
             ImGuiWindowFlags_NoCollapse |
             ImGuiWindowFlags_NoResize |
             ImGuiWindowFlags_NoMove |
             ImGuiWindowFlags_NoBringToFrontOnFocus |
             ImGuiWindowFlags_NoNavFocus);
ImGuiID dockspace_id = ImGui::DockSpace(ImGui::GetID("MyDockSpace"));
ImGui::End();

Assign Windows to Specific Dock Nodes

After you have a dock node ID, use ImGui::SetNextWindowDockID() to force a window to open inside that node.

ImGui::SetNextWindowDockID(my_dock_id, ImGuiCond_Once);
ImGui::Begin("MyFixedPanel");
ImGui::Text("This window always starts docked in the same node.");
ImGui::End();

Program Default Layouts with the Dock Builder API

For tool-style applications, use the ImGui::DockBuilder* family declared in imgui.h and defined in imgui.cpp to split nodes and assign windows before the first frame.

ImGuiID dock_main = ImGui::GetID("MainDockSpace");
ImGui::DockBuilderRemoveNode(dock_main);
ImGui::DockBuilderAddNode(dock_main, ImGuiDockNodeFlags_None);
ImGui::DockBuilderSetNodeSize(dock_main, ImGui::GetMainViewport()->Size);

ImGuiID dock_left, dock_right;
dock_left = ImGui::DockBuilderSplitNode(dock_main, ImGuiDir_Left, 0.25f, nullptr, &dock_main);
dock_right = dock_main;

ImGui::DockBuilderDockWindow("LeftPanel", dock_left);
ImGui::DockBuilderDockWindow("RightPanel", dock_right);
ImGui::DockBuilderFinish(dock_main);

Build Tab Windows That Integrate with Docking

Tab bars participate in the docking system when you pass ImGuiTabBarFlags_DockingEnable. This lets users drag an entire tab group between dock slots.

ImGui::Begin("TabHost");
if (ImGui::BeginTabBar("MyTabBar", ImGuiTabBarFlags_DockingEnable)) {
    if (ImGui::BeginTabItem("Tab A")) {
        ImGui::Text("Content of Tab A");
        ImGui::EndTabItem();
    }
    if (ImGui::BeginTabItem("Tab B")) {
        ImGui::Text("Content of Tab B");
        ImGui::EndTabItem();
    }
    ImGui::EndTabBar();
}
ImGui::End();

Persist and Restore Docking Layouts

Docking hierarchies are written to the .ini file as [Dock][...] entries. Call ImGui::SaveIniSettingsToDisk() before shutdown and ImGui::LoadIniSettingsFromDisk() at startup.

ImGui::SaveIniSettingsToDisk("my_imgui_layout.ini");
// ...
ImGui::LoadIniSettingsFromDisk("my_imgui_layout.ini");

Key Source Files and Internal Architecture

The docking system relies on a few critical files in the ocornut/imgui repository. imgui.h contains the public flags and DockSpace() prototype, while imgui.cpp implements the core docking logic, layout persistence, and the DockBuilder* family. Internal structures such as ImGuiDockNode and ImGuiDockContext are defined in imgui_internal.h. You can find usage examples in examples/example_sdl2_opengl3/main.cpp and the interactive docking demo inside imgui_demo.cpp.

Summary

  • Enable docking globally by setting ImGuiConfigFlags_DockingEnable in ImGuiIO.
  • Host dockable panels inside a region created with ImGui::DockSpace() or ImGui::DockSpaceOverViewport().
  • Pin windows to nodes with ImGui::SetNextWindowDockID() or build default trees with the ImGui::DockBuilder* API.
  • Combine tabs into draggable groups by passing ImGuiTabBarFlags_DockingEnable to ImGui::BeginTabBar().
  • Persist layouts between sessions using ImGui::SaveIniSettingsToDisk() and ImGui::LoadIniSettingsFromDisk().

Frequently Asked Questions

Why is my dock space not interacting with windows?

Docking only activates if ImGuiConfigFlags_DockingEnable is set in the ImGuiIO object before the first frame, and if the host window containing ImGui::DockSpace() is submitted before the child windows. Verify that the dock space ID is consistent and that the host window uses correct flags such as ImGuiWindowFlags_NoNavFocus.

Can I dock windows without a user dragging them?

Yes. Use ImGui::SetNextWindowDockID() to place a single window, or use the ImGui::DockBuilder* API to split nodes and assign multiple windows to a default tree programmatically as implemented in imgui.cpp.

Do tab bars require a separate dock space to work?

No. Tab bars that use ImGuiTabBarFlags_DockingEnable live inside normal windows and participate in the same docking system. You can drag the entire tab group into any existing dock node because the tab bar integrates with the ImGuiDockContext structures defined in imgui_internal.h.

How do I reset the docking layout to the original default?

Call ImGui::DockBuilderRemoveNode() on your dock space ID before rebuilding the tree with ImGui::DockBuilderAddNode() and ImGui::DockBuilderDockWindow(). Alternatively, delete the saved .ini file and restart so that ImGui::LoadIniSettingsFromDisk() finds no prior state.

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 →