TL;DR — Live wallpapers on macOS demand fullscreen multi-display rendering with low power cost — and have to live inside the App Store sandbox. Metal is the right pipeline for the job; the engineering is in pacing, power budget and surface handoff to the desktop.

Wallnetic Metal rendering pipelinePer-display CAMetalLayer + CVDisplayLink — sandbox-compatible, multi-refresh-rate aware. — /Metal pipeline Render coordinator NSScreen events Display 1 CAMetalLayer · 120 Hz Display 2 CAMetalLayer · 60 Hz Display 3 CAMetalLayer · 60 Hz Sandbox compositor surface handoff → 30 fps on battery, 60 fps on mains, pause when occluded → extended sRGB render → per-display profile conversion → App Group + helper process inside sandbox
Per-display CAMetalLayer + CVDisplayLink — sandbox-compatible, multi-refresh-rate aware.

A static wallpaper is one image. A live wallpaper is a 60 fps render that has to survive multi-display setups, dynamic display reconfiguration, sleep cycles, and the App Store sandbox. Wallnetic‘s rendering pipeline is more native engineering than the rest of the app combined.

Why Metal

  • Direct GPU control needed for procedural shaders and custom blends
  • Multi-display rendering — each connected display gets its own command buffer
  • Per-frame pacing that survives display refresh-rate mismatches
  • Compatibility with App Store sandbox (Metal works inside the sandbox without entitlement gymnastics)
  • Apple Silicon performance — Metal hits the GPU directly with negligible overhead

The pipeline

  1. A render coordinator subscribes to NSScreen notifications for display add / remove / reconfigure events
  2. One CAMetalLayer per connected display, sized to that display’s backing store
  3. One Metal command queue per display, sharing the same MTLDevice
  4. A frame timer driven by CVDisplayLink per display (refresh-rate aware)
  5. Per-frame: encode the shader pass, commit to the queue, present
  6. Surface handoff to the desktop via a private compositor pathway approved for sandboxed apps

Power budget

A live wallpaper running at full tilt on every display can dominate the system’s GPU activity. Power awareness is the difference between “I love it” and “I uninstalled because of battery”. The rules we follow:

  • Cap to 30 fps on battery; 60 fps only on mains power
  • Pause when the display is asleep, locked, or covered (occluded windows)
  • Pause when the user has explicitly set Low Power Mode
  • Defer expensive shader work to keyframes; interpolate between them
  • Use Metal’s hazard tracking sparingly — manual barriers are cheaper at our render shape

Sandbox constraints

  • No private APIs for window-server interaction — everything goes through approved entitlements
  • File access for user-supplied wallpaper assets uses security-scoped bookmarks
  • Render targets stay inside the app’s address space; the desktop compositor pulls them through the approved IPC surface
  • App Group sharing connects the main app and the helper process that holds the render loop

What was hard

  • Dynamic display reconfiguration mid-frame — fixed with a coordinator that drains in-flight buffers before rebuilding the layer set
  • Color profile mismatches between displays — fixed by rendering in extended sRGB and letting the display’s own profile do the final conversion
  • High-refresh ProMotion displays (120 Hz) mixed with 60 Hz externals — fixed by per-display CVDisplayLink instead of a single tick
  • Sandbox-compatible handoff path — required two App Store review cycles to land

What this buys

A wallpaper that feels alive on every display the user has, uses single-digit-percent of GPU time, survives the App Store review, and runs without entitlement warnings. The pipeline is invisible — which is the goal.

Frequently asked questions

Why not Core Animation for live wallpapers?

Core Animation is great for app UI but limited for fullscreen procedural rendering across multiple displays. Metal gives us the control to hit 60 fps with custom shaders on every connected display while staying inside the sandbox.

How much battery does this use?

A well-optimized Metal pipeline on Apple Silicon costs ~3–6% per hour at 60 fps on a single display. We cap to 30 fps on battery and pause rendering when the display is asleep or covered.

Working on something similar?

T-Square architects, builds and operates production systems for learning, AI and custom software products. Talk to a senior engineer if you want a second opinion on your design or roadmap.