project-switch v0.17
A borderless in-app webview window
Some of the things I open are local web apps that I’d rather see in a clean, chromeless window than in a browser tab. So commands can now carry webview: true, and instead of launching a browser they open the URL in a reusable, borderless WebView2 window. It’s mutually exclusive with command — config validation rejects setting both — and it merges across the project/client/global layers like any other command field.
The window runs as its own process via a hidden webview <url> subcommand, deliberately, so its tao event loop never collides with the egui launcher’s. There’s only ever one of these windows: summon_or_open uses FindWindowW on a fixed window title to spot an existing instance and just foregrounds it (restoring it first if minimised), otherwise it spawns a fresh process and grants it AllowSetForegroundWindow so it can raise itself.
The fiddly part was that a borderless window with a WebView2 child has no chrome and no way to be dragged — the child window swallows every mouse message, so the host never gets a WM_NCHITTEST over those pixels. The fix is an injected JavaScript shim: it treats the top strip as a drag handle and the window edges as resize handles, sets the right resize cursors, skips interactive elements so the app’s own header buttons still work, and forwards gestures over wry’s IPC channel. The host turns those into drag_window / drag_resize_window calls. The window also remembers where it was: its physical-pixel rect is saved to ~/.project-switch-webview.yml and reapplied with SetWindowPos on next open (which sidesteps tao’s cross-DPI mis-placement), unless the monitor it lived on has since been disconnected, in which case it falls back to the default placement.
One build wrinkle: the GNU cross-compile target can’t statically link the MSVC WebView2 loader, so docker-build.sh now finds and ships WebView2Loader.dll next to the exe.