HydraIssues

Bring HydraExperienceNet kiosk Qt app to Windows with macOS feature parity
open feature Project: hydra-experiencenet Reporter: cederik 30 Apr 2026 06:24

Description

## Background

The kiosk grid + on-stream exit overlay + version label etc. all live in `HydraExperienceNet.app` (`/home/claude-user/hydra-experiencenet`), which today is **macOS-only at the kiosk install side**:

- `pkg/client/moonlight_darwin.go` has the real `isHydraExperienceNetInstalled()` probe.
- `pkg/client/moonlight_windows.go:92` is hardcoded `return false` — Windows kiosks fall back to raw Moonlight without any branded UI.
- `pkg/client/moonlight_linux.go:29` likewise.

Hydra-experiencenet's CI already has a `build-win-mac.yml` workflow capable of producing Windows builds (uses `scripts/build-arch.bat` + `scripts/generate-bundle.bat`), so the codebase isn't strictly Mac-only — it's that nothing on the kiosk-deployment side picks up a Windows build.

This issue is to take the Windows path from "compiles" to "first-class kiosk runtime with feature parity".

## Why now

We've shipped a stack of features in the last days (catalog refactor #122, Qt-app auto-updater #118, version label #121, fullscreen game-mode chain v6.1.4–v6.1.27, exit overlay, adaptive bitrate, orientation-adaptive resolution #130) — all on Mac kiosks. A Windows kiosk in the field today gets *none* of these. As we expand the fleet beyond Mac Minis (cheaper hardware options, Intel NUCs, repurposed PCs), Windows parity is unblocking.

## Feature parity checklist

For a Windows kiosk to be at parity with a Mac kiosk:

1. **Bundle install path on Windows**: package as `.msi` or self-extracting EXE; install to `C:\Program Files\HydraExperienceNet\` (or under user dir if unsigned). Provisioning recipe `hydraheadflatscreen-windows.yaml` adds a step analogous to `install-hydra-experiencenet` in `recipes/hydraheadflatscreen-macos.yaml`.
2. **Kiosk autoload at user logon**: scheduled task or Run-key registry entry, similar to how hydrabody self-launches under Windows auto-login.
3. **Fullscreen / game-mode equivalent**: macOS uses `NSWindowCollectionBehaviorCanJoinAllSpaces` + Spaces; Windows needs the equivalent (taskbar/icon hiding via Win32 API — same approach hydrabody's `kioskoverlay` already takes — plus per-monitor fullscreen).
4. **`isHydraExperienceNetInstalled()` on Windows**: replace the `return false` with a proper probe (registry uninstall key, or path check at `C:\Program Files\HydraExperienceNet\HydraExperienceNet.exe`).
5. **Stream subprocess invocation**: today `moonlight_darwin.go` launches `HydraExperienceNet stream <host> <app> <args>` as a subprocess. Windows needs the same argv handling — the Qt CLI is already cross-platform via Qt's QCoreApplication, just need the Windows file path.
6. **Auto-updater for the Windows Qt app**: today's `pkg/client/qtapp_windows.go` is a no-op stub returning `errQtAppUnsupported`. Replace with a real implementation: download `.msi`/`.exe` installer, invoke installer in silent mode, mark version file. Adapter pattern matches `qtapp_darwin.go`.
7. **Window/orientation API parity**: the local API on `:9741` (`/api/v1/window/hide`, `/api/v1/window/show`) needs the same Windows behaviour. Should "just work" via Qt cross-platform.
8. **Kiosk header version label**: already cross-platform in `KioskView.qml` via `Qt.application.version`. No change needed.
9. **Catalog UI + tile interactions**: cross-platform QML; should work as-is.
10. **Exit-to-menu overlay during streams**: floating Qt window with Spaces-equivalent. Windows has no Spaces, so the Mac-specific `setCollectionBehavior` is a no-op; the overlay just needs to be a top-most window. Validate this works via Qt's `Qt.WindowStaysOnTopHint`.

## Implementation order (suggested)

**Phase 1 — make a Windows kiosk technically possible:**
- Wire `isHydraExperienceNetInstalled()` on Windows, write the recipe step that installs from `releases.experiencenet.com/hydraexperiencenet/production/v<X.Y.Z>/HydraExperienceNet-<X.Y.Z>.msi` (CI to start producing this), add the auto-updater Windows path.

**Phase 2 — kiosk-mode polish on Windows:**
- Hide taskbar/icons (reuse hydrabody's pattern), fullscreen across all monitors, disable system hotkeys at the OS level.

**Phase 3 — visual + interaction parity validation:**
- Stream lifecycle, exit overlay, hide/show during streams, mouse/keyboard handling. Likely uncovers Win-specific bugs in QML paths that have only been tested on Mac.

## Out of scope

- Linux kiosk parity — different effort, separate issue.
- Touch input on Windows — most kiosks are mouse/keyboard; touch is a follow-up.

## Expected outcome

A Windows mini-PC enrolled with `hydraheadflatscreen` role behaves the same as a Mac Mini head: kiosk grid loads from the catalog, tile-tap streams an experience, exit overlay returns to the grid, agent auto-updates the Qt bundle every 6h, kiosk header shows the running version. A new venue gets to choose hardware on price/availability rather than OS.

## Related

- Today's adaptive bitrate (#130 MVP), orientation hint (#130), Qt auto-updater (#118), version label (#121), catalog refactor (#122) — all currently macOS-flavoured.