Click empty desktop wallpaper (or empty taskbar area) to reveal your desktop — just like macOS Sonoma.
PeekDesktop brings macOS Sonoma's "click wallpaper to reveal desktop" feature to Windows 10 and 11. By default it uses Explorer's native Show Desktop behavior, and it also includes an optional Fly Away experimental style plus tray toggles for Require Double-Click, Peek on Desktop Click, and Peek on Taskbar Click. Click or drag desktop icons normally without accidentally triggering peek. When you're done, click any window, the taskbar, or the wallpaper again and everything comes right back where it was.
PeekDesktop is submitted to the Windows Package Manager community repository as Hanselman.PeekDesktop when tagged releases are published. After the community manifest is accepted, install it with:
winget install Hanselman.PeekDesktop
| File | Platform |
|---|---|
PeekDesktop-vX.Y.Z-win-x64.zip |
Intel/AMD (most PCs) |
PeekDesktop-vX.Y.Z-win-arm64.zip |
ARM64 (Surface Pro X, Snapdragon, etc.) |
No installer needed. Download the zip, extract it, and run PeekDesktop.exe. Release builds are self-contained, so you do not need to install .NET separately. It lives in your system tray and updates itself automatically — when a new version is available, it downloads, verifies the code signature, and restarts in place.
That's it. It just works.
PeekDesktop uses lightweight Windows APIs:
SetWindowsHookEx(WH_MOUSE_LL) — low-level mouse hook to detect desktop clicksWindowFromPoint — identifies the window under your cursorAccessibleObjectFromPoint) — distinguishes empty wallpaper from desktop iconsSendInput — fallback if taskbar button is unavailableEnumWindows + WINDOWPLACEMENT — captures exact position and state (including maximized) of every windowSetWinEventHook(EVENT_SYSTEM_FOREGROUND) — watches for when you switch back to an appSetWindowPlacement — restores windows to their exact previous positionsNo admin rights required. Uses < 5 MB RAM idle.
Right-click the tray icon for options:
When Windows is in dark mode, the tray menu also follows the system theme when supported by the OS.
| Feature | macOS Sonoma | PeekDesktop |
|---|---|---|
| Click wallpaper to peek | ✅ | ✅ |
| Restore on app click | ✅ | ✅ |
| Restore on second wallpaper click | ✅ | ✅ |
| Clicking/dragging icons does not trigger peek | ✅ | ✅ |
| Desktop icons accessible | ✅ | ✅ |
| Exact window position restore | ✅ | ✅ |
| System tray control | ❌ | ✅ |
| Multi-monitor support | ✅ | ✅ |
| Start with OS | Login Items | ✅ Registry |
| Smooth animation | ✅ | Fly Away mode |
Requirements: .NET 10 SDK
git clone https://github.com/shanselman/PeekDesktop.git
cd PeekDesktop
dotnet build src/PeekDesktop/PeekDesktop.csproj
dotnet run --project src/PeekDesktop/PeekDesktop.csproj
# Run the P/Invoke safety harness (invalid handles + stress/leak checks)
dotnet run --project src/PeekDesktop.InteropHarness/PeekDesktop.InteropHarness.csproj -- 10000
# Windows-friendly wrapper script
.\test.ps1 -Iterations 10000
# Verbose mode (prints per-test timing + leak probe diagnostics)
.\test.ps1 -Iterations 10000 -VerboseOutput
# For Intel/AMD
dotnet publish src/PeekDesktop/PeekDesktop.csproj -c Release -r win-x64 --self-contained -p:PublishSingleFile=true
# For ARM64
dotnet publish src/PeekDesktop/PeekDesktop.csproj -c Release -r win-arm64 --self-contained -p:PublishSingleFile=true
Release builds use .NET Native AOT — the exe is a fully native binary with no .NET runtime dependency. Current releases ship as self-contained single-file executables for both x64 and ARM64. Earlier experiments also used PublishAotCompressed (LZMA), but current builds favor compatibility and predictable startup behavior.
src/PeekDesktop/
├── Program.cs # Entry point, single-instance mutex
├── DesktopPeek.cs # Core state machine (Idle ↔ Peeking)
├── MouseHook.cs # WH_MOUSE_LL global mouse hook
├── FocusWatcher.cs # EVENT_SYSTEM_FOREGROUND monitor
├── WindowTracker.cs # Enumerate, minimize, and restore windows
├── DesktopDetector.cs # Identify desktop windows, icons, taskbar
├── Win32MessageLoop.cs # Win32 message loop + TaskbarCreated recovery
├── Win32TrayIcon.cs # Shell_NotifyIcon wrapper
├── Win32Menu.cs # Win32 popup menu wrapper
├── Win32Icon.cs # Programmatic icon via CreateIconIndirect
├── WinHttp.cs # WinHTTP wrapper (replaces HttpClient)
├── TrayIcon.cs # Tray icon business logic + menu wiring
├── AppUpdater.cs # In-place auto-updater (download, verify, swap, restart)
├── AppDiagnostics.cs # Logging via Trace/DebugView
├── Settings.cs # Hand-written UTF-8 JSON persistence + autostart
└── NativeMethods.cs # Win32 P/Invoke declarations
PRs welcome! Current status and next ideas:
Ctrl+F12 to toggle peek)PeekDesktop is a showcase for how small a .NET Native AOT application can get. Starting from a standard WinForms app, we systematically eliminated every managed framework dependency until the binary was pure Win32 P/Invoke — then compressed it to fit on a floppy disk.
| Version | Binary Size | What Changed |
|---|---|---|
| v0.4.5 | ~65 MB | Self-contained .NET (no AOT) |
| v0.5.0 | 17.5 MB | Enabled Native AOT |
| v0.6.0 | 4.2 MB | Dropped WinForms — pure Win32 P/Invoke for tray icon, menus, message loop |
| v0.6.1 | 2.3 MB | Replaced HttpClient with OS-native WinHTTP (winhttp.dll) |
| v0.7.2 | 1.88 MB | Eliminated JSON source generator, System.Reflection, Process.Start |
| v0.7.2 + LZMA | ~564 KB | LZMA compression via PublishAotCompressed |
What's left in the 1.88 MB (pre-compression)?
Utf8JsonReader/Utf8JsonWriter + async task machineryKey techniques:
Shell_NotifyIcon, CreatePopupMenu, TrackPopupMenuEx, MessageBoxW, CreateIconIndirect via P/InvokeWinHttpOpen/WinHttpSendRequest uses the OS HTTP+TLS stack at zero binary costUtf8JsonReader/Utf8JsonWriter for the two tiny JSON shapes we needGetFileVersionInfoExW P/InvokeUnmanagedCallersOnly function pointers avoid marshaling overheadOptimizationPreference=Size + InvariantGlobalization + stripped diagnosticsSpecial thanks to Michal Strehovský — the architect of .NET Native AOT — whose PR #5 inspired the final round of optimizations that eliminated the JSON source generator, reflection, and managed delegates. When the person who built the AOT compiler optimizes your app, you pay attention. 🙏