Putting your live windows on an infinite canvas: the 'park & swap' trick (C++ / WGC / D3D11)

Published: (June 13, 2026 at 05:18 PM EDT)
3 min read
Source: Dev.to

Source: Dev.to

The problem

Alt-tab and multiple monitors are how we’ve juggled windows for 30 years. I wanted something spatial: zoom out, see every window at once; zoom into one, work in it for real; zoom back out. Like a map for your desktop. On Linux there’s niri and driftwm (they’re compositors). On Windows you can’t replace the compositor — so the question was: can you do this on top of Windows, with the real windows, in a single exe? The naive idea: capture every window, hide the originals off-screen, and draw the captures on a fullscreen surface. When the user “dives” into one, show the real window again. This breaks immediately. The moment a window is fully occluded or moved off the visible desktop, DWM stops compositing it — Windows.Graphics.Capture then returns black or stale frames. Your beautiful canvas fills with black tiles. The fix is to never fully hide a window: Each window is captured with Windows.Graphics.Capture (FreeThreaded frame pool, poll-based) into a persistent D3D11 texture. The window is “parked” in a 2px-tall visible strip at the bottom of the primary monitor. 2px is enough that DWM keeps compositing it, so the capture stays live — but it’s invisible behind the canvas. The canvas is a borderless fullscreen D3D11 swapchain. Each window is a 1:1-pixel textured quad placed in world space; pan/zoom is just a camera transform. A D2D/DWrite overlay draws labels, a world-anchored dot grid, the minimap, docks. When you zoom past a threshold (or double-click), the real HWND is moved onto its quad’s screen rect and given focus. Now you’re typing into the actual window — no input simulation, no proxying. Pull back (a thumb-button press) and it returns to the park strip. So there are two states per window: parked (you see its live texture on the canvas) and swapped-in (you see and use the real window). The transition is a SetWindowPos. IsBorderRequired(false) and the borderless-capture path black out capture on some Windows builds — removed. CopySubresourceRegion with content-sized copies + a drain-to-newest loop also produced black tiles; a single TryGetNextFrame + full CopyResource is the proven path. Added a constant-buffer field the pixel shader reads, but only bound the cbuffer to the vertex stage — every tile came out alpha=0 (invisible). If a shader stage reads a cbuffer, bind it to that stage. A single 559 KB exe (statically linked, no .NET/redist), ~3300 lines in one translation unit. Idle-throttled so it doesn’t cook the GPU. It has grown search-and-fly, sticky notes, a minimap, an app launcher, named workspaces. Demo + download: https://github.com/13auth/spatial-canvas Happy to answer questions about the capture/compositing pipeline.

0 views
Back to Blog

Related posts

Read more »

The spec is in the wrong place

My day job is at a large tech company. Hundreds of engineering teams, and every one of them is somewhere different on AI adoption. Some are still treating codin...

The Heuristics Say Don't

A culture that only records its disasters ends up with a biased archive. Wars documented, plagues chronicled, collapses catalogued. The quiet decades go unwritt...