# PeekDesktop **Repository Path**: fate83/PeekDesktop ## Basic Information - **Project Name**: PeekDesktop - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-21 - **Last Updated**: 2026-04-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # PeekDesktop ๐Ÿ‘€ **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.

PeekDesktop demo showing windows minimizing when you click the wallpaper

## Download ๐Ÿ“ฅ **[Download the latest release](https://github.com/shanselman/PeekDesktop/releases/latest)** | 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 can notify you when a newer GitHub Release is available. ## Documentation - **[Engineering Deep Dive](Docs/PeekDesktop-Engineering-Deep-Dive.md)** - architecture, shell internals, experiments, debugging workflow, undocumented API notes, and release tradeoffs ## How It Works 1. **Click empty desktop wallpaper or empty taskbar area** (not an icon or taskbar button) -> your desktop is revealed 2. **Stay on the desktop** -> click or drag icons, right-click, and rearrange things while windows stay hidden 3. **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 clicks - **`WindowFromPoint`** โ€” 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 window - **`SetWinEventHook(EVENT_SYSTEM_FOREGROUND)`** โ€” watches for when you switch back to an app - **`SetWindowPlacement`** โ€” 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 - ๐Ÿ‘€ **Peek Style** โ€” switch between Explorer and fly-away modes - โ„น๏ธ **About** โ€” version info - โฌ‡๏ธ **Check for Updates** โ€” see if a newer version is out and open the download page - โŒ **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 - **Auto-update notifications** via GitHub Releases ## 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](https://dotnet.microsoft.com/download/dotnet/10.0) ```bash git clone https://github.com/shanselman/PeekDesktop.git cd PeekDesktop dotnet build src/PeekDesktop/PeekDesktop.csproj ``` ### Run it ```bash dotnet run --project src/PeekDesktop/PeekDesktop.csproj ``` ### Publish a self-contained single-file exe ```bash # 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](https://github.com/MichalStrehovsky/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 # GitHub release update checker (via WinHTTP) โ”œโ”€โ”€ 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: - [x] Click empty wallpaper to peek - [x] Click empty taskbar area to peek (opt-in) - [x] Restore on app click or taskbar click - [x] Restore on a second wallpaper click - [x] Clicking or dragging desktop icons does **not** start peek - [x] Right-click desktop icons while peeking (context menus stay open) - [x] Desktop icons remain usable while peeking - [x] Exact window positions are restored - [x] GitHub release-based update checks - [x] Works with PowerToys Keyboard Manager (keyboard remapping) - [ ] Smooth minimize/restore animations (slide/fade) - [ ] Hotkey support (e.g., `Ctrl+F12` to 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](https://github.com/MichalStrehovsky/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`, `CreateIconIndirect` via P/Invoke - **No HttpClient** โ€” `WinHttpOpen`/`WinHttpSendRequest` uses the OS HTTP+TLS stack at zero binary cost - **No JSON source generator** โ€” hand-written `Utf8JsonReader`/`Utf8JsonWriter` for the two tiny JSON shapes we need - **No System.Reflection** โ€” PE version resources read via `GetFileVersionInfoExW` P/Invoke - **No managed delegates for WndProc** โ€” `UnmanagedCallersOnly` function pointers avoid marshaling overhead - **`OptimizationPreference=Size`** + `InvariantGlobalization` + stripped diagnostics Special thanks to [Michal Strehovskรฝ](https://github.com/MichalStrehovsky) โ€” the architect of .NET Native AOT โ€” whose [PR #5](https://github.com/shanselman/PeekDesktop/pull/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. ๐Ÿ™ ## License [MIT](LICENSE)