# How to Implement Drag and Drop Between Widgets in Dear ImGui

> Learn to implement drag and drop between widgets in Dear ImGui. Use BeginDragDropSource and BeginDragDropTarget to easily transfer data between UI elements.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: how-to-guide
- Published: 2026-07-26

---

**Dear ImGui's drag and drop system uses `BeginDragDropSource()` and `BeginDragDropTarget()` to convert any widget into a data source or destination, with payloads identified by unique type strings.**

Dear ImGui provides a lightweight, state-driven drag and drop system that can turn any widget into a **drag source**, a **drop target**, or both simultaneously. According to the [ocornut/imgui](https://github.com/ocornut/imgui) source code, the entire mechanism is declared 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), allowing you to move arbitrary data between color buttons, list items, or tree nodes with minimal overhead.

## Core Drag and Drop API Stages

The system operates through a defined workflow that tracks the active drag, source ID, and payload buffer internally. Because ImGui copies payload data into its own storage, you can safely pass pointers to temporary variables without lifetime concerns.

### Starting a Drag Operation

Call `ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)` **immediately after** submitting the widget you want to make draggable. This function returns `true` when the user has initiated a drag (typically by holding the mouse button). Follow with `ImGui::SetDragDropPayload(const char* type, const void* data, size_t size, ImGuiCond cond)` to store your data under a custom type string (maximum 32 characters), then close the block with `ImGui::EndDragDropSource()`.

### Accepting a Drop Operation

To receive data, call `ImGui::BeginDragDropTarget()` **after** submitting the target widget. This returns `true` when a compatible payload is hovering over the item. Retrieve the payload using `ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags)`, which returns a pointer to an `ImGuiPayload` structure if the type matches. Always close with `ImGui::EndDragDropTarget()` when the function returns `true`.

## Example: Dragging Between Color Buttons

This example demonstrates exchanging color data between two buttons. The implementation in [`imgui_demo.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_demo.cpp) ([lines 1689-1703](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp#L1689-L1703)) illustrates this pattern.

```cpp
// Source widget
ImGui::ColorButton("##src", ImVec4(0.8f, 0.2f, 0.2f, 1.0f));
if (ImGui::BeginDragDropSource()) {
    ImVec4 color = ImVec4(0.8f, 0.2f, 0.2f, 1.0f);
    ImGui::SetDragDropPayload("DND_COLOR", &color, sizeof(color));
    ImGui::Text("Dragging color");
    ImGui::EndDragDropSource();
}

// Target widget
ImGui::SameLine();
ImGui::ColorButton("##dst", ImVec4(0.2f, 0.2f, 0.8f, 1.0f));
if (ImGui::BeginDragDropTarget()) {
    if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_COLOR")) {
        ImVec4* received = (ImVec4*)payload->Data;
        // Apply received color to your application state
    }
    ImGui::EndDragDropTarget();
}

```

The payload lives in ImGui's internal buffer until `EndDragDropSource()` is called, making it safe to use stack-allocated data as shown above.

## Advanced Pattern: Reordering Lists

For reordering list items, each element must serve as both source and target. The [`imgui_demo.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_demo.cpp) implementation ([lines 3495-3513](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp#L3495-L3513)) demonstrates swapping items by passing the source index as payload.

```cpp
for (int i = 0; i < MyList.Size; ++i) {
    ImGui::PushID(i);
    ImGui::Selectable(MyList[i].c_str());
    
    // Source
    if (ImGui::BeginDragDropSource()) {
        ImGui::SetDragDropPayload("DND_ITEM", &i, sizeof(i));
        ImGui::Text("Moving %s", MyList[i].c_str());
        ImGui::EndDragDropSource();
    }
    
    // Target
    if (ImGui::BeginDragDropTarget()) {
        if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_ITEM")) {
            int src_idx = *(int*)payload->Data;
            std::swap(MyList[src_idx], MyList[i]);
        }
        ImGui::EndDragDropTarget();
    }
    ImGui::PopID();
}

```

## Dragging Tree Nodes

Tree nodes can be re-parented by dragging them onto other nodes. The source supplies its own ID, allowing the target to modify the hierarchy when the payload is delivered.

```cpp
void ShowTreeNode(const char* label, int node_id) {
    ImGui::PushID(node_id);
    bool opened = ImGui::TreeNode(label);
    
    if (ImGui::BeginDragDropSource()) {
        ImGui::SetDragDropPayload("DND_TREENODE", &node_id, sizeof(node_id));
        ImGui::Text("Moving %s", label);
        ImGui::EndDragDropSource();
    }
    
    if (ImGui::BeginDragDropTarget()) {
        if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_TREENODE")) {
            int src_id = *(int*)payload->Data;
            AttachAsChild(src_id, node_id); // Your custom logic
        }
        ImGui::EndDragDropTarget();
    }
    
    if (opened) {
        // Render children recursively
        ImGui::TreePop();
    }
    ImGui::PopID();
}

```

## Key Implementation Files

Understanding where the drag and drop system lives helps when debugging or extending functionality:

- **[`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)** ([lines 73-84](https://github.com/ocornut/imgui/blob/master/imgui.h#L73-L84)): Declares `BeginDragDropSource`, `SetDragDropPayload`, `BeginDragDropTarget`, and `AcceptDragDropPayload`
- **[`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp)** ([lines 15037-15292](https://github.com/ocornut/imgui/blob/master/imgui.cpp#L15037-L15292)): Contains the core state machine implementation handling source/target detection and payload storage
- **[`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h)**: Defines `ImGuiPayload` and internal drag drop flags such as `ImGuiDragDropFlags_SourceNoPreviewTooltip`
- **[`imgui_demo.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_demo.cpp)**: Provides working examples including color exchange and list reordering

## Summary

- **Initiate drags** by calling `BeginDragDropSource()` after the widget and closing with `EndDragDropSource()`
- **Store data** using `SetDragDropPayload()` with a unique 32-character type identifier; ImGui copies and manages the memory internally
- **Receive data** by calling `BeginDragDropTarget()` then `AcceptDragDropPayload()` with matching type strings
- **Enable complex interactions** by making widgets dual-purpose sources and targets, using `PushID()`/`PopID()` to maintain stable identifiers
- **Reference the demo code** in [`imgui_demo.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_demo.cpp) for production-ready patterns

## Frequently Asked Questions

### What data types can I pass through a drag and drop payload?

You can pass any data type because `SetDragDropPayload()` accepts a `const void*` and size in bytes. The system copies your data into an internal buffer, so you can safely drag primitive types like `int` or `float`, structs like `ImVec4`, or complex objects. Ensure the type string uniquely identifies the data format so targets can cast the `payload->Data` pointer correctly.

### How do I hide the default tooltip during a drag operation?

Pass the `ImGuiDragDropFlags_SourceNoPreviewTooltip` flag to `BeginDragDropSource()`. By default, ImGui displays "..." while dragging, but this flag suppresses it. If you want a custom preview, draw your own content between `BeginDragDropSource()` and `EndDragDropSource()`—ImGui will render it as the drag preview.

### Can a single widget act as both a drag source and drop target?

Yes. Submit your widget, then call both `BeginDragDropSource()` and `BeginDragDropTarget()` sequentially. This pattern is essential for reordering lists where each item can be dragged to a new position and also receive other items. Use `PushID()` to give each widget a stable unique ID so ImGui can track the state correctly.

### Where does ImGui store the drag and drop state?

The state lives in the `ImGuiContext` structure defined in [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h) and managed in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp). Key fields include `DragDropActive`, `DragDropSourceId`, and the payload buffer `DragDropPayload`. Because the system is immediate-mode, you must call the Begin/End functions every frame; ImGui handles the persistence of the payload data internally between frames while a drag is active.