macOS DMG: branded window background and icon layout

The DMG opened as a plain Finder window. It now shows the app icon's figure on
the VectorCraft colour, with VectorCraft.app and the Applications link side by side.

- packaging/macos/dmg/: background (SVG source, 1x + 2x HiDPI TIFF) and the
  Finder view settings (DS_Store: window, icon size 128, positions, background).
- package.sh copies them into the staging folder. The image is still built with
  hdiutil makehybrid: no mounted device and no Finder scripting on CI.
- The volume name drops the version: .DS_Store finds the background through an
  alias that includes the volume name. The DMG file name keeps the version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Xus Badia 2026-10-08 14:58:51 +02:00 committed by bflatastic
parent d3625f0b70
commit 884df22408
5 changed files with 74 additions and 1 deletions

Binary file not shown.

View File

@ -0,0 +1,47 @@
# macOS DMG window
What Finder shows when the DMG opens: a 660 × 400 pt background with the app icon and the
`Applications` link side by side. `package.sh` copies these files into the image; nothing here is
generated at build time, so the DMG still builds with `hdiutil makehybrid` (no mounted device, no
Finder scripting on CI).
| File | What |
|---|---|
| `background.svg` | Source of the background: the app icon's figure on the VectorCraft colour field (`#e8573f`), Ink and Paper, Inter and JetBrains Mono. |
| `background.tiff` | The background at 1x (660 × 400 px, 72 dpi) and 2x (1320 × 800 px, 144 dpi) in one HiDPI TIFF. Goes to `.background/background.tiff`. |
| `DS_Store` | Finder's view settings for the volume: window size, icon size 128, VectorCraft.app at (326, 205), `Applications` at (574, 205), and the background. Goes to `.DS_Store`. |
## Rules
- **The volume name has no version** (`VectorCraft`, not `VectorCraft <version>`). `.DS_Store` points at the
background through an alias that includes the volume name, so a versioned name loses the
background. The DMG file name still carries the version.
- **Finder draws the icon labels in black in light and dark mode** when a window has a background,
so the area under both icons stays light (Paper).
- **Nothing goes inside the icon boxes:** artwork keeps 10 pt clear of each 128 pt icon box and of
the label strip under it.
## Regenerate
1. Edit `background.svg` and render it with [resvg](https://github.com/linebender/resvg), with
Inter and JetBrains Mono available (`--use-fonts-dir` pointing at a craft-fonts checkout):
```sh
resvg --use-fonts-dir ../craft-fonts -w 660 background.svg bg.png
resvg --use-fonts-dir ../craft-fonts -w 1320 background.svg bg@2x.png
sips -s dpiWidth 144 -s dpiHeight 144 bg@2x.png
tiffutil -cathidpicheck bg.png bg@2x.png -out background.tiff
```
2. `DS_Store` only changes if the window size, icon positions or background file name change.
Recreate it once on a Mac with [create-dmg](https://github.com/create-dmg/create-dmg) and copy it
out of the mounted volume:
```sh
create-dmg --volname "VectorCraft" --background background.tiff --window-size 660 432 \
--icon-size 128 --icon "VectorCraft.app" 326 205 --hide-extension "VectorCraft.app" \
--app-drop-link 574 205 seed.dmg <folder with VectorCraft.app>
hdiutil attach seed.dmg -mountpoint /tmp/seed && cp "/tmp/seed/.DS_Store" DS_Store
```
(660 × 432 includes Finder's 32 pt title bar; the content area is 660 × 400.)

View File

@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="660" height="400" viewBox="0 0 660 400">
<defs><clipPath id="panel"><rect width="232" height="400"/></clipPath><pattern id="hatch" width="2.6" height="2.6" patternUnits="userSpaceOnUse" patternTransform="rotate(-38)">
<rect width="2.6" height="1.05" fill="#0b0b0c"/></pattern><filter id="grain" x="0" y="0" width="100%" height="100%">
<feTurbulence type="fractalNoise" baseFrequency="0.9" numOctaves="2" seed="7"/>
<feColorMatrix values="0 0 0 0 0.04 0 0 0 0 0.04 0 0 0 0 0.05 0.5 0 0 0 -0.225"/>
</filter></defs>
<rect width="660" height="400" fill="#efe9dc"/><rect width="660" height="400" filter="url(#grain)"/>
<g clip-path="url(#panel)"><rect width="232" height="400" fill="#e8573f"/><g transform="translate(-62.5,-31.0) scale(1.05)"><image href="../../../assets/app-icon/vectorcraft-small.svg" width="512" height="512"/></g></g>
<line x1="232.5" y1="0" x2="232.5" y2="400" stroke="#0b0b0c" stroke-width="1.2"/>
<line x1="236.5" y1="0" x2="236.5" y2="400" stroke="#0b0b0c" stroke-width="0.5"/>
<text x="266" y="72" font-family="Inter" font-weight="600" font-size="30" letter-spacing="-0.5" fill="#0b0b0c">VectorCraft</text>
<line x1="267" y1="88.5" x2="624" y2="88.5" stroke="#0b0b0c" stroke-width="0.6"/>
<path d="M271.5,81.5 L276,88.5 L271.5,95.5 L267,88.5 Z" fill="#e8573f"/>
<text x="267" y="112" font-family="JetBrains Mono" font-size="9" fill="#0b0b0c" fill-opacity="0.7">Path · 2 anchors · 2 pt stroke</text>
<path d="M412,213 C438,169 452,237 482,205" fill="none" stroke="#0b0b0c" stroke-width="2"/><rect x="408.5" y="209.5" width="7" height="7" fill="#efe9dc" stroke="#e8573f" stroke-width="1.4"/><path d="M494.8,201.9 L484.3,211.9 L480.5,199.5 Z" fill="#0b0b0c"/>
<line x1="267" y1="335.5" x2="624" y2="335.5" stroke="#0b0b0c" stroke-width="0.6"/>
<text x="267" y="358" font-family="Inter" font-weight="500" font-size="11" letter-spacing="1.5"
fill="#0b0b0c" fill-opacity="0.65">DRAG ONTO APPLICATIONS TO INSTALL</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

View File

@ -131,10 +131,15 @@ STAGE="$WORK/dmg"
mkdir -p "$STAGE"
ditto "$APP" "$STAGE/VectorCraft.app"
ln -s /Applications "$STAGE/Applications"
# Finder window layout: background, icon size and positions (packaging/macos/dmg/README.md).
mkdir -p "$STAGE/.background"
cp "$HERE/dmg/background.tiff" "$STAGE/.background/background.tiff"
cp "$HERE/dmg/DS_Store" "$STAGE/.DS_Store"
rm -f "$DMG" "$WORK/raw.dmg"
# makehybrid + convert builds the image without attaching a device, unlike `create -srcfolder`,
# which is flaky on CI runners ("Resource busy") and hangs in sandboxed sessions.
hdiutil makehybrid -hfs -hfs-volume-name "VectorCraft $VERSION" -hfs-openfolder "$STAGE" -o "$WORK/raw.dmg" "$STAGE"
# The volume name has no version: .DS_Store finds the background through an alias that includes it.
hdiutil makehybrid -hfs -hfs-volume-name "VectorCraft" -hfs-openfolder "$STAGE" -o "$WORK/raw.dmg" "$STAGE"
hdiutil convert "$WORK/raw.dmg" -format UDZO -imagekey zlib-level=9 -o "$DMG"
rm -f "$WORK/raw.dmg"
sign "$DMG"