From 40c19fd4f52d20df94c2dfa2d68102b89bd9d3f1 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 15 Sep 2026 14:46:38 -0300 Subject: Add optional compact tagline styling for source context --- src/macos/Sources/AppDelegate.swift | 2 + src/macos/Sources/PardesView.swift | 133 +++++++++++++++++++++++++++++++++--- src/macos/pardes.h | 7 ++ 3 files changed, 133 insertions(+), 9 deletions(-) (limited to 'src/macos') diff --git a/src/macos/Sources/AppDelegate.swift b/src/macos/Sources/AppDelegate.swift index eb499f1b..96f4a184 100644 --- a/src/macos/Sources/AppDelegate.swift +++ b/src/macos/Sources/AppDelegate.swift @@ -671,6 +671,8 @@ final class AppDelegate: NSObject, NSApplicationDelegate, PardesViewDelegate { grid.cols, grid.rows, UInt16((view.cellWidth * scale).rounded()), UInt16((view.cellHeight * scale).rounded())) + pardes_row_metrics(UInt16(max(1,(view.cellWidth*scale).rounded())), UInt16(max(1,(view.cellHeight*scale).rounded())), + UInt16(max(1,(view.taglineCellWidth*scale).rounded())), UInt16(max(1,(view.taglineBandHeight*scale).rounded()))) pump() } diff --git a/src/macos/Sources/PardesView.swift b/src/macos/Sources/PardesView.swift index 2160047d..b14e1aa0 100644 --- a/src/macos/Sources/PardesView.swift +++ b/src/macos/Sources/PardesView.swift @@ -736,12 +736,15 @@ final class PardesView: NSView { guard percent != taglines.percent else { return false } taglines = TaglineMetrics(body: metrics, percent: percent, scale: metricsScale) taglineGlyphCache.removeAll(keepingCapacity: true) + pardes_row_metrics(UInt16(max(1,(cellWidth*metricsScale).rounded())),UInt16(max(1,(cellHeight*metricsScale).rounded())), + UInt16(max(1,(taglines.width*metricsScale).rounded())),UInt16(max(1,(taglines.height*metricsScale).rounded()))) needsDisplay = true return true } var taglinePercent: UInt8 { taglines.percent } var taglineBandHeight: CGFloat { taglines.height } + var taglineCellWidth: CGFloat { taglines.width } /// Seed runtime Config after init and update it after every successful /// adopt/zoom. Points are the native owner's unit; the cell's backing-pixel @@ -905,7 +908,10 @@ final class PardesView: NSView { // Only a canonical presentation advances the attachment baseline. // During a transition deleted panes keep their cropped CGImages alive // here even after both the core placement and image cache entry vanish. - if !animatedPanels { presentedImages = frameImages } + if !animatedPanels { + presentedImages = frameImages + presentedBodyLayers = snapshotBodyLayers() + } presentationSerial &+= 1 let animationWoke = pardes_frame_presented(animatedPanels) let pointerMoved = refreshPresentedPointer() @@ -936,9 +942,9 @@ final class PardesView: NSView { guard changed else { return false } if let button = latchedButton { latchedCell = at - pardes_mouse(button, PARDES_MOUSE_DRAG, at.col, at.row, pointerModifiers) + sendMouse(button, PARDES_MOUSE_DRAG, at.col, at.row, pointerModifiers) } else { - pardes_mouse(PARDES_MOUSE_NONE, PARDES_MOUSE_MOTION, + sendMouse(PARDES_MOUSE_NONE, PARDES_MOUSE_MOTION, at.col, at.row, pointerModifiers) } return true @@ -1159,6 +1165,101 @@ final class PardesView: NSView { width: caretWidth, height: caretHeight), fg, 1) } } + if frozenImages == nil { + drawBodyLayers(ctx, hideCursor:hideCursor) + } else { + for layer in presentedBodyLayers { + layer.cells.withUnsafeBufferPointer { cells in + if let base = cells.baseAddress { drawBodyLayer(ctx, values:layer.values, cells:base, hideCursor:true) } + } + } + } + } + + private struct FrozenBodyLayer { + let values: [Int] + let cells: [pardes_cell_s] + } + private var presentedBodyLayers: [FrozenBodyLayer] = [] + + private func snapshotBodyLayers() -> [FrozenBodyLayer] { + var result: [FrozenBodyLayer] = [] + for index in 0.., hideCursor: Bool) { + func value(_ field: Int) -> Int { values[field] } + let rows = value(0), cols = value(1), contexts = value(2) + let left = CGFloat(value(3)) * cellWidth, top = CGFloat(value(4)) * cellHeight + let viewport = CGRect(x: left, y: top, width: CGFloat(value(5))*cellWidth, + height: CGFloat(value(6))*cellHeight) + ctx.saveGState() + ctx.clip(to: viewport) + fill(ctx, viewport, themeBG ?? pardesDefaultBG, 1) + for row in 0..= viewport.maxY { break } + let rowStyle = resolve(cells[row*cols], block: false, ground: themeBG ?? pardesDefaultBG, clearGround: false) + fill(ctx, CGRect(x: left, y: y, width: viewport.width, height: height), rowStyle.bg, 1) + for pass in 0...1 { + for col in 0..