# Implementing Docking Windows with the Dear ImGui Docking Branch: A Complete Guide

> Learn to implement docking windows with the Dear ImGui docking branch. Master workspace arrangements for professional UIs using the DockBuilder API.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: tutorial
- Published: 2026-07-14

---

**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`](https://github.com/ocornut/imgui/blob/main/imgui.h) and implemented in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/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`](https://github.com/ocornut/imgui/blob/main/imgui.h) (around line 1210), the flag is defined as:

```cpp
enum ImGuiConfigFlags_ {
    // ...
    ImGuiConfigFlags_DockingEnable = 1 << 6,
    // ...
};

```

Enable it during initialization:

```cpp
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`](https://github.com/ocornut/imgui/blob/main/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:

```cpp
// 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 `ImGuiID` can be generated from any stable string using `ImGui::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_NoDocking` to prevent itself from being docked into other windows, while the `DockSpace` inside accepts docked children.

## Programmatic Layout Control with DockBuilder

The **DockBuilder API** (implemented around line 17820 in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/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**

```cpp
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`](https://github.com/ocornut/imgui/blob/main/imgui_impl_glfw.cpp) or similar) and works seamlessly with the docking system.

Update your main loop to handle multiple viewports:

```cpp
// 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`](https://github.com/ocornut/imgui/blob/main/imgui.ini)). This persistence includes:

- Window positions and sizes
- Dock node splits and ratios
- Tab bar ordering

To load a specific layout programmatically, use:

```cpp
ImGui::LoadIniSettingsFromMemory(ini_data, ini_size);
// or
ImGui::LoadIniSettingsFromDisk("custom_layout.ini");

```

## Complete Implementation Example

This self-contained example demonstrates a full docking implementation:

```cpp
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_DockingEnable` in `ImGuiIO::ConfigFlags` before the first frame, as defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h).
- **Create a container** using `ImGui::DockSpace()` from [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) with a unique `ImGuiID` inside a host window.
- **Define layouts** using the `DockBuilder` API (`DockBuilderSplitNode`, `DockBuilderDockWindow`, etc.) to create deterministic split views.
- **Support multi-viewport dragging** by enabling `ImGuiConfigFlags_ViewportsEnable` and updating platform windows after rendering.
- **Persist configurations** automatically via the `.ini` file system or manually using `SaveIniSettingsToDisk()`.

## 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`](https://github.com/ocornut/imgui/blob/main/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`](https://github.com/ocornut/imgui/blob/main/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`](https://github.com/ocornut/imgui/blob/main/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`](https://github.com/ocornut/imgui/blob/main/imgui_impl_glfw.cpp) or [`imgui_impl_win32.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_win32.cpp)) supports multi-viewport rendering.