Skip to content

Releases: Ching367436/spice-mac

SpiceMac 0.1.8

Choose a tag to compare

@Ching367436 Ching367436 released this 27 Aug 16:26

Added

  • Display zoom (View ▸ Zoom). On a Retina Mac the client asked the guest for
    the view's full backing pixel count, so a 1512×982-point window drove the
    guest at 3024×1964 — the guest has no idea the Mac is HiDPI, so it rendered
    one pixel per pixel and everything came out half size, while the VM pushed
    four times the pixels it needed. Zoom is now Z = Mac physical pixels per
    guest pixel
    : the client requests points × backing scale ÷ Z and each guest
    pixel is drawn as a Z×Z block, so readability and cost improve together.
    Shortcuts ⌃⌘+ / ⌃⌘− / ⌃⌘0.

  • The zoom level is per-window, and a fixed level is absolute. Each window
    is its own session on its own display, so it carries its own level: picking
    one in the front window leaves the others alone. The commands live on the
    window controller and reach it down the responder chain the way Connection ▸ Send Ctrl-Alt-Del already did, so the submenu greys out with no session open;
    the preference is only the seed a new window starts from. Nothing but the user
    ever changes a level — Automatic is the mode for constant apparent size
    across a move.

  • A window that changes display re-applies its geometry. At a fixed level
    the target guest size is points × backing scale ÷ Z, and a move changes the
    backing scale out from under it — which is why it used to need a manual nudge
    of the window before the guest came out right. All four signals AppKit offers
    now drive it, including NSApplicationDidChangeScreenParameters for hotplug,
    sleep/wake and Displays scaled-mode changes, which resize the window without a
    live resize. Requests are coalesced, so four triggers cost at most one guest
    mode switch.

  • Without spice-vdagent, zoom and screen changes resize the window
    (guest × Z ÷ backing scale points) rather than doing nothing — the guest
    resolution is fixed, so that is the only side of the equation left. The
    geometry is a new dependency-free package, Packages/DisplayScale, with a
    21-check scalecheck runner wired into make test and CI.

Changed

  • The default zoom is Automatic (Z = the screen's backing scale), which
    changes behaviour on upgrade.
    The guest resolution now tracks the window's
    point size instead of its backing-pixel size, so on first connect after
    updating a Retina guest drops to roughly half its previous resolution and
    everything in it gets twice as big. That is the fix; View ▸ Zoom ▸ 100%
    restores the old behaviour. Automatic also means the requested resolution is
    the window's point size on any display, so dragging between screens needs no
    guest reconfiguration.

Fixed

  • A dead connection no longer hides its own explanation. When a session
    ended, the last guest frame stayed frozen over the window (the Metal view is
    opaque and detach() leaves it showing its final texture), so the
    "Disconnected — open a fresh .vv file" hint or the failure reason was drawn
    invisibly behind it and the window just looked hung. The display view now
    hides when the session ends and returns on the next connect, revealing the
    centered status message. A specific failure reason (.failed) is also kept
    if the generic disconnect callback arrives after the error one, instead of
    being downgraded to "Disconnected."

  • ISO / French Magic Keyboard <> key now reaches the guest. The keymap was
    ANSI-only and omitted kVK_ISO_Section (0x0A), the key next to Left Shift on
    ISO hardware (e.g. French AZERTY < / >). Presses produced no guest event.
    Map it to PC set-1 KEY_102ND (0x56); inputcheck covers the mapping.
    (#4)

  • Guest text was blurry at some window sizes and not others, worst on a
    normal-DPI monitor. The sampler only went nearest-neighbour at 2× or more, so
    a 1:1 presentation — what 100% means on a 1x screen — always took the bilinear
    path; and because the requested mode is floored onto the 8-wide/2-high grid
    guest drivers want, the centred quad landed on a half-pixel offset
    whenever that slack was odd. Nearest now applies at any whole-number
    magnification, and viewportOrigin nudges the quad onto whole pixels — the
    input router subtracts the same origin, so the cursor stays locked.

  • Dragging a window between a Retina panel and a 1x monitor did not re-scale
    the guest.
    MTKView refreshes drawableSize lazily, so inside
    viewDidChangeBackingProperties — the one moment such a move offers — it
    still holds the previous screen's value: on a real 2.0↔1.0 drag the callback
    reports backingScaleFactor 1.0 while drawableSize is still 1800×1200 for a
    view that is now 900×600 physical pixels. The fit now measures with
    convertToBacking(bounds), which follows the backing store immediately, and
    pulls the drawable up to match.

Download

SpiceMac.app.zip — Apple Silicon, macOS 12+. Ad-hoc signed; to open: right-click ▸ Open (macOS 14) or System Settings ▸ Privacy & Security ▸ Open Anyway (macOS 15+), or xattr -dr com.apple.quarantine /Applications/SpiceMac.app.

SHA-256: faeb08e0ef42a4189ed69a4a64cc4c7d3b6e29e511645ccea876eb865551ad76

SpiceMac 0.1.7

Choose a tag to compare

@Ching367436 Ching367436 released this 15 Jun 09:47

Fixed

  • Copying a spreadsheet cell in the guest now pastes onto the Mac. A guest
    copy offers several clipboard representations at once (a cell = UTF-8 text + a
    bitmap image); the guest→host bridge cleared the Mac pasteboard on every write,
    so the representations clobbered each other and only the last survived — usually
    the image, leaving nothing to paste as text. The bridge now clears once per
    guest grab and accumulates the rest, so the cell's text (and image) both land.
    Plain-text copy was unaffected because it's a single type. (Fork change — see
    ThirdParty/CocoaSpice/FORK-NOTES.md.)

Security

  • Hardened the .vv parser (the one attacker-influenced file the app opens):
    a 1 MiB file-size cap + UTF-8 enforcement in VVConfig(contentsOf:),
    control-character stripping from values (a NUL in host/proxy would
    otherwise survive Swift validation but truncate inside the C SPICE stack — a
    smuggle), port-range validation (only 1–65535; junk/negative/overflow become
    "absent"), and leading-BOM tolerance. Added a deterministic 20k-iteration
    fuzzer
    + edge-case tests (vvcheck, now 24 checks) proving the parser never
    crashes on arbitrary input.

Download

SpiceMac.app.zip — Apple Silicon, macOS 12+. Ad-hoc signed; to open: right-click ▸ Open (macOS 14) or System Settings ▸ Privacy & Security ▸ Open Anyway (macOS 15+), or xattr -dr com.apple.quarantine /Applications/SpiceMac.app.

SHA-256: f2aec8992a339d883638ac84007733c1c7726e9ff3ce3e25283f0eec7994b05a

SpiceMac 0.1.6

Choose a tag to compare

@Ching367436 Ching367436 released this 09 Jun 04:11

Security release: the bundled TLS stack moves off EOL OpenSSL.

Security

  • OpenSSL upgraded to 3.5.6 (LTS, maintained to 2030), retiring the EOL 1.1.1 branch — the server-facing TLS stack is now current. Built under the old install names so spice-gtk loads it unchanged; the build verifies all ~72 of spice-gtk's OpenSSL symbols resolve in 3.x, and a real TLS connection to a Proxmox VM was confirmed. (The rest of the native stack is still the older UTM build — see SECURITY.md.)

Download

SpiceMac.app.zip — Apple Silicon, macOS 12+. Ad-hoc signed; to open: right-click ▸ Open (macOS 14) or System Settings ▸ Privacy & Security ▸ Open Anyway (macOS 15+), or xattr -dr com.apple.quarantine /Applications/SpiceMac.app.

SHA-256: 2a3e99a7da123b7b0bc739275358dcab3880b90d8870618e238709f2ccf95c98
Full changelog: CHANGELOG.md.

SpiceMac 0.1.5

Choose a tag to compare

@Ching367436 Ching367436 released this 09 Jun 03:41

USB-hardening + housekeeping release.

Changed

  • Hardened run-as-root.sh (the supported path for redirecting kernel-claimed USB devices): a clear trust-boundary warning + confirmation prompt (-y to skip), and documented honestly in the README/SECURITY.md. A privileged USB helper that would keep the SPICE stack unprivileged was scoped and deferred — macOS forces a design that's only a partial win and needs a Developer ID for the clean path.

Fixed

  • .vv no longer moved to root's Trash when launched via run-as-root.sh — the Trash-after-connect preference is skipped under root, so your file stays put.

Download

SpiceMac.app.zip — Apple Silicon, macOS 12+. Ad-hoc signed; to open: right-click ▸ Open (macOS 14) or System Settings ▸ Privacy & Security ▸ Open Anyway (macOS 15+), or xattr -dr com.apple.quarantine /Applications/SpiceMac.app.

SHA-256: 3f4cf75c76b2202b3eddae9a192566e2fa959b3066741b717460d5ae4d697a0e
Full changelog: CHANGELOG.md.

SpiceMac 0.1.4

Choose a tag to compare

@Ching367436 Ching367436 released this 09 Jun 02:30

Security

  • Multi-head monitor-config crash (DoS). A guest reporting more than one monitor config on a display channel (a protocol-legal multi-head configuration) tripped an assertion that aborted the whole client. Removed it — the display is now handled gracefully regardless of head count. Same class as a fix already in 0.1.0; this closes the second site.

Download

Grab SpiceMac.app.zip, unzip, move SpiceMac.app to /Applications. Apple Silicon, macOS 12+.

Ad-hoc signed, not notarized. To open: right-click ▸ Open (macOS 14) or System Settings ▸ Privacy & Security ▸ Open Anyway (macOS 15+), or:

xattr -dr com.apple.quarantine /Applications/SpiceMac.app && open /Applications/SpiceMac.app

Verify: shasum -a 256 SpiceMac.app.zip
SHA-256: cbca20cb5f829b678e4d912f1c03d2786a47fe7b78220d6cdef33e9011bd347a

Full changelog: CHANGELOG.md.

SpiceMac 0.1.3

Choose a tag to compare

@Ching367436 Ching367436 released this 09 Jun 02:13

Fixed

  • Blank screen on connect. The display no longer stays black until you click — the initial framebuffer is now painted as soon as the connection's renderer attaches (it was being dropped due to a SPICE-thread/Metal-device timing race).

Added

  • Move .vv to Trash after connecting (File menu, default on). Proxmox SPICE tickets are single-use and the file also carries the cluster CA, so the used file goes to the Trash (recoverable — not a hard delete) once it's opened a connection. Toggle in File ▸ Move .vv to Trash After Connecting.

Download

Grab SpiceMac.app.zip, unzip, move SpiceMac.app to /Applications. Apple Silicon, macOS 12+.

Ad-hoc signed, not notarized (needs a paid Apple Developer membership — help via the Sponsor button / ETH ching367436.eth). To open: right-click ▸ Open (macOS 14) or System Settings ▸ Privacy & Security ▸ Open Anyway (macOS 15+), or:

xattr -dr com.apple.quarantine /Applications/SpiceMac.app && open /Applications/SpiceMac.app

Verify: shasum -a 256 SpiceMac.app.zip
SHA-256: fd912b54539cca958d52755563ad46fb6a3019acfda018f17be9d71ac57e5cd7

Full changelog: CHANGELOG.md.

SpiceMac 0.1.2

Choose a tag to compare

@Ching367436 Ching367436 released this 09 Jun 01:11

Adds an app icon — a warm spice-palette squircle with a glowing remote-console screen and signal arcs — shown in the Dock, Finder, and ⌘-Tab. Otherwise identical to 0.1.1.

Download

Grab SpiceMac.app.zip below, unzip, move SpiceMac.app to /Applications. Apple Silicon, macOS 12+.

Ad-hoc signed, not notarized (Apple notarization needs a paid Apple Developer membership the project can't yet fund — help via the Sponsor button / ETH ching367436.eth). To open: right-click ▸ Open (macOS 14), or System Settings ▸ Privacy & Security ▸ Open Anyway (macOS 15+), or:

xattr -dr com.apple.quarantine /Applications/SpiceMac.app && open /Applications/SpiceMac.app

Verify your download:

shasum -a 256 SpiceMac.app.zip

SHA-256: 30ea01c7684426faf79aee997e96acca53173110f32966b939f15736f6aca95d

Bundles only the 26-framework LGPL/MIT/BSD/OpenSSL runtime closure — no GPL; license texts + LGPL §6 offer ship inside the app. Full changelog: CHANGELOG.md.

SpiceMac 0.1.1

Choose a tag to compare

@Ching367436 Ching367436 released this 09 Jun 00:23

Adds a prebuilt SpiceMac.app download alongside the source release. Apple Silicon, macOS 12+.

Download

Grab SpiceMac.app.zip below, unzip, and move SpiceMac.app to /Applications.

This build is ad-hoc signed, not Developer-ID-signed or notarized — Apple notarization needs a paid Apple Developer membership (US$99/yr) the project can't currently fund. It's safe to run; macOS just won't recognize the signer. Want signed + notarized builds? You can help fund the membership via the repo's Sponsor button. Prefer maximum trust? Build from source.

Opening it (Gatekeeper)

  • macOS 14: right-click the app ▸ OpenOpen.
  • macOS 15+: double-click once → Done, then System Settings ▸ Privacy & Security ▸ Open Anyway.
  • Terminal (either):
    xattr -dr com.apple.quarantine /Applications/SpiceMac.app
    open /Applications/SpiceMac.app

Verify your download

shasum -a 256 SpiceMac.app.zip

SHA-256: 5af408a0cb245ce51e9ab0a43c8d927af4f51d53494a7f64fc4d193d113c0732

Notes

  • Bundles only the 26-framework LGPL/MIT/BSD/OpenSSL runtime closure — no GPL (no QEMU). The verbatim license texts + LGPL §6 written offer ship inside the app at Contents/Resources/Licenses/.
  • OpenSSL 1.1.1w (fixes CVE-2022-0778); the rest is an older UTM sysroot — fine for personal use against trusted VMs (SECURITY.md).

Full changelog: CHANGELOG.md.

Prebuilt SPICE sysroot (arm64) v2 — OpenSSL 3.5.6

Choose a tag to compare

@Ching367436 Ching367436 released this 09 Jun 04:02

This is not the app — it's the pinned native dependency stack scripts/fetch-sysroot.sh downloads to build SpiceMac. For the app, see the latest release.

Same as sysroot-arm64-v1 but with OpenSSL upgraded to 3.5.6 (LTS, maintained to 2030) in place of the EOL 1.1.1w — built under the ssl.1.1/crypto.1.1 install names so spice-gtk (compiled against 1.1.1) loads it unchanged. The 26 @rpath frameworks + 19 GStreamer plugin archives (arm64); LGPL/MIT/BSD/OpenSSL only, no GPL.

License notices + LGPL §6 offer: THIRD-PARTY-LICENSES.txt.

SHA-256:

a7435e48731861b6babc6ea7804b9bdc801c7e03e808b460492cb6fab299d03f  spice-sysroot-macos-arm64.tgz

Prebuilt SPICE sysroot (arm64) — build dependency

Choose a tag to compare

@Ching367436 Ching367436 released this 09 Jun 01:29

This is not the app — it's the pinned native dependency stack scripts/fetch-sysroot.sh downloads to build SpiceMac. For the app, see the latest release.

spice-sysroot-macos-arm64.tgz contains the 26 @rpath-relocatable .framework bundles + 19 GStreamer static plugin archives (arm64) that SpiceMac links and embeds — the exact runtime/link closure, nothing more. Derived from a UTM Sysroot-macos-arm64 build, with the GPL components (QEMU, spice-server, swtpm, …) excluded: everything here is LGPL-2.1 / MIT / BSD-3 / OpenSSL. OpenSSL is 1.1.1w (already patched; upgrade-openssl.sh not needed when using this tarball).

License notices + the LGPL §6 written offer (corresponding source for these versions): THIRD-PARTY-LICENSES.txt.

SHA-256:

381f76f686c47e99bd347cd086b24096deae4e5d613d0ad1571fab8257f0f4d8  spice-sysroot-macos-arm64.tgz

fetch-sysroot.sh pins this digest and fails closed on mismatch.