English | 中文
Lock your Mac, let the external monitors nap, come back — and every window has been herded onto the laptop screen. macOS does this on sleep and never undoes it. DisplayWindowKeeper puts them back.
Lock/sleep never relaunches your apps, so each window keeps its CGWindowID for the
whole session. DisplayWindowKeeper uses that as a stable identity (not the title,
which changes) and re-applies the saved layout at +1.5s / +3s / +5s to beat macOS's
own re-arranging on wake.
- Layouts are keyed by the connected displays' UUIDs, so it restores only when the same monitors return.
- A fresh snapshot is taken the instant you lock.
- Only normal windows are moved; full-screen / minimized / dialogs are skipped.
macOS 26 (Tahoe) · Apple M5 Pro · Swift 6.3.3. Expected to work on any Apple Silicon Mac running macOS 13+.
./setup-cert.sh # once — self-signed cert so the grant survives rebuilds
./build.sh # compile, bundle, sign, refresh icon cachemacOS ties the Accessibility grant to the code signature. Ad-hoc signing changes on
every rebuild and loses the grant; the self-signed cert anchors a stable identity, so
you authorize once. build.sh falls back to ad-hoc if no cert exists.
open ./DisplayWindowKeeper.appGrant it in System Settings → Privacy & Security → Accessibility (required to move
other apps' windows). Autostart with ./install.sh, remove with ./uninstall.sh.
Menu: Restore now · Snapshot now · Pause · Open log · About. Recording is automatic (every 5s, on lock, and on display change).
| Constraint | Note |
|---|---|
| Apple Silicon only | Won't run on Intel |
| Gatekeeper | Self-signed, not notarized — first launch needs right-click → Open, or xattr -dr com.apple.quarantine DisplayWindowKeeper.app |
| Accessibility | Recipient grants it on their own Mac |
Sharing the source (they run ./build.sh) is smoother. A warning-free app needs a
paid Apple Developer ID and notarization.
- Uses the private API
_AXUIElementGetWindow(as yabai and Amethyst do). Fine for open source, but not Mac App Store eligible, and Apple could change it. As-is. - No cross-reboot restore — window IDs change after a relaunch. The lock/unlock case is fully covered.
MIT © 2026 ExWang
