PeekDesktop ๐
April 24, 2026 ยท View on GitHub
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 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.
Download
๐ฅ Download the latest release
| File | Platform |
|---|---|
PeekDesktop-vX.Y-win-x64.zip | Intel/AMD (most PCs) |
PeekDesktop-vX.Y-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.
Documentation
- Engineering Deep Dive - architecture, shell internals, experiments, debugging workflow, undocumented API notes, and release tradeoffs
- Auto-Updater - how the in-place auto-update system works, security model, swap dance, testing
How It Works
- Click empty desktop wallpaper or empty taskbar area (not an icon or taskbar button) -> your desktop is revealed
- Stay on the desktop -> click or drag icons, right-click, and rearrange things while windows stay hidden
- Click any app, the taskbar, or empty wallpaper again -> all windows restore to exactly where they were
That's it. It just works.
Peek Styles
- Show Desktop (Explorer) โ the default and recommended mode. Uses Explorer's native Show Desktop behavior.
- Fly Away (Experimental) โ animates windows offscreen. Fun but has known quirks with external window management (Win+D, taskbar). Use for the visual flair, but know it can get confused if the shell changes window state behind its back.
Under the Hood
PeekDesktop uses lightweight Windows APIs:
SetWindowsHookEx(WH_MOUSE_LL)โ low-level mouse hook to detect desktop clicksWindowFromPointโ identifies the window under your cursor- MSAA hit-testing (
AccessibleObjectFromPoint) โ distinguishes empty wallpaper from desktop icons - UI Automation hit-testing โ classifies empty taskbar space without firing on Start, pinned apps, or tray buttons
- Taskbar Show Desktop button click โ primary path, immune to keyboard remapping (PowerToys, etc.)
- Win+D
SendInputโ fallback if taskbar button is unavailable EnumWindows+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 positions
No admin rights required. Uses < 5 MB RAM idle.
System Tray
Right-click the tray icon for options:
- โ Enabled โ toggle the peek feature on/off
- ๐ Start with Windows โ launch automatically at login
- ๐ฑ๏ธ Require Double-Click โ optionally require a double-click on the desktop to trigger peek
- ๐ฎ Pause While Gaming / Full-Screen โ on by default for exclusive full-screen and known gaming fullscreen apps
- ๐ Peek on Taskbar Click โ optionally trigger peek from empty taskbar space
- ๐ช Restore All Windows on App Switch โ on by default; in Explorer show desktop mode, taskbar/Alt+Tab app switches restore all hidden windows behind the selected app
- ๐ Peek Style โ switch between Explorer and fly-away modes
- โน๏ธ About โ version info
- โฌ๏ธ Check for Updates โ download and install newer versions automatically
- ๐ Auto-Check for Updates โ on by default; silently checks for updates on startup
- โ Exit โ quit PeekDesktop
When Windows is in dark mode, the tray menu also follows the system theme when supported by the OS.
What's New
- Small Native AOT single-file builds for both x64 and ARM64
- Peek on Taskbar Click โ optional trigger from empty taskbar space
- Dark tray menu support โ follows Windows dark mode when available
- Taskbar button Show Desktop โ bypasses keyboard remappers (PowerToys Keyboard Manager, etc.)
- Pause While Gaming / Full-Screen โ avoids interference during gaming sessions
- Require Double-Click โ optional double-click trigger for desktop peek
- In-place auto-updater โ downloads, verifies Authenticode signature, swaps, and restarts automatically
macOS Sonoma vs PeekDesktop
| 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 |
Build from Source
Requirements: .NET 10 SDK
git clone https://github.com/shanselman/PeekDesktop.git
cd PeekDesktop
dotnet build src/PeekDesktop/PeekDesktop.csproj
Run it
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
Publish a self-contained single-file exe
# 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 packaging
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.
Architecture
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
Contributing
PRs welcome! Current status and next ideas:
- Click empty wallpaper to peek
- Click empty taskbar area to peek (opt-in)
- Restore on app click or taskbar click
- Restore on a second wallpaper click
- Clicking or dragging desktop icons does not start peek
- Right-click desktop icons while peeking (context menus stay open)
- Desktop icons remain usable while peeking
- Exact window positions are restored
- GitHub release-based update checks
- Works with PowerToys Keyboard Manager (keyboard remapping)
- Smooth minimize/restore animations (slide/fade)
- Hotkey support (e.g.,
Ctrl+F12to toggle peek) - Per-monitor peek (only minimize windows on the clicked monitor)
- Exclude specific apps from being minimized
.NET Native AOT โ The Size Journey ๐พ
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)?
- ~1.2 MB โ .NET Native AOT runtime (GC, threading, exception handling, type system)
- ~0.4 MB โ
Utf8JsonReader/Utf8JsonWriter+ async task machinery - ~0.2 MB โ App code, P/Invoke stubs, string literals
- ~0.08 MB โ PE headers and metadata
Key techniques:
- No WinForms, no System.Drawing โ
Shell_NotifyIcon,CreatePopupMenu,TrackPopupMenuEx,MessageBoxW,CreateIconIndirectvia P/Invoke - No HttpClient โ
WinHttpOpen/WinHttpSendRequestuses the OS HTTP+TLS stack at zero binary cost - No JSON source generator โ hand-written
Utf8JsonReader/Utf8JsonWriterfor the two tiny JSON shapes we need - No System.Reflection โ PE version resources read via
GetFileVersionInfoExWP/Invoke - No managed delegates for WndProc โ
UnmanagedCallersOnlyfunction pointers avoid marshaling overhead OptimizationPreference=Size+InvariantGlobalization+ stripped diagnostics
Special 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. ๐