8.19.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.19.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
3options gc
4
5require imgui
6require imgui_app
7require opengl/opengl_boost
8require live/glfw_live
9require live/live_api
10require live/live_commands
11require live/live_vars
12require live_host
13require imgui/imgui_live
14require imgui/imgui_boost_runtime
15require imgui/imgui_boost_v2
16require imgui/imgui_widgets_builtin
17require imgui/imgui_containers_builtin
18require imgui/imgui_visual_aids
19
20var private SCROLL_ROW : table<int; NarrativeState>
21
22// nolint:STYLE014 — file-header tutorial banner displaced below a var decl
23// =============================================================================
24// TUTORIAL: child — BeginChild/EndChild sub-windows.
25//
26// child(IDENT, (text = "..", size = float2(w, h),
27// child_flags = ..., window_flags = ...)) { body }
28//
29// child is the workhorse for nesting a scrollable, optionally-bordered region
30// inside another window. Three knobs:
31//
32// 1. size — float2(w, h). (0,0) auto-fits to the available row/column
33// depending on flags. Positive = explicit pixels. Negative = "fill the
34// remainder, minus N pixels".
35//
36// 2. child_flags — ImGui's child-specific bitfield: Border, AlwaysAutoResize,
37// AutoResizeX/Y, FrameStyle, NavFlattened, ResizeX/Y.
38//
39// 3. window_flags — same flags every other window takes. Scrollbar control
40// lives here: HorizontalScrollbar, AlwaysVerticalScrollbar, etc.
41//
42// ChildState observed each frame: scroll (float2 current), scroll_max (float2
43// max). The body's render runs only while BeginChild returned true; scroll is
44// captured INSIDE that gate so a hidden child reports the last-known values.
45//
46// STANDALONE: daslang.exe modules/dasImgui/examples/tutorial/child.das
47// LIVE: daslang-live modules/dasImgui/examples/tutorial/child.das
48// =============================================================================
49
50[export]
51def init() {
52 live_create_window("dasImgui child tutorial", 800, 540)
53 live_imgui_init(live_window)
54 let io & = unsafe(GetIO())
55 GetStyle().FontScaleMain = 1.4
56}
57
58[export]
59def update() {
60 if (!live_begin_frame()) return
61 begin_frame()
62
63 ImGui_ImplGlfw_NewFrame()
64 apply_synth_io_override()
65 NewFrame()
66
67 SetNextWindowPos(ImVec2(20.0f, 20.0f), ImGuiCond.Always)
68 SetNextWindowSize(ImVec2(760.0f, 500.0f), ImGuiCond.Always)
69 window(CHILD_WIN, (text = "child tutorial", closable = false,
70 flags = ImGuiWindowFlags.None)) {
71
72 text("Three child variants - one each for borders, autosize, and h-scroll.")
73 separator()
74
75 // ---- A: bordered, fixed-size, vertical scroll ----
76 text("A) Bordered fixed-size with vertical scroll")
77 child(SCROLL_A, (text = "scroll_a",
78 size = float2(360.0f, 140.0f),
79 child_flags = ImGuiChildFlags.Borders,
80 window_flags = ImGuiWindowFlags.None)) {
81 for (i in range(20)) {
82 text(SCROLL_ROW[i], (text = "row {i} - content overflows the visible region"))
83 }
84 }
85 text("scroll.y = {SCROLL_A.scroll.y} / {SCROLL_A.scroll_max.y}")
86 spacing()
87
88 // ---- B: auto-resize Y, FrameStyle (input-group look) ----
89 text("B) AutoResizeY + FrameStyle - height tracks content")
90 child(AUTO_B, (text = "auto_b",
91 size = float2(360.0f, 0.0f),
92 child_flags = ImGuiChildFlags.AutoResizeY | ImGuiChildFlags.FrameStyle,
93 window_flags = ImGuiWindowFlags.None)) {
94 text("Three rows of input chrome")
95 checkbox(B_VSYNC, (text = "VSync"))
96 slider_int(B_LIMIT, (text = "frame limit"))
97 }
98 // AutoResizeY trims overflow to zero, so scroll = (0,0) and
99 // scroll_max = (0,0). The child's actual size lives in size.y;
100 // print scroll fields directly to show "no overflow".
101 text("AUTO_B.scroll = ({AUTO_B.scroll.x}, {AUTO_B.scroll.y}); scroll_max = ({AUTO_B.scroll_max.x}, {AUTO_B.scroll_max.y})")
102 spacing()
103
104 // ---- C: bordered, horizontal scroll ----
105 text("C) Border + horizontal scroll - wide content")
106 child(SCROLL_C, (text = "scroll_c",
107 size = float2(720.0f, 90.0f),
108 child_flags = ImGuiChildFlags.Borders,
109 window_flags = ImGuiWindowFlags.HorizontalScrollbar)) {
110 // One long line — forces horizontal scroll because no wrap.
111 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"))
112 text("(scroll horizontally to read; scroll.x mirrors below)")
113 }
114 text("scroll.x = {SCROLL_C.scroll.x} / {SCROLL_C.scroll_max.x}")
115 }
116
117 end_of_frame()
118 Render()
119 var w, h : int
120 live_get_framebuffer_size(w, h)
121 glViewport(0, 0, w, h)
122 glClearColor(0.10f, 0.10f, 0.12f, 1.0f)
123 glClear(GL_COLOR_BUFFER_BIT)
124 live_imgui_render()
125
126 live_end_frame()
127}
128
129[export]
130def shutdown() {
131 live_imgui_shutdown()
132 live_destroy_window()
133}
134
135[export]
136def main() {
137 init()
138 while (!exit_requested()) {
139 update()
140 maybe_collect_gc()
141 }
142 shutdown()
143}
8.19.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.19.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.19.15.1.3. child_flags vs window_flags
ImGuiChildFlags (the third arg) is child-specific:
Borders— draw a one-pixel border around the region.ResizeX/ResizeY— user-draggable resize grip on that axis.AutoResizeX/AutoResizeY— width/height 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.19.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.19.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.19.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.Borders,
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.19.15.1.7. Standalone vs live
Same convention as the other tutorials.
8.19.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.