v0.9.0
[0.9.0] - 2026-07-11
Added
- Windows apps can be registered as URL-scheme handlers on Linux (#421, #694 — host-side groundwork). When an app carries URL schemes (
mailto,https,slack,vnc, …), its.desktopnow getsx-scheme-handler/<scheme>entries and theExecaccepts a URL, so clicking such a link on the host opens it in the Windows app — the URL is passed straight through to the app (not mapped to a$HOMEfile path). A shared policy module (denylist + strict scheme regex + a/app-cmd sanitizer) blocks dangerous schemes (file:,javascript:,data:, …) and neutralizes command-line injection at both registration and launch. Discovery now auto-harvests each app's schemes from the guest (per-schemeUrlAssociationsdefault, per-appCapabilities\URLAssociations, and the UWP manifest'swindows.protocol), so an app that handlesmailto/https/etc. is registered automatically — no manualapp.tomledit needed.
Changed
- The optional Windows debloat pass opts out of more ads / telemetry (#669, #684, thanks @GameSoul7Eugene). Broadened the advertising and suggestion opt-outs (advertising ID, lock-screen "tips & tricks", Start / Settings / search suggestions, silent consumer-app auto-install), added a disable for the SQM/CEIP telemetry scheduled task, and applied RDP-friendly visual-effect tweaks — all kept to a conservative, reversible scope.
Fixed
- A discovered Windows app can no longer silently seize the host's default
http/httpshandler (security hardening). Registering a Windows app as a URL-scheme handler ranxdg-mime defaultfor every declared scheme — so an app discovered from the (semi-trusted) guest could, viaapp install --mimeordoctor --fix, become the system default forhttp/httpsand receive every web link the user clicks (session tokens included). Those two universal web schemes are now excluded from the automatic default grab: a Windows browser still works as a URL target (app run <browser> https://…) and stays available in "Open with", but making it your web default is now an explicit, opt-in choice.mailtoand vendor schemes are unaffected. - The session window-reaper no longer mis-kills a just-relaunched app, nor mass-kills every session on a transient scan failure (#680 follow-up). Closing a document and immediately reopening it could SIGTERM the fresh session (the reaper tracked apps by name, and a relaunch overwrites the process marker) — the reaper now binds each reap to the exact PID it armed against. And a non-zero
wmctrlexit (the window manager momentarily busy) was read as "no windows open", so two transient failures in a row reaped every running app; a failed scan is now treated as a failure, not as zero windows. - The install one-liner now auto-installs
gitif it's missing instead of aborting (#705, thanks @numericOverflow). On a fresh system withoutgit(e.g. Linux Mint 22) thecurl … | bashinstaller failed at the clone step with "git is required for remote install" — even though it auto-installs every other dependency. It now installsgitthrough the same package-manager path as the rest, and only errors out (with a manual-install hint) if the package manager can't provide it. - kio-fuse is no longer reported "not installed" when it actually is (#697, thanks @twkirk161). The Info/health check only looked for the
kio-fusebinary in a fixed set of paths, so on distros that put it elsewhere — Fedora Kinoite / KF6-versioned libexec, or the Debian multiarch/usr/lib/<triplet>/libexec/kio-fuse(three levels deep, missed by the old two-level glob) — it read as missing even though reverse-open guest-disk mounting (#616) works fine. Detection now also matches the multiarch path and, as the authoritative signal, theorg.kde.KIOFuseD-Bus activation service that the mount actually calls. - The reverse-open listener now autostarts with the tray, and tray Quit stops it deliberately (#691, thanks @notnotno). The listener was only (re)started by
pod startand the app-launch path, so starting justwinpodx gui(or logging in with the tray autostart) left Windows→Linux "Open with" silently dead even with the feature enabled. And Quit only killed it by accident: the listener is a double-forked daemon that inherits its parent's command line, so thepkill …guiin Quit matched it only when it happened to be started from the GUI settings panel. The tray now runs the idempotent listener self-heal at startup (off the UI thread) and Quit callsstop_listener()explicitly. - Fast suspend/resume recovery actually subscribes to systemd-logind now (#690, thanks @notnotno). The tray's
PrepareForSleepD-Bus subscription passed a bare Python function toQDBusConnection.connect, which PySide6 rejects at runtime (called with wrong argument types) — so the fast post-resume pod refresh (#225) never actually armed and every install silently fell back to the 30 s status poll, logging a warning at eachwinpodx gui/tray start. The subscription now uses a QObject receiver with aSLOT("onPrepareForSleep(bool)")signature (held on the tray icon so it can't be garbage-collected out from under the connection), verified live againstorg.freedesktop.login1. - A Windows app that stays resident after you close its window no longer shows "RUNNING" forever (#680, thanks @mdshahalam3). A FreeRDP RemoteApp client only exits when the guest disconnects, but Office keeps its process (and the RemoteApp session) resident after the document window closes — so the session never terminated, the app listed RUNNING indefinitely, and it left a half-stuck
\\tsclient\homeredirect that broke the next open. The system-tray helper now watches every session's RAIL windows and, once an app's windows have all closed (with a short debounce), terminates the stuck session so it drops off the running list. It runs in the long-lived tray (not the short-livedwinpodx app runprocess, which exits immediately) so it fires for menu / CLI launches too. Best-effort (X11/XWayland withwmctrl); it only reaps a session whose window was actually seen, so a launching or window-less app is never reaped early. - FreeRDP's cosmetic
[get_next_comma]: Invalid quoted argumentwarning at every RemoteApp launch is silenced (#680, thanks @mdshahalam3). It came from the quotedcmd:"<UNC>"form winpodx keeps so a file path with spaces isn't split; the FreeRDP subprocess now runs withWLOG_FILTER=com.winpr.commandline:FATAL, which mutes that one WLog tag without changing the delivered command line (the/log-filtersflag is parsed too late to suppress its own parser's warning). - Office 2016 (MSI) apps no longer collapse into one broken "Microsoft Office 2016 component" entry (#680 regression, thanks @mdshahalam3). 0.8.0's Start-Menu-only discovery read each shortcut's raw
.TargetPath, but MSI installs use advertised shortcuts (Windows Installer "Darwin descriptors") whose target resolves to a per-product icon stub underC:\WINDOWS\Installer\{ProductCode}\(e.g.xlicons.exe). Those stubs all share the file description "Microsoft Office 2016 component", so Word/Excel/PowerPoint/Outlook all looked identical and deduplicated into a single non-runnable entry — they vanished fromwinpodx app list. Advertised shortcuts are now resolved to their real installed executable viaMsiGetShortcutTarget+MsiGetComponentPathbefore recording the target; normal (Click-to-Run / direct) shortcuts are unaffected. - "Open with" a Windows app while it's already running now reliably opens the file in a fresh window (#675 thanks @ajeshchrist, #680 thanks @mdshahalam3). It used to silently do nothing (the already-running path swallowed every error), or — when the file was delivered to the running app via the guest agent — pop "Access denied", or hang ~30 s before a crash-looking relaunch. Root cause: the guest runs multi-session RDP, so any attempt to hand a file to the already-visible app lands in a different session (the agent even runs in the autologon console session, which has no per-session
\\tsclient\homeredirect at all). So winpodx no longer attempts a "warm" delivery — opening a file while the app is running goes straight to a fresh RemoteApp window carrying the file (whose credentialed connect also unlocks / re-logs-in the session). A file outside the shared$HOME/ media locations raises a visible error instead of vanishing. Also hardened the silent-failure surface: the.desktopExecuses%f(multi-select opens one window per file instead of a no-op), andnotify-send+file://URIs resolve by absolute path so error toasts and file arguments survive a stripped-PATH launch. - The guest lock-screen check is now session-scoped, and the cold launch waits longer for a slow guest (#680/#675, thanks @mdshahalam3 & @ajeshchrist). winpodx waits for the guest desktop to be interactive before creating a RemoteApp window, but the check used a machine-wide
Get-Process LogonUI— so a lock screen in another session (the console, or a stale disconnected RAIL session) wrongly reported the app's own session as locked and made launches wait the full timeout. It now matches LogonUI/explorer by session ID. The cold launch also waits up to 45 s (was 20 s) for a slow guest to finish autologon before drawing the window, so it no longer paints a stale logon frame over the app.
Contributors
Thanks to everyone who reported issues or contributed fixes in this release: @notnotno (#694, #691, #690), @twkirk161 (#697), @mdshahalam3 (#680), @ajeshchrist (#675), @numericOverflow (#705), and @GameSoul7Eugene (#669, #684).