From 0b54c599fa5e26fb1754ca0aab53da5fa0e14af1 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Wed, 16 Sep 2026 11:53:11 -0300 Subject: Composite tag layers into the macOS e2e captures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tag text stopped living in the frame grid when the core moved the topbar, the column bar and every pane tag into tag layers of their own; the grid keeps the chrome and the physical grips. readFrame still read the grid alone, so every capture recorded blank header rows and each script timed out waiting for text that was on screen but not in the dump. Flatten the layers back over the grid at one cell per column — the tty backend's spelling, which these goldens exist to stay comparable with — and follow pardes_font_take to its size out-param. The goldens were recorded before the column bar and before the tag gap, so they are rerecorded here: the captures now agree column for column with what the tty renderer paints today. Co-Authored-By: Claude Opus 5 (1M context) --- test/macos_e2e.swift | 68 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 19 deletions(-) (limited to 'test/macos_e2e.swift') diff --git a/test/macos_e2e.swift b/test/macos_e2e.swift index 427d8314..58ad5206 100644 --- a/test/macos_e2e.swift +++ b/test/macos_e2e.swift @@ -266,8 +266,9 @@ private final class Driver: PardesViewDelegate { // The app does exactly this on every pump (AppDelegate.pump). Without // it the `Font` builtin would set a path nobody ever collects, and a // script asserting the new face would be asserting the old one. - if let view, let wanted = pardes_font_take() { - view.adoptFont(path: String(cString: wanted)) + var fontSize: UInt16 = 0 + if let view, let wanted = pardes_font_take(&fontSize) { + view.adoptFont(path: String(cString: wanted), sizeHundredths: fontSize) } } @@ -353,34 +354,63 @@ private final class Driver: PardesViewDelegate { return Frame(cols: cols, rows: rows, cursorX: cursorX, cursorY: cursorY, lines: []) } - var lines: [String] = [] - lines.reserveCapacity(rows) + var grid = [[String]](repeating: [String](repeating: " ", count: cols), count: rows) for row in 0.. String { + let text = withUnsafeBytes(of: cell.text) { raw in + String(decoding: raw.prefix(Int(cell.len)), as: UTF8.self) + } + return text.isEmpty ? " " : text + } + + /// Tag text is not in the frame grid any more. The core paints the topbar, + /// the column bar and every pane tag into tag layers of their own so a GUI + /// shell can set them at the smaller tagline pitch (Pardes.renderTagLayers); + /// the grid keeps only the chrome under them and the physical grips. A + /// capture that reads the grid alone therefore records blank header rows. + /// + /// Flatten the layers back over the grid at ONE cell per column. That is + /// the tty backend's spelling, and these goldens exist to stay comparable + /// with the tty ones row for row — the sub-cell pitch the layers carry is a + /// pixel concern with nowhere to live in a character grid. + private func compositeTagLayers(into grid: inout [[String]], cols: Int, rows: Int) { + for index in 0.. 0, let cells = pardes_tag_layer_cells(index) else { continue } + let x = Int(pardes_tag_layer_value(index, 4)) + let y = Int(pardes_tag_layer_value(index, 5)) + // A layer is allocated wide enough for text the viewport may crop, + // so the viewport — not the cell count — decides what is on screen. + let width = Int(pardes_tag_layer_value(index, 6)) + guard y >= 0, y < rows else { continue } + for col in 0..= cols { break } + let cell = cells[col] + if cell.flags & UInt8(PARDES_CELL_DEFAULT) != 0 || cell.len == 0 { continue } + grid[y][at] = cellText(cell) + } + } + } + // MARK: - captures private func snap(_ label: String) { -- cgit v1.3