This document explains how widgets are implemented in Dear ImGui, covering the fundamental ItemAdd/ItemSize pattern, widget lifecycle, interaction handling, and state management. Widgets are the building blocks of the user interface, ranging from simple text display to complex interactive controls.
For information about the window and layout system that hosts widgets, see Window System and Layout. For details on how widgets are rendered, see Draw System and Rendering Pipeline. For text input specifically, see Text Input System.
Widgets in Dear ImGui follow an immediate-mode paradigm where each widget function is called every frame and returns immediately after submitting draw commands and handling interaction. The widget system is built on a foundation of layout calculation, interaction detection via behavior functions, and draw command submission.
Sources: imgui_widgets.cpp1-33 imgui_widgets.cpp479-495 imgui_internal.h2145-2168
The ItemAdd/ItemSize pattern is the fundamental mechanism by which widgets register themselves with the layout system and interaction system. This pattern is used by virtually every widget in Dear ImGui.
ItemSize() advances the layout cursor and reserves space for an item. It updates window->DC.CursorPos and window->DC.CursorMaxPos to track the layout boundaries.
Key Responsibilities:
Sources: imgui.cpp9300-9350 imgui_internal.h3510-3515
ItemAdd() registers an item with the interaction system and determines if the item should be processed (not clipped). It returns false if the item is fully clipped and should skip rendering.
Key Responsibilities:
g.LastItemData for query functions (IsItemHovered(), etc.)Sources: imgui.cpp9352-9480 imgui_internal.h3515-3520
Example from Button:
Sources: imgui_widgets.cpp790-890 imgui.cpp9300-9480
Each widget goes through a standard lifecycle during frame processing, with state tracked across multiple systems.
Sources: imgui_internal.h2154-2168 imgui.cpp8800-9000
The ImGuiItemStatusFlags enum tracks various states of the last submitted item:
| Flag | Meaning | Set By |
|---|---|---|
ImGuiItemStatusFlags_HoveredRect | Mouse is over the item's rectangle | ItemHoverable() |
ImGuiItemStatusFlags_HasDisplayRect | Item has a display rectangle | ItemAdd() |
ImGuiItemStatusFlags_Edited | Value was edited this frame | Widget logic |
ImGuiItemStatusFlags_ToggledOpen | TreeNode was toggled open | TreeNode() |
ImGuiItemStatusFlags_ToggledSelection | Item selection was toggled | Selection logic |
ImGuiItemStatusFlags_HasDeactivated | Item was just deactivated | Activation logic |
ImGuiItemStatusFlags_Deactivated | Item is deactivated | Activation logic |
ImGuiItemStatusFlags_HoveredWindow | Mouse is over the item's window | Hover detection |
ImGuiItemStatusFlags_Focused | Item has keyboard focus | Navigation |
Sources: imgui_internal.h1192-1211
Widgets handle mouse, keyboard, and gamepad input through behavior functions that implement standardized interaction patterns. The ButtonBehavior() function is the core interaction handler used by most interactive widgets.
ButtonBehavior() is key to many interactions and used by most widgets. It handles various cases including keyboard/gamepad navigation, drag and drop, and many specific behaviors via ImGuiButtonFlags. The most common path is interacting with the mouse using the default ImGuiButtonFlags_PressedOnClickRelease button behavior.
Key Flags:
ImGuiButtonFlags_PressedOnClickRelease (default) - Returns true on mouse release over itemImGuiButtonFlags_PressedOnClick - Returns true on mouse pressImGuiButtonFlags_PressedOnRelease - Returns true on mouse release (even if not over item)ImGuiButtonFlags_PressedOnDoubleClick - Returns true on double-clickImGuiButtonFlags_Repeat - Holds return true when held for multiple framesThe following table shows the state reported by Dear ImGui during interaction with PressedOnClickRelease behavior:
| Frame | Mouse State | Return Value | IsItemHovered() | IsItemActive() | IsItemActivated() | IsItemDeactivated() | IsItemClicked() |
|---|---|---|---|---|---|---|---|
| N+0 | Outside bb | - | - | - | - | - | - |
| N+1 | Moves inside bb | - | true | - | - | - | - |
| N+2 | Button down | - | true | true | true | - | true |
| N+3 | Button down | - | true | true | - | - | - |
| N+4 | Moves outside bb | - | - | true | - | - | - |
| N+5 | Moves inside bb | - | true | true | - | - | - |
| N+6 | Button released | true | true | - | - | true | - |
| N+7 | Button released | - | true | - | - | - | - |
| N+8 | Moves outside bb | - | - | - | - | - | - |
Sources: imgui_widgets.cpp479-495 imgui_widgets.cpp522-790 imgui_internal.h2145-2168
| Function | Purpose | Defined In | Typical Usage |
|---|---|---|---|
ButtonBehavior() | Core button interaction handler | imgui_widgets.cpp:522 | Used by Button, Checkbox, MenuItem, etc |
ItemHoverable() | Check if item can be hovered | imgui.cpp | Called by ButtonBehavior and custom widgets |
SetActiveID() | Claim active state for item | imgui.cpp | When interaction begins (mouse/key press) |
ClearActiveID() | Release active state | imgui.cpp | When interaction completes |
KeepAliveID() | Prevent active ID from being cleared | imgui.cpp | Used for multi-frame interactions |
IsItemHovered() | Query if last item is hovered | imgui.cpp | User code, widget logic, tooltips |
IsItemActive() | Query if last item is active | imgui.cpp | User code to check ongoing interaction |
IsItemActivated() | Query if last item just became active | imgui.cpp | Detect interaction start |
IsItemDeactivated() | Query if last item just became inactive | imgui.cpp | Detect interaction end |
IsItemDeactivatedAfterEdit() | Query if item was edited then deactivated | imgui.cpp | Detect value change completion |
IsItemClicked() | Query if last item was clicked | imgui.cpp | Alternative to checking return value |
Sources: imgui_widgets.cpp522-790 imgui.cpp8800-9200 imgui.h916-936 imgui_internal.h3470-3510
Sources: imgui_widgets.cpp790-890 imgui_widgets.cpp522-790
Dear ImGui provides a comprehensive set of widget types. Most interactive widgets use ButtonBehavior() as their core interaction handler.
Sources: imgui_widgets.cpp1-33 imgui.h540-880 imgui_internal.h3470-3510
| File | Contains | Key Widgets/Functions |
|---|---|---|
imgui_widgets.cpp | Most interactive widgets | Button(), ButtonEx(), ButtonBehavior(), Checkbox(), SliderScalar(), DragScalar(), InputText(), ColorEdit4(), TreeNode(), Selectable(), BeginMenu(), MenuItem(), BeginTabBar(), TabItem() |
imgui.cpp | Core layout and display widgets | Text(), Separator(), Dummy(), Spacing(), Indent(), ItemAdd(), ItemSize(), SetActiveID(), ClearActiveID() |
imgui_tables.cpp | Table system | BeginTable(), EndTable(), TableNextRow(), TableSetupColumn() |
Sources: imgui_widgets.cpp1-50 imgui.cpp1-100 imgui_tables.cpp1-50
Widgets that need to persist state across frames use ID-based storage mechanisms. The Active ID system is central to tracking which widget is currently interacting with the user.
The Active ID system manages which widget currently "owns" user input. Only one widget can be active at a time.
Key State Variables (in ImGuiContext):
ActiveId - Currently active widget's ID (0 if none)ActiveIdWindow - Window containing the active widgetActiveIdIsAlive - Set to true by active widget each frameActiveIdSource - Source of activation (Mouse, Keyboard, Nav)ActiveIdTimer - Time the item has been activeActiveIdUsingMouseWheel - Active widget is using mouse wheelActiveIdUsingNavDirMask - Active widget is using directional navigationActiveIdAllowOverlap - Allow another item to steal active IDKey Functions:
SetActiveID(id, window) - Claim active status for a widgetClearActiveID() - Release active statusKeepAliveID(id) - Mark active ID as still alive this frameGetActiveID() - Query current active IDSources: imgui.cpp8650-8750 imgui_internal.h1050-1120 imgui_internal.h2145-2400
Button State (No Storage):
Buttons are stateless - they only return true when clicked. The interaction state (hovered, active) is tracked via g.ActiveId and g.HoveredId but not persisted across frames.
Checkbox State (User Variable):
TreeNode State (ImGuiStorage):
InputText State (ImGuiInputTextState):
Active ID Example:
Sources: imgui_widgets.cpp890-990 imgui_widgets.cpp5790-5900 imgui_widgets.cpp4100-4200 imgui_widgets.cpp522-790
Widgets emit drawing commands to ImDrawList, which are later collected and rendered by the backend.
Sources: imgui.cpp4500-4800 imgui_widgets.cpp790-1000
Frame Rendering (Button, Checkbox, etc):
Text Rendering:
Custom Shapes:
Sources: imgui.cpp4500-5000 imgui_widgets.cpp790-1100
Many widgets operate on multiple components (e.g., InputFloat3, ColorEdit4). These use a common pattern:
Example:
Sources: imgui_widgets.cpp3920-3970
Scalar widgets (Drag, Slider, Input) use a templated pattern with ImGuiDataType:
| Data Type | Size | Min | Max |
|---|---|---|---|
ImGuiDataType_S8 | 1 byte | -128 | 127 |
ImGuiDataType_U8 | 1 byte | 0 | 255 |
ImGuiDataType_S16 | 2 bytes | -32768 | 32767 |
ImGuiDataType_U16 | 2 bytes | 0 | 65535 |
ImGuiDataType_S32 | 4 bytes | -2147483648 | 2147483647 |
ImGuiDataType_U32 | 4 bytes | 0 | 4294967295 |
ImGuiDataType_S64 | 8 bytes | -2^63 | 2^63-1 |
ImGuiDataType_U64 | 8 bytes | 0 | 2^64-1 |
ImGuiDataType_Float | 4 bytes | -FLT_MAX | FLT_MAX |
ImGuiDataType_Double | 8 bytes | -DBL_MAX | DBL_MAX |
Sources: imgui_widgets.cpp2215-2400 imgui_widgets.cpp2800-3000
Widgets use the ID system to uniquely identify themselves for interaction and state storage.
Key Concepts:
Label Syntax:
"Label" - Visible label, used for ID"Label##Hidden" - "Label" visible, "Hidden" used for ID"##Hidden" - No visible label, "Hidden" used for IDID Stack:
Sources: imgui.cpp8650-8750 imgui_internal.h3890-3920
The Dear ImGui widget system is built on several core concepts:
ImDrawList for later renderingIsItemHovered(), IsItemActive(), etc. provide feedback to user codeThis architecture enables Dear ImGui's ease of use while maintaining efficiency and flexibility.
Sources: imgui.cpp1-200 imgui_widgets.cpp1-100 imgui_internal.h1-200
Refresh this wiki