dasImgui documentation Logo
2.0

Contents

  • dasImgui v2.0
    • 1. Boost macro layer
      • 1.1. Boost macro layer — DSL for declarative widget composition
        • 1.1.1. Function annotations
        • 1.1.2. Classes
      • 1.2. Boost runtime — widget state structs, registry, and dispatcher
        • 1.2.1. Type aliases
        • 1.2.2. Structures
        • 1.2.3. Per-frame registry
        • 1.2.4. Path machinery
        • 1.2.5. Coroutines
        • 1.2.6. Window control
        • 1.2.7. Live commands
        • 1.2.8. Synthetic input
        • 1.2.9. Debug logging
        • 1.2.10. Memory debugging
        • 1.2.11. Snapshot transform
        • 1.2.12. JSON serialization
    • 2. Builtin widgets
      • 2.1. Built-in widgets — inputs, selection, color, plots, output
        • 2.1.1. Call macros
        • 2.1.2. Selection
        • 2.1.3. Focus & scrolling
        • 2.1.4. Logging
        • 2.1.5. Status queries
      • 2.2. Built-in containers — windows, child regions, tabs, menus, popups
        • 2.2.1. Call macros
        • 2.2.2. Windows
        • 2.2.3. Tabs
        • 2.2.4. Popups
      • 2.3. ID stack — push/pop, scoped, hashing
        • 2.3.1. ID stack
      • 2.4. Layout helpers — splits, columns, docking, spacing
        • 2.4.1. Call macros
        • 2.4.2. Columns
        • 2.4.3. Trees
        • 2.4.4. List clipping
      • 2.5. Style helpers — colors, vars, push/pop, themes
        • 2.5.1. Call macros
        • 2.5.2. Push/pop
      • 2.6. Icon set
        • 2.6.1. Transport
        • 2.6.2. Edit
        • 2.6.3. Visualize
        • 2.6.4. Mix
        • 2.6.5. Organize
        • 2.6.6. Synth
        • 2.6.7. Scene tools
        • 2.6.8. Scene objects
        • 2.6.9. Arrange
        • 2.6.10. Editor transport
        • 2.6.11. View
        • 2.6.12. File
        • 2.6.13. General
        • 2.6.14. API
    • 3. Live reload and transport
      • 3.1. Live-reload lifecycle and synthetic-IO bypass driver
        • 3.1.1. Structures
        • 3.1.2. Lifecycle
        • 3.1.3. Synth IO drivers
        • 3.1.4. Event timelines
        • 3.1.5. Status / introspection
      • 3.2. Transport — pluggable lambda-based IPC for imgui commands
        • 3.2.1. Type aliases
        • 3.2.2. Constants
        • 3.2.3. Structures
        • 3.2.4. Transport construction
        • 3.2.5. Send / receive
        • 3.2.6. Awaiting
        • 3.2.7. Raw HTTP
    • 4. Testing toolkit
      • 4.1. Playwright — block-form test harness for daslang-live + dasImgui apps
        • 4.1.1. Constants
        • 4.1.2. Structures
        • 4.1.3. App lifecycle
        • 4.1.4. Locators / queries
        • 4.1.5. Actions
        • 4.1.6. Recording / narration
        • 4.1.7. Content-time gating
        • 4.1.8. Snapshots
        • 4.1.9. Polling / await
        • 4.1.10. Pause control
        • 4.1.11. Transport plumbing
      • 4.2. Visual aids — tutorial-mode overlays, mouse trail, narration, key HUD
        • 4.2.1. Constants
        • 4.2.2. Structures
        • 4.2.3. Highlight overlay
        • 4.2.4. Mouse trail
        • 4.2.5. Narration
        • 4.2.6. HUD
        • 4.2.7. Cursor sprite
        • 4.2.8. Override hooks
        • 4.2.9. Memory debugging
        • 4.2.10. Color utilities
        • 4.2.11. Serve / lifecycle
    • 5. External types
      • 5.1. imgui::ImGuiCol
      • 5.2. imgui::ImGui*Flags
      • 5.3. imgui::ImGuiCond
      • 5.4. imgui::ImVec2 / imgui::ImVec4 / imgui::ImColor
      • 5.5. imgui::ImGuiViewport
      • 5.6. imgui::ImGuiSizeCallbackData
      • 5.7. glfw::GLFWwindow
      • 5.8. imgui::ImGuiTextFilter
  • dasImgui tutorials
    • Boost basics
      • Walkthrough
        • Requires
        • Init and shutdown
        • The frame loop
        • The window container
        • Widgets
        • Standalone vs live
        • Driving from outside
        • Next steps
    • Widgets tour
      • Walkthrough
        • Requires
        • Init and shutdown
        • The frame loop
        • Widgets
        • Standalone vs live
        • Driving from outside
        • Next steps
    • Display widgets
      • Walkthrough
        • Requires
        • progress_bar
        • image
        • Snapshot shape
    • Narrative widgets
      • Walkthrough
        • Requires
        • text vs text_unformatted vs text_wrapped
        • Colored vs disabled
        • Bullets
        • label_text
        • separator_text
        • Snapshot shape
    • Custom widgets
      • Walkthrough
        • Requires
        • The state struct
        • The [widget] annotation
        • The drawlist pattern
        • Reusing pending_value_finalize
        • Standalone vs live
        • Driving from outside
        • Next steps
    • Layout
      • Walkthrough
        • Requires
        • Init and shutdown
        • The frame loop
        • Layout helpers
        • Standalone vs live
        • Driving from outside
        • Scope wrappers
        • Next steps
    • Layout primitives
      • Walkthrough
        • Requires
        • When to reach for each
        • Snapshot shape
    • Docking
      • Walkthrough
        • Requires
        • The flag that lights it up
        • Seeding the layout
        • Variant: dockspace inside a host window
        • The frame loop
        • Standalone vs live
        • Driving from outside
        • Next steps
    • With style
      • Walkthrough
        • Requires
        • Single block, mixed types
        • Nesting
        • Pop balance
        • Standalone vs live
        • Driving from outside
        • Next steps
    • With id
      • Walkthrough
        • Requires
        • The single-render rule
        • with_id scopes
        • Nested chains
        • Per-call id= — stable hash across renames
        • Per-call path= — stable registry path across renames
        • Standalone vs live
        • Driving from outside
        • Next steps
    • With disabled / font / button_repeat
      • Walkthrough
        • Requires
        • Why scope wrappers
        • with_disabled
        • with_button_repeat
        • with_font
        • with_clip_rect
        • Combining wrappers
    • State & telemetry
      • Walkthrough
        • Auto-emit
        • Reading state
        • Dotted flags
        • text_show — the app-driven mirror
        • Standalone vs live
        • Driving from outside
        • Next steps
    • Containers
      • Walkthrough
        • Requires
        • menu_bar / menu / menu_item
        • tab_bar / tab_item
        • popup
        • item_tooltip — hover-gated overlay
        • Standalone vs live
        • Driving from outside
        • Context popups
        • Next steps
    • Child windows
      • Walkthrough
        • Requires
        • size — three sizing modes
        • child_flags vs window_flags
        • ChildState — what the snapshot reports
        • Auto-resize variants
        • Horizontal scroll
        • Standalone vs live
        • Driving from outside
    • Group
      • Walkthrough
        • Requires
        • Two columns via same_line
        • Hit-testing a cluster
        • The (label | value | button) row
        • Why no flags?
        • Standalone vs live
        • Driving from outside
    • Tree node
      • Walkthrough
        • Requires
        • Nesting and path composition
        • Open / close from outside
        • Reading state.opened
        • ImGuiTreeNodeFlags
        • tree_node vs tree_node_ex
        • Standalone vs live
    • Collapsing header
      • Walkthrough
        • Requires
        • Two visibility dimensions
        • The closable form
        • The pending-flag channel
        • DefaultOpen flag
        • Standalone vs live
        • Driving from outside
    • Tab bar
      • Walkthrough
        • Requires
        • Active tab + body gating
        • Switching tabs from outside
        • Closable tabs
        • Sharing open state across two surfaces
        • ImGuiTabBarFlags
        • Standalone vs live
    • Modal popups
      • Walkthrough
        • Requires
        • Confirm dialog (non-closable)
        • Closable settings modal
        • popup vs popup_modal
        • Pending-flag channels
        • Standalone vs live
        • Driving from outside
    • Main menu bar
      • Walkthrough
        • Requires
        • main_menu_bar vs menu_bar
        • menu_item vs menu_label
        • Driving from outside
        • Snapshot shape
    • Popup window
      • Walkthrough
        • Requires
        • Two scopes, one str_id
        • Custom predicates
        • State
        • Standalone vs live
    • Flat tooltips
      • Walkthrough
        • Requires
        • set_item_tooltip vs the container form
        • The HelpMarker pattern
        • Standalone vs live
    • Drag and drop
      • Walkthrough
        • Requires
        • Source side
        • Target side
        • Driving from outside
        • Next steps
    • Live reload
      • Walkthrough
        • The reload boundary
        • @live preservation
        • The frame gate
        • [live_command] — user-defined HTTP endpoints
        • Manual reload hooks
        • Init / shutdown idempotence
        • Standalone vs live
        • Driving from outside
        • Next steps
    • Driving from outside
      • Walkthrough
        • The command surface
        • imgui_snapshot — read the world
        • imgui_force_set — value writes
        • imgui_click — fire a click
        • imgui_open / imgui_close — containers
        • The flow on a single command
        • Standalone vs live
        • Driving from outside (recap)
        • Next steps
    • Visual aids tour
      • Walkthrough
        • Layout
        • Highlight
        • Mouse trail
        • Cursor sprite
        • Narrate
        • Auto-highlight on command
        • Key HUD + focus rect (recording’s keyboard tour)
        • Standalone vs live
        • Driving from outside
    • Narrative + layout primitives
      • What the tour shows
      • Driving the tour
      • Idents matter for recordings
    • External-pointer editing rail
      • What the tour shows
      • safe_addr vs unsafe(addr)
      • Driving the tour
    • Recording tutorial videos
      • The subject
      • The driver
        • Anatomy of a driver
        • The visual-aids stack
        • The driver workflow in shell
        • Stop conditions
        • Replay stability
        • Standalone vs live
        • Driving from outside
        • The end of the curriculum
    • Harness + headless mode
      • Why headless
      • Running tests headless
      • What –headless does internally
      • Default-on lint: HARNESS001
      • Limits under –headless
    • data_table
      • Walkthrough
        • Requires
        • Container shape
        • Body primitives
        • Sortable tables
        • Why the name
        • Standalone vs live
    • file_dialog
      • Walkthrough
        • Requires
        • Public API
        • Modes
        • Navigation and sorting
        • Drivability
        • Standalone vs live
    • Window size constraints
      • Walkthrough
        • Requires
        • The three callback patterns
        • Struct layout
        • Standalone vs live
    • With tab stop
      • Walkthrough
        • Requires
        • Behaviour
        • When to reach for it
        • Standalone vs live
    • Color button hover
      • Walkthrough
        • Requires
        • When to reach for it
        • Click vs hover
        • Standalone vs live
    • Selectable hover
      • Walkthrough
        • Requires
        • When to reach for it
        • Toggle vs hover
        • Standalone vs live
    • Drawlist rail
      • Walkthrough
        • Scope wrappers
        • Primitives
        • Shape extras (v2 additions)
        • Path building
        • Channel splitting
        • Clip rect scope
        • Path-key telemetry
        • Standalone vs live
    • Drag widgets
      • Walkthrough
        • Requires
        • Speed and format
        • Bounds
        • Vector forms
        • Range forms
        • Driving from outside
        • Drag vs slider vs input
        • Caller-owned variant
    • Slider widgets
      • Walkthrough
        • Requires
        • Bounds
        • Format
        • Vector forms
        • Vertical orientation
        • Driving from outside
        • Slider vs drag vs input
        • Caller-owned variant
    • Input numeric widgets
      • Walkthrough
        • Requires
        • Step buttons
        • Format
        • Vector forms
        • Double precision
        • Flags
        • Driving from outside
        • Input vs drag vs slider
        • Caller-owned variant
    • Input text widgets
      • Walkthrough
        • Requires
        • Basic and with_hint
        • Multiline
        • Growable
        • Callback
        • text_filter
        • Indexed-form note
        • Driving from outside
    • Toggles
      • Walkthrough
        • Requires
        • checkbox vs radio_button (bool form)
        • radio_button_int — grouped, mutually exclusive
        • Driving from outside
        • Caller-owned variants
    • Dropdown + select
      • Walkthrough
        • Requires
        • combo — items array
        • combo_getter — procedural list
        • selectable — multi-toggle rows
        • selectable_label inside list_box — single-select
        • Driving from outside
        • When to use which
    • Color
      • Walkthrough
        • Requires
        • edit vs picker
        • color_button — click trigger, caller-owned color
        • Flags
        • Driving from outside
        • Caller-owned variants
    • Buttons
      • Walkthrough
        • Requires
        • button — the workhorse
        • small_button — zero padding
        • arrow_button — directional glyph
        • invisible_button — hit area only
        • image_button — textured trigger
        • tab_item_button — button styled as a tab
        • Driving from outside
        • Caller-owned variant
    • Plot
      • Walkthrough
        • Requires
        • Array form vs lambda form
        • Auto-fit vs explicit bounds
        • Size
        • The overlay arg
        • Driving from outside
    • tree_node_ex + image
      • Walkthrough
        • Requires
        • tree_node_ex vs tree_node (container)
        • image vs image_button
        • Driving from outside
    • Right-click context popups
      • Walkthrough
        • Requires
        • popup_context_item — attached to an item
        • popup_context_window — attached to the window
        • Flags
        • State model — stateless_finalize
    • edit_tab_item
      • Walkthrough
        • Requires
        • Why edit_tab_item over tab_item
        • The id arg
        • The pointer arg
        • Driving from outside
    • Icons
      • Walkthrough
        • Requires
        • icon_button — clickable
        • icon() — draw only
        • Enumerating the set
        • Drawing without a button
    • Wrapping tab bar
      • Walkthrough
        • Requires
        • Selecting a tab by name
        • Why an index, not ImGui’s tab state
        • Standalone vs live
    • Dynamic fonts
      • Walkthrough
        • Requires
        • Behaviour
        • Migration note
        • Standalone vs live
    • Texture references
      • Walkthrough
        • Requires
        • Behaviour
        • Migration note
    • Item flags
      • Walkthrough
        • Requires
        • Behaviour
    • Log capture
      • Walkthrough
        • Requires
        • Behaviour
        • Migration note
  • Internal binding families
    • Render helpers
    • Vertex shading
    • Layout & item sizing
    • Item hit-test & geometry
    • Item assembly (ItemAdd + ButtonBehavior)
    • Behavior-flag buttons
    • Axis layout primitives (splitter & scrollbar)
    • Tree-node behavior
    • Separator & low-level text
    • Combo internals
    • Popups, tooltips & menus
    • ID stack seed & override
    • Focus scope & activation
    • Item flags
    • Logging & capture
dasImgui documentation
  • dasImgui tutorials
  • Popup window
  • Edit on GitHub

Popup window

ImGui exposes three popup-opening patterns: auto-trigger from a preceding item (BeginPopupContextItem), auto-trigger from anywhere in the window (BeginPopupContextWindow), and manual-trigger — the caller decides when to open. The boost layer wraps each with a dedicated [container]:

  • popup_context_item(IDENT, (str_id, flags)) — right-click on the previously-submitted item opens the popup.

  • popup_context_window(IDENT, (str_id, flags)) — right-click anywhere inside the enclosing window opens it.

  • popup_window(IDENT, (str_id, flags)) — no auto-trigger; the caller drives open_popup(str_id, flags) from any custom predicate.

The manual form is what the cpp demo’s per-column table-context section needs: one shared str_id across multiple PushID scopes, each deciding for itself when to OpenPopup based on hover state, key combinations, or any predicate that has no preceding “item” to attach to.

Source: examples/tutorial/popup_window.das.

Walkthrough

Your browser doesn't support HTML5 video. Download the recording.

The recording drives both trigger scopes for real: clicking Open via button fires open_popup and the popup body renders; picking a fruit calls close_current_popup and the Last pick line updates; right-clicking anywhere in the hover region opens the same popup through the second scope. Each open is verified against the popup body’s rendered-this-frame state and each pick against the status line, so a trigger that failed to open or close the popup would abort the recording.

  1options gen2
  2
  3require imgui
  4require imgui_app
  5require opengl/opengl_boost
  6require live/glfw_live
  7require live/live_api
  8require live/live_commands
  9require live/live_vars
 10require live_host
 11require imgui/imgui_live
 12require imgui/imgui_boost_runtime
 13require imgui/imgui_boost_v2
 14require imgui/imgui_widgets_builtin
 15require imgui/imgui_containers_builtin
 16require imgui/imgui_id_builtin
 17require imgui/imgui_visual_aids
 18
 19// =============================================================================
 20// TUTORIAL: popup_window — stateless BeginPopup/EndPopup with manual trigger.
 21//
 22//   popup_window(IDENT, (str_id = "..", flags = ..)) { body }
 23//
 24// Distinct from the auto-triggered relatives:
 25//
 26//   popup_context_item    — right-click on the preceding item opens the popup.
 27//   popup_context_window  — right-click anywhere in the window opens it.
 28//   popup_window          — NO auto-trigger; caller drives open_popup(str_id).
 29//
 30// The manual form maps the cpp pattern from `imgui_demo.cpp`'s table-context
 31// section: one shared str_id, multiple PushID-scoped instances, custom
 32// hover/key/release predicates feeding the same OpenPopup call.
 33//
 34// STANDALONE: daslang.exe modules/dasImgui/examples/tutorial/popup_window.das
 35// LIVE:       daslang-live modules/dasImgui/examples/tutorial/popup_window.das
 36// =============================================================================
 37
 38var private LAST_PICK : string = "(none yet)"
 39
 40[export]
 41def init() {
 42    live_create_window("dasImgui popup_window tutorial", 760, 480)
 43    live_imgui_init(live_window)
 44    let io & = unsafe(GetIO())
 45    GetStyle().FontScaleMain = 1.4
 46}
 47
 48[export]
 49def update() {
 50    if (!live_begin_frame()) return
 51    begin_frame()
 52
 53    ImGui_ImplGlfw_NewFrame()
 54    apply_synth_io_override()
 55    NewFrame()
 56
 57    SetNextWindowPos(ImVec2(40.0f, 40.0f), ImGuiCond.Always)
 58    SetNextWindowSize(ImVec2(560.0f, 340.0f), ImGuiCond.Always)
 59    window(PW_WIN, (text = "popup_window", closable = false,
 60                    flags = ImGuiWindowFlags.None)) {
 61        text("Two scopes share str_id \"fruit_picker\":")
 62
 63        // Scope A: explicit click trigger.
 64        with_id("via_button") {
 65            if (button(PW_BTN, (text = "Open via button"))) {
 66                open_popup("fruit_picker")
 67            }
 68            popup_window(PW_BTN_POPUP, (str_id = "fruit_picker",
 69                                        flags = ImGuiWindowFlags.None)) {
 70                draw_picker_body()
 71            }
 72        }
 73
 74        separator()
 75
 76        // Scope B: hover-region + right-click — no preceding item involved.
 77        with_id("via_region") {
 78            text(PW_HOVER, (text = "(hover this region, right-click)"))
 79            let region_min = GetItemRectMin()
 80            let region_max = GetItemRectMax()
 81            let in_region = (IsMouseHoveringRect(region_min, region_max, true) &&
 82                             !IsAnyItemHovered())
 83            if (in_region && IsMouseReleased(ImGuiMouseButton.Right)) {
 84                open_popup("fruit_picker")
 85            }
 86            popup_window(PW_REG_POPUP, (str_id = "fruit_picker",
 87                                        flags = ImGuiWindowFlags.None)) {
 88                draw_picker_body()
 89            }
 90        }
 91
 92        separator()
 93        text(PW_STATUS, (text = "Last pick: {LAST_PICK}"))
 94    }
 95
 96    end_of_frame()
 97    Render()
 98    var w, h : int
 99    live_get_framebuffer_size(w, h)
100    glViewport(0, 0, w, h)
101    glClearColor(0.10f, 0.10f, 0.12f, 1.0f)
102    glClear(GL_COLOR_BUFFER_BIT)
103    live_imgui_render()
104
105    live_end_frame()
106}
107
108def private draw_picker_body() {
109    text("Pick a fruit:")
110    if (menu_label(PW_APPLE, (text = "Apple"))) {
111        LAST_PICK = "Apple"
112        close_current_popup()
113    }
114    if (menu_label(PW_BANANA, (text = "Banana"))) {
115        LAST_PICK = "Banana"
116        close_current_popup()
117    }
118    if (menu_label(PW_CHERRY, (text = "Cherry"))) {
119        LAST_PICK = "Cherry"
120        close_current_popup()
121    }
122    separator()
123    if (button(PW_CLOSE, (text = "Close"))) {
124        close_current_popup()
125    }
126}
127
128[export]
129def shutdown() {
130    live_imgui_shutdown()
131    live_destroy_window()
132}
133
134[export]
135def main() {
136    init()
137    while (!exit_requested()) {
138        update()
139    }
140    shutdown()
141}

Requires

Already in the baseline boost layer:

  • imgui/imgui_containers_builtin — popup_window, open_popup, close_current_popup.

  • imgui/imgui_id_builtin — with_id for the per-scope ID-stack push.

Two scopes, one str_id

ImGui keys a popup’s open state by str_id under the current ID stack. When two render sites want the same logical popup (“pick a fruit”) but need independent open state, push a distinct with_id("scope") { ... } around each:

with_id("via_button") {
    if (button(OPEN_BTN, (text = "Open via button"))) {
        open_popup("fruit_picker")
    }
    popup_window(BTN_POPUP, (str_id = "fruit_picker", flags = ImGuiWindowFlags.None)) {
        // body
    }
}

with_id("via_region") {
    // ...custom hover/release trigger...
    if (in_region && IsMouseReleased(ImGuiMouseButton.Right)) {
        open_popup("fruit_picker")
    }
    popup_window(REG_POPUP, (str_id = "fruit_picker", flags = ImGuiWindowFlags.None)) {
        // body
    }
}

The two scopes see the same str_id, but ImGui’s ID-stack push from with_id mangles the open state per scope. The shared body factor lets both scopes call the same private draw_picker_body() helper.

Custom predicates

Because there’s no auto-trigger, the caller is free to compose any predicate that should open the popup. The features demo combines a hover-region check with a right-release:

text(HINT, (text = "(hover this region, right-click)"))
let region_min = GetItemRectMin()
let region_max = GetItemRectMax()
let in_region = (IsMouseHoveringRect(region_min, region_max, true) &&
                 !IsAnyItemHovered())
if (in_region && IsMouseReleased(ImGuiMouseButton.Right)) {
    open_popup("fruit_picker")
}

This shape is what the cpp imgui_demo’s "Tables > Context menus" section uses to open one "MyPopup" per column. The examples/imgui_demo/tables.das port reuses popup_window for exactly that loop.

State

PopupWindowState is empty — ImGui owns the open lifecycle by str_id and the boost wrapper just brackets the body. The state global is what the registry walks to find the widget by IDENT; the snapshot reports kind="popup_window" for every registered instance regardless of whether the popup is currently visible.

Standalone vs live

Same convention as the other tutorials.

See also

Full source: examples/tutorial/popup_window.das

Features-side demo: examples/features/popup_window.das.

Integration test: tests/integration/test_popup_window.das.

Boost macros — the macro layer.

Previous Next

© Copyright 2026-2026, Gaijin Entertainment.

Built with Sphinx using a theme provided by Read the Docs.