How to Enable the Dear ImGui Docking System in Your Application

To enable Dear ImGui docking, set io.ConfigFlags |= ImGuiConfigFlags_DockingEnable before creating your context, then create a dock space using ImGui::DockSpace() or ImGui::DockSpaceOverViewport() each frame.

Dear ImGui (ocornut/imgui) includes an advanced docking system that allows users to drag, dock, and tab windows within a host space. This feature transforms floating tool windows into a professional, integrated layout similar to modern game engines and IDEs.

Prerequisites and Configuration

Enabling the Docking Flag

You must enable docking at initialization time by modifying the ImGuiIO configuration flags. According to the source code in imgui.h (around line 1279), you set the ImGuiConfigFlags_DockingEnable bit before calling NewFrame():

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

This flag triggers the allocation of an ImGuiDockContext structure (defined in imgui_internal.h near line 2150) that tracks all dock nodes and their hierarchy. Without this flag, the docking API functions exist but will not create or manage dock nodes.

Optional Multi-Viewport Support

For docking across multiple OS-level windows, combine the docking flag with ImGuiConfigFlags_ViewportsEnable:

io.ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_ViewportsEnable;

This integration, implemented in imgui_viewports.cpp, allows docked panels to be dragged outside the main window to form independent viewports.

Creating the Dock Space

Using DockSpaceOverViewport (Simpler)

The DockSpaceOverViewport function provides the quickest setup. As implemented in imgui.cpp (around line 16130), this creates a dock space that fills the specified viewport:

ImGui::NewFrame();
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport());
// Your windows here...
ImGui::Render();

This handles the background window creation automatically, making it ideal for full-screen docking layouts.

Manual DockSpace Setup (More Control)

For custom layouts, explicitly create a host window and call ImGui::DockSpace():

static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;

const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->Pos);
ImGui::SetNextWindowSize(viewport->Size);
ImGui::SetNextWindowViewport(viewport->ID);
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
                ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;

ImGui::Begin("##DockSpace", nullptr, window_flags);
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
ImGui::End();

The dockspace_id returned from GetID() serves as the anchor where windows can attach. Each ImGuiWindow stores its target dock node in the DockId field (part of the ImGuiWindow structure in imgui_internal.h).

Customizing Docking Behavior

Input Modifiers

Control how docking interactions behave using the IO configuration:

io.ConfigDockingWithShift = true; // Require Shift key for docking
io.ConfigDockingTransparentPayload = true; // Show window contents while dragging

Dock Node Flags

When calling DockSpace, pass flags to restrict behavior:

  • ImGuiDockNodeFlags_NoResize: Prevent manual resizing of splits
  • ImGuiDockNodeFlags_AutoHideTabBar: Hide tabs when only one window is docked
  • ImGuiDockNodeFlags_PassthruCentralNode: Central node is transparent (useful for full-screen game views)

Programmatic Layout Control

To define specific layouts programmatically rather than relying on user interaction, use the Dock Builder API. This code checks if a layout exists and constructs a split hierarchy:

if (ImGui::DockBuilderGetNode(dockspace_id) == nullptr)
{
    ImGui::DockBuilderRemoveNode(dockspace_id); // Clear existing layout
    ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_None);
    
    ImGuiID dock_main_id = dockspace_id;
    ImGuiID dock_left_id = ImGui::DockBuilderSplitNode(
        dock_main_id, ImGuiDir_Left, 0.25f, nullptr, &dock_main_id);
    
    ImGui::DockBuilderDockWindow("##MyLeftPanel", dock_left_id);
    ImGui::DockBuilderDockWindow("##MyMainPanel", dock_main_id);
    ImGui::DockBuilderFinish(dockspace_id);
}

DockBuilderSplitNode divides a node horizontally or vertically, returning the new child ID through the out parameter. DockBuilderDockWindow assigns specific windows to nodes by name.

How Docking Works Under the Hood

Behind the scenes, the docking system manages several key data structures:

  1. ImGuiDockContext: A per-context structure allocated when ImGuiConfigFlags_DockingEnable is set. It maintains a hash map of ImGuiDockNode instances indexed by ID.

  2. Dock Nodes: Each ImGuiDockNode (defined in imgui_internal.h) represents a split container or tab bar. Nodes track their parent/child relationships, split ratios, and hosted windows.

  3. Window Attachment: When Begin() is called on a window with a non-zero DockId, the system looks up the corresponding node in the dock context. If the window is being dragged, the system evaluates mouse position against node split boundaries to determine docking targets.

  4. Serialization: Node layouts persist across frames through the .ini file system, storing the hierarchy and window assignments (unless ImGuiDockNodeFlags_NoSavedSettings is set).

Summary

  • Enable docking by setting ImGuiConfigFlags_DockingEnable in io.ConfigFlags before the first frame
  • Call ImGui::DockSpaceOverViewport() for automatic full-screen docking, or ImGui::DockSpace() for manual host windows
  • Store the returned ImGuiID to reference specific dock nodes for programmatic layout
  • Use the Dock Builder API (DockBuilderSplitNode, DockBuilderDockWindow) to create predefined layouts
  • Reference imgui.h for public flags, imgui_internal.h for node structures, and imgui.cpp for the core implementation
  • Disable docking entirely at compile time via IMGUI_DISABLE_DOCKING in imconfig.h

Frequently Asked Questions

What is the difference between DockSpace and DockSpaceOverViewport?

DockSpaceOverViewport is a convenience wrapper that creates a full-screen background window and calls DockSpace internally, while DockSpace requires you to create and manage the host window manually. Use DockSpaceOverViewport for simple full-screen docking; use DockSpace when you need the dock area to occupy only a portion of your UI or require specific window flags.

Why are my windows not docking after enabling the flag?

Ensure you are creating a dock space every frame. Docking only works when a visible dock node exists to receive the window. If you enabled ImGuiConfigFlags_DockingEnable but forgot to call DockSpace() or DockSpaceOverViewport(), windows will remain floating. Also verify you are not passing ImGuiWindowFlags_NoDocking to your windows.

How do I save and restore docking layouts?

Dear ImGui automatically serializes docking layouts to the ini file. The dock node hierarchy and window assignments persist between sessions by default. To manually save/restore specific layouts, use the Dock Builder API to capture node IDs and reconstruct the splits, or use DockBuilderCopyWindowSettings to clone layouts between dock spaces.

Can I disable docking at compile time?

Yes, via imconfig.h. Define IMGUI_DISABLE_DOCKING before including imgui headers to remove all docking-related code and data structures. This reduces binary size for applications that do not need the feature, eliminating the ImGuiDockContext allocation and associated processing overhead.

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 →