8.18.1.15. Child windows
child brackets BeginChild/EndChild into a block-arg container —
a sub-window that can be sized, bordered, scrolled, and addressed in the
registry hierarchy. The wrapper’s signature:
child(IDENT, (text = "...",
size = float2(w, h),
child_flags = ImGuiChildFlags....,
window_flags = ImGuiWindowFlags....)) {
// body — leaves register under <window>/IDENT
}
Three knobs do most of the work — size, child_flags, window_flags
— and the boost layer captures scroll / scroll_max each frame so a
snapshot reports the current scroll position without polling.
Source: modules/dasImgui/examples/tutorial/child.das.
8.18.1.15.1. Walkthrough
The recording drives each of the three children with real synthetic input
and self-verifies. It parks the cursor inside the bordered child A and
wheel-scrolls it, asserting SCROLL_A’s scroll payload actually
moved; toggles the VSync checkbox inside the AutoResizeY child B;
then wheel-scrolls the horizontal child C sideways, asserting
SCROLL_C’s scroll moved. The scroll assertions read the boost
layer’s per-frame scroll telemetry directly — a no-op scroll (cursor
not over the child, wheel not attributed) would abort the recording.
1options gen2
2options _comment_hygiene = true
3
4require imgui
5require imgui_app
6require opengl/opengl_boost
7require live/glfw_live
8require live/live_api
9require live/live_commands
10require live/live_vars
11require live_host
12require imgui/imgui_live
13require imgui/imgui_boost_runtime
14require imgui/imgui_boost_v2
15require imgui/imgui_widgets_builtin
16require imgui/imgui_containers_builtin
17require imgui/imgui_visual_aids
18
19var private SCROLL_ROW : table<int; NarrativeState>
20
21// nolint:STYLE014 — file-header tutorial banner displaced below a var decl
22// =============================================================================
23// TUTORIAL: child — BeginChild/EndChild sub-windows.
24//
25// child(IDENT, (text = "..", size = float2(w, h),
26// child_flags = ..., window_flags = ...)) { body }
27//
28// child is the workhorse for nesting a scrollable, optionally-bordered region
29// inside another window. Three knobs:
30//
31// 1. size — float2(w, h). (0,0) auto-fits to the available row/column
32// depending on flags. Positive = explicit pixels. Negative = "fill the
33// remainder, minus N pixels".
34//
35// 2. child_flags — ImGui's child-specific bitfield: Border, AlwaysAutoResize,
36// AutoResizeX/Y, FrameStyle, NavFlattened, ResizeX/Y.
37//
38// 3. window_flags — same flags every other window takes. Scrollbar control
39// lives here: HorizontalScrollbar, AlwaysVerticalScrollbar, etc.
40//
41// ChildState observed each frame: scroll (float2 current), scroll_max (float2
42// max). The body's render runs only while BeginChild returned true; scroll is
43// captured INSIDE that gate so a hidden child reports the last-known values.
44//
45// STANDALONE: daslang.exe modules/dasImgui/examples/tutorial/child.das
46// LIVE: daslang-live modules/dasImgui/examples/tutorial/child.das
47// =============================================================================
48
49[export]
50def init() {
51 live_create_window("dasImgui child tutorial", 800, 540)
52 live_imgui_init(live_window)
53 let io & = unsafe(GetIO())
54 GetStyle().FontScaleMain = 1.4
55}
56
57[export]
58def update() {
59 if (!live_begin_frame()) return
60 begin_frame()
61
62 ImGui_ImplGlfw_NewFrame()
63 apply_synth_io_override()
64 NewFrame()
65
66 SetNextWindowPos(ImVec2(20.0f, 20.0f), ImGuiCond.Always)
67 SetNextWindowSize(ImVec2(760.0f, 500.0f), ImGuiCond.Always)
68 window(CHILD_WIN, (text = "child tutorial", closable = false,
69 flags = ImGuiWindowFlags.None)) {
70
71 text("Three child variants - one each for borders, autosize, and h-scroll.")
72 separator()
73
74 // ---- A: bordered, fixed-size, vertical scroll ----
75 text("A) Bordered fixed-size with vertical scroll")
76 child(SCROLL_A, (text = "scroll_a",
77 size = float2(360.0f, 140.0f),
78 child_flags = ImGuiChildFlags.Borders,
79 window_flags = ImGuiWindowFlags.None)) {
80 for (i in range(20)) {
81 text(SCROLL_ROW[i], (text = "row {i} - content overflows the visible region"))
82 }
83 }
84 text("scroll.y = {SCROLL_A.scroll.y} / {SCROLL_A.scroll_max.y}")
85 spacing()
86
87 // ---- B: auto-resize Y, FrameStyle (input-group look) ----
88 text("B) AutoResizeY + FrameStyle - height tracks content")
89 child(AUTO_B, (text = "auto_b",
90 size = float2(360.0f, 0.0f),
91 child_flags = ImGuiChildFlags.AutoResizeY | ImGuiChildFlags.FrameStyle,
92 window_flags = ImGuiWindowFlags.None)) {
93 text("Three rows of input chrome")
94 checkbox(B_VSYNC, (text = "VSync"))
95 slider_int(B_LIMIT, (text = "frame limit"))
96 }
97 // AutoResizeY trims overflow to zero, so scroll = (0,0) and
98 // scroll_max = (0,0). The child's actual size lives in size.y;
99 // print scroll fields directly to show "no overflow".
100 text("AUTO_B.scroll = ({AUTO_B.scroll.x}, {AUTO_B.scroll.y}); scroll_max = ({AUTO_B.scroll_max.x}, {AUTO_B.scroll_max.y})")
101 spacing()
102
103 // ---- C: bordered, horizontal scroll ----
104 text("C) Border + horizontal scroll - wide content")
105 child(SCROLL_C, (text = "scroll_c",
106 size = float2(720.0f, 90.0f),
107 child_flags = ImGuiChildFlags.Borders,
108 window_flags = ImGuiWindowFlags.HorizontalScrollbar)) {
109 // One long line — forces horizontal scroll because no wrap.
110 text(LONG_LINE, (text = "very wide content: lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua ut enim ad minim veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo"))
111 text("(scroll horizontally to read; scroll.x mirrors below)")
112 }
113 text("scroll.x = {SCROLL_C.scroll.x} / {SCROLL_C.scroll_max.x}")
114 }
115
116 end_of_frame()
117 Render()
118 var w, h : int
119 live_get_framebuffer_size(w, h)
120 glViewport(0, 0, w, h)
121 glClearColor(0.10f, 0.10f, 0.12f, 1.0f)
122 glClear(GL_COLOR_BUFFER_BIT)
123 live_imgui_render()
124
125 live_end_frame()
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}
8.18.1.15.1.1. Requires
Already in the baseline boost layer:
imgui/imgui_containers_builtin— defineschild,child_scroll_reenter.imgui/imgui_widgets_builtin—text,checkbox,slider_int.
8.18.1.15.1.2. size — three sizing modes
The size : float2(w, h) argument has three flavors:
Explicit positive —
size = float2(360.0f, 140.0f)— fixed pixel size. The body’s content is clipped to that region and scrollbars appear if it overflows.Zero —
size = float2(0.0f, 0.0f)— auto-fit to the available column/row. Pair withImGuiChildFlags.AutoResizeX/Yto let the body grow to the content extent instead.Negative —
size = float2(-FLT_MIN, 0.0f)— “fill the remaining space minus that many pixels”. Useful for stretchy panes that should fit the parent.
8.18.1.15.1.3. child_flags vs window_flags
ImGuiChildFlags (the third arg) is child-specific:
Border— draw a one-pixel border around the region.AutoResizeX/AutoResizeY— height/width tracks content extent.AlwaysAutoResize— combine both axes and re-measure every frame.FrameStyle— frame-style chrome (like input groups). Implies a background and rounded corners drawn from the active style.NavFlattened— keyboard nav treats the child as part of the parent.
ImGuiWindowFlags (the fourth arg) governs the child’s scrollbar
policy and window-level behavior:
HorizontalScrollbar— enable the bottom scroll track when content overflows horizontally (default = none).AlwaysVerticalScrollbar/AlwaysHorizontalScrollbar— keep the bar visible even when the content fits.NoMove/NoResize/NoBackground— standard window knobs.
The two flag sets compose freely; pick from each based on the child’s chrome and scroll needs.
8.18.1.15.1.4. ChildState — what the snapshot reports
ChildState captures four floats:
var SCROLL_A : ChildState
// After the frame renders:
// SCROLL_A.size : float2 // sticky — what was passed in
// SCROLL_A.scroll : float2 // current scroll (GetScrollX/Y)
// SCROLL_A.scroll_max : float2 // GetScrollMaxX/Y for this content
// SCROLL_A.child_flags / SCROLL_A.window_flags // sticky
Snapshot reports them under <window>/SCROLL_A. Drivers that want to
verify “the user scrolled to row 12” compare scroll.y against a
known threshold. scroll_max is read AFTER the body invoke — it
depends on the content extent, which the body just emitted.
8.18.1.15.1.5. Auto-resize variants
The B child uses AutoResizeY | FrameStyle:
child(AUTO_B, (text = "auto_b",
size = float2(360.0f, 0.0f),
child_flags = ImGuiChildFlags.AutoResizeY | ImGuiChildFlags.FrameStyle,
window_flags = ImGuiWindowFlags.None)) {
text("Three rows of input chrome")
checkbox(B_VSYNC, (text = "VSync"))
slider_int(B_LIMIT, (text = "frame limit"))
}
Size’s Y is 0.0f — required when AutoResizeY is active so ImGui
treats the slot as auto. The height grows to fit the body each frame.
scroll and scroll_max both report (0, 0) for an AutoResize child:
no overflow means no scroll range. ChildState.size is the
caller-provided input — for AutoResizeY it stays at (360.0f, 0.0f),
so it does NOT tell you the rendered height. The wrapper does not
currently expose the auto-computed extent; if you need it, call
GetWindowSize() inside the child body, or place a sentinel widget
at the end and read its bbox bottom from the snapshot.
8.18.1.15.1.6. Horizontal scroll
window_flags.HorizontalScrollbar enables the bottom track:
child(SCROLL_C, (text = "scroll_c",
size = float2(720.0f, 90.0f),
child_flags = ImGuiChildFlags.Border,
window_flags = ImGuiWindowFlags.HorizontalScrollbar)) {
text(LONG_LINE, (text = "very wide content: lorem ipsum..."))
}
Without the flag, overlong single-line text would be clipped. With it,
the user drags the bottom bar and SCROLL_C.scroll.x mirrors the
position.
8.18.1.15.1.7. Standalone vs live
Same convention as the other tutorials.
8.18.1.15.1.8. Driving from outside
External drivers can wheel-scroll the active child by posting an
imgui_mouse_scroll command (the live counterpart to
ImGui_ImplGlfw’s wheel events):
curl -X POST -d '{"name":"imgui_mouse_scroll","args":{"x":0.0,"y":-3.0}}' \
localhost:9090/command
The cursor must be over the child window for ImGui to attribute the
scroll. The recording driver uses this exact channel to nudge
SCROLL_A between narration stages.
See also
Full source: modules/dasImgui/examples/tutorial/child.das
Features-side demo: modules/dasImgui/examples/features/child_scroll_reenter.das — the
child_scroll_reenter helper for nudging an existing child’s scroll
from outside its block.
Sibling: Containers — the umbrella tour of container rails.
Boost macros — the macro layer.