From fc3ef596fcfa780c879bbd3dfeedf1942f8bb621 Mon Sep 17 00:00:00 2001 From: "prompt.ac/@jeffrey" Date: Tue, 23 Jun 2026 22:39:13 -0700 Subject: [PATCH] slab/frame: capture-scale knob + fix Retina OCR coord scaling Introduces a captureScale constant (1x) used for both the capture resolution and the OCR->points conversion, replacing the backingScaleFactor- derived ocr scale that halved box coords on Retina displays. Leaves the knob for future higher-res / tiled OCR work. --- .../Sources/SlabMenubar/FrameCapture.swift | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/slab/menubar-swift/Sources/SlabMenubar/FrameCapture.swift b/slab/menubar-swift/Sources/SlabMenubar/FrameCapture.swift index e5d210bddd..dd6f943c4e 100644 --- a/slab/menubar-swift/Sources/SlabMenubar/FrameCapture.swift +++ b/slab/menubar-swift/Sources/SlabMenubar/FrameCapture.swift @@ -29,6 +29,11 @@ final class FrameCapture { // Transient overlay windows we draw (capture flash, OCR boxes). We exclude // them from the screen capture by windowID so they never appear in a frame // — that's the "doesn't interfere" guarantee. (The badge etc. still show.) + // Capture at this multiple of the display's point size — 2x makes small, + // dense text (terminals) physically larger in the buffer, pushing it over + // Vision's recognition threshold. The OCR scale uses the same factor so + // box coords still map back to screen points. + private let captureScale: Double = 1.0 private let overlayLock = NSLock() private var overlayWindowIDs = Set() private var ocrOverlayWindow: NSWindow? @@ -169,8 +174,8 @@ final class FrameCapture { } let filter = SCContentFilter(display: display, excludingWindows: exclude) let cfg = SCStreamConfiguration() - cfg.width = display.width - cfg.height = display.height + cfg.width = Int(Double(display.width) * self.captureScale) + cfg.height = Int(Double(display.height) * self.captureScale) cfg.showsCursor = true img = try? await SCScreenshotManager.captureImage(contentFilter: filter, configuration: cfg) } @@ -340,7 +345,6 @@ final class FrameCapture { var t = nowNs(); let mt = meta(); tm["meta"] = msSince(t) env["meta"] = mt - let scale = ((mt["screen"] as? [String: Any])?["scale"] as? CGFloat).map(Double.init) ?? 1.0 t = nowNs(); let cg = captureDisplay(); tm["capture"] = msSince(t) if cg != nil { flashCaptureIndicator() } // subtle post-capture awareness flash // The JPEG ships as RAW BYTES in a sidecar file (frame.out.jpg), not @@ -352,7 +356,7 @@ final class FrameCapture { if noOCR { env["ocr"] = [] } else { - t = nowNs(); let boxes = ocr(cg, scale: scale, fast: fast); tm["ocr"] = msSince(t) + t = nowNs(); let boxes = ocr(cg, scale: captureScale, fast: fast); tm["ocr"] = msSince(t) env["ocr"] = boxes showOcrOverlay(boxes) } -- 2.51.2