From f45cf4a2271392efbb07edb5860c0426e37adda4 Mon Sep 17 00:00:00 2001 From: foxnne Date: Sun, 18 Oct 2026 16:06:17 -0500 Subject: [PATCH] popout: a float's window keeps its title for automation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `Popout.windowsShown` walked the float slots by value, so each float's `title` was a slice of `title_buf` in a stack copy that died with the iteration. `Demo.frameEnd` then named float windows from garbage, and `fizzy.screen` listed them as `.name="\x01\x00…"`, `.tag="fizzy.window:float:\x00…"`: tapes and agents could not aim at a float's window by its title. The loop now walks the slots by pointer, so the title is a slice of the float's own buffer, which lives until the float closes. The menus and dialogs loop below it copies too, but takes nothing by reference from the copy (a dialog's title comes from `core.dialogs`), so it stays. Co-Authored-By: Claude Opus 5.5 --- src/editor/Popout.zig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/editor/Popout.zig b/src/editor/Popout.zig index 7c2aaa35c..b844711d5 100644 --- a/src/editor/Popout.zig +++ b/src/editor/Popout.zig @@ -336,8 +336,9 @@ pub const Shown = struct { /// stacks them: the floats, then the dialogs and menus. After `endFrame`. pub fn windowsShown(buf: []Shown) []Shown { var n: usize = 0; - for (outs) |slot| { - const o = slot orelse continue; + // By pointer: the title is a slice of the float's own buffer, which a copy would take with it. + for (&outs) |*slot| { + const o = if (slot.*) |*o| o else continue; const p = o.part orelse continue; const t = o.target orelse continue; if (n == buf.len) break;