Fix ad-hoc appex signing and thumbnail scaling for QuickLook (#365)

The ad-hoc codesign path signed the whole bundle with one --deep pass,
which never carried --entitlements to the QuickLook appex, so PlugInKit
silently rejected it as unsandboxed. Sign nested code individually
instead, matching the Developer ID path.

Separately, ThumbnailProvider drew the extracted preview at its native
pixel size anchored at the CGContext origin (bottom-left) instead of
scaling it to fill request.maximumSize, producing a small thumbnail
stuck in one corner instead of a properly sized, centered icon.

Note: Gatekeeper still rejects an ad-hoc or unnotarized Developer-ID
signature outright, and PlugInKit periodically re-validates and drops
any registered plugin that fails that check — so these fixes are
necessary but not sufficient for thumbnails to render from a build
that isn't both signed and notarized.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Felix RiestraandClaude Sonnet 5 committed 2026-09-15 16:43:28 +02:00
1 parent 612124b84b
commit 79028bcee4
2 files changed
+28 -5

No files matched your search

@@ -39,9 +39,19 @@ final class ThumbnailProvider: QLThumbnailProvider {
return
}
let size = CGSize(width: cg.width, height: cg.height)
let reply = QLThumbnailReply(contextSize: size) { (ctx: CGContext) -> Bool in
ctx.draw(cg, in: CGRect(origin: .zero, size: size))
// The embedded DWG preview bitmap is often much smaller than the
// requested icon size. Scale it up (or down) to fit request.maximumSize
// and center it — otherwise QuickLook draws it at its native pixel size
// anchored at the CGContext origin (bottom-left), producing a small
// thumbnail stuck in the corner instead of filling the icon (#365).
let maxSize = request.maximumSize
let nativeSize = CGSize(width: cg.width, height: cg.height)
let scale = min(maxSize.width / nativeSize.width, maxSize.height / nativeSize.height)
let drawSize = CGSize(width: nativeSize.width * scale, height: nativeSize.height * scale)
let origin = CGPoint(x: (maxSize.width - drawSize.width) / 2, y: (maxSize.height - drawSize.height) / 2)
let reply = QLThumbnailReply(contextSize: maxSize) { (ctx: CGContext) -> Bool in
ctx.draw(cg, in: CGRect(origin: origin, size: drawSize))
return true
}
handler(reply, nil)