Commit Graph

14 Commits

Author SHA1 Message Date
enricobuehler f88d0ae4dc feat(touch): cross-client touch-input modes on Linux + Windows
ci / web (push) Successful in 43s
ci / rust (push) Failing after 53s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
decky / build-publish (push) Successful in 16s
ci / docs-site (push) Successful in 1m5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 7s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 6s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m41s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m53s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 52s
apple / swift (push) Successful in 4m41s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 54s
ci / bench (push) Successful in 6m30s
docker / deploy-docs (push) Successful in 23s
flatpak / build-publish (push) Failing after 8m9s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
android / android (push) Has been cancelled
apple / screenshots (push) Has been cancelled
arch / build-publish (push) Has been cancelled
deb / build-publish (push) Has been cancelled
Bring the SDL presenter (Linux/Deck + Windows) to parity with the Android and
Apple clients: a persisted TouchMode selects how a touchscreen drives the host —

  * Trackpad (default): relative cursor with pointer ballistics + the shared
    gesture vocabulary (tap = left click, two-finger tap = right click,
    two-finger drag = scroll, tap-then-drag = held left drag, three-finger tap =
    cycle the stats overlay).
  * Direct pointer: the cursor jumps to and follows the finger (absolute).
  * Touch passthrough: every finger is a real host touchscreen contact.

Previously the presenter had no finger handling, so SDL synthesized mouse events
from touch and — under the stream's relative-mouse lock — walked the host cursor
into the corner (the reported Deck bug). SDL touch->mouse synthesis is now off;
DIRECT touchscreens route through a new incremental gesture engine (a port of
Android TouchInput.kt / Apple TouchMouse.swift), while INDIRECT trackpads keep
driving the mouse. Fingers map through the aspect-fit letterbox onto the content
rect.

TouchMode lives in the shared trust::Settings (default trackpad, so passthrough
is opt-in like the other clients); the GTK and WinUI settings screens both gained
a "Touch input" picker. Gesture engine, letterbox mapping, and settings
back-compat are unit-tested (28 tests green); clippy -D warnings clean; full
Linux client + session build verified on-host.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 23:51:29 +02:00
enricobuehler ef5808254a refactor(windows): remove the legacy in-process builtin stream path
The real Windows client is the spawned punktfunk-session Vulkan binary
(pf-client-core); the in-process builtin GUI stream — reachable only via
PUNKTFUNK_BUILTIN_STREAM=1 — was dead weight kept alive by nothing and a
recurring source of wasted effort. Remove it: delete present/render/input/
audio.rs and the builtin remainder of session/video.rs, rip all the builtin
wiring (app/mod, connect, stream), and make connect always spawn.

Preserve the two shipped keepers that happened to live in those files by
relocating them to a new probe.rs: run_speed_probe (the per-host network speed
test used by the Settings speed page and --headless --speed-test) and
decodable_codecs (the codec-capability advert on the probe connect). Trim gpu.rs
to just the Settings adapter picker (adapter_names + helpers). --headless now
supports only --speed-test — the in-process decode/frame-counter went with the
pump.

Drops the now-orphaned deps opus, wasapi, crossbeam-channel, anyhow; keeps
ffmpeg-next (probe::decodable_codecs still needs it). Net 4432 deletions.
Statically verified (module wiring, imports, orphaned symbols/deps all clean);
the type-level compile runs on the windows-amd64 CI runner, which has the
toolchain this non-Windows host lacks.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 01:22:09 +02:00
enricobuehler 9514a8c0e2 fix(client): correct Linux/Windows "Forwarded controller" copy for multi-controller
ci / web (push) Successful in 51s
ci / docs-site (push) Successful in 56s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 11s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 10s
decky / build-publish (push) Successful in 52s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
apple / swift (push) Successful in 4m39s
ci / bench (push) Successful in 6m27s
windows-host / package (push) Successful in 8m34s
flatpak / build-publish (push) Successful in 7m15s
docker / deploy-docs (push) Successful in 24s
android / android (push) Successful in 12m49s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 4m16s
deb / build-publish (push) Successful in 12m50s
arch / build-publish (push) Successful in 16m32s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m53s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 19m44s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m14s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 17m53s
ci / rust (push) Successful in 25m18s
release / apple (push) Successful in 22m3s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m57s
apple / screenshots (push) Successful in 18m56s
The relm4 (Linux) and native (Windows) shells spawn punktfunk-session, which
since the native-plane rework forwards ALL controllers by default — but the
"Forwarded controller" settings dropdowns still described the pre-rework world
("Automatic (most recent)", "Exactly one controller is forwarded to the host").

The dropdown already lists every detected pad and wires set_pinned(None)=all /
set_pinned(key)=single-player; this fixes only the misleading labels, subtitle,
tooltip, and stale leading comments to match: Automatic forwards every real
controller (each its own player); pick one to force single-player.

cargo check -p punktfunk-client-linux green; Windows is windows-gated (pure
string edits, CI windows.yml).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 21:53:07 +02:00
enricobuehler a95b518ef3 fix(windows): show app version on About screen + capitalize Punktfunk on licenses
ci / docs-site (push) Successful in 51s
ci / web (push) Successful in 57s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9s
decky / build-publish (push) Successful in 19s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 7s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 7s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 38s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 2m1s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 2m3s
apple / swift (push) Successful in 5m1s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m4s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m25s
ci / bench (push) Successful in 8m10s
docker / deploy-docs (push) Successful in 20s
arch / build-publish (push) Successful in 11m11s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m47s
android / android (push) Successful in 16m10s
deb / build-publish (push) Successful in 16m57s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 17m47s
ci / rust (push) Successful in 23m26s
apple / screenshots (push) Successful in 19m57s
The About settings card had no version at all — add an identity block (app name +
"Version <CARGO_PKG_VERSION>", the workspace version) at the top, the WinUI
Settings convention and matching the Apple client's "Version X" wording. Also
capitalize the brand name on the licenses screen (was lowercase "punktfunk").

Verified against the pinned windows-reactor source + cargo fmt --check; full
Windows link left to CI (Windows-only crate).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 02:46:45 +02:00
enricobuehler d0d9bd5bfb feat(resize): mid-stream resolution resize — host hardening (H1–H5) + session-binary Match window (C1)
design/midstream-resolution-resize.md Phase 0 + Phase 1.

Host (Phase 0):
- H1/H5: per-backend Reconfigure acceptance gate — reject for gamescope
  (all sub-modes; a resize must never relaunch the title) and under the
  per-client-mode identity policy (a resize would resolve a different
  display slot). Synthetic stays reconfigurable on purpose (the protocol
  test source; the C-ABI roundtrip test rides it). Plus a 500 ms host-side
  min-interval backstop against Reconfigure spam.
- H2: rollback/corrective ack — the data plane reports the mode actually
  live after a failed rebuild (or a refresh the backend capped) through a
  reconfig_result channel; the control task forwards it as a second
  accepted Reconfigured so the client's mode slot self-corrects.
- H3: live stats mode — SendStats reads a packed AtomicU64 (w|h|hz)
  updated on every switch instead of latching the session-start mode.
- H4: registry::retire(gen) — a mode-switch rebuild force-releases the
  superseded Linux display, so linger/forever keep-alive policies don't
  accumulate kept monitors at stale modes. VirtualOutput carries pool_gen
  (fresh AND reused) and the Pipeline tuple threads it to the switch arm.

Client (Phase 1, default off):
- Settings: match_window policy + persisted last window size; exposed as
  the Resolution tri-state (Native / Match window / explicit) in the Skia
  console, GTK and WinUI settings pages.
- pf-presenter: window opens at the persisted size; Hello mode follows the
  window's pixel size; D2 trigger discipline (400 ms debounce to
  resize-end, ≥1 s spacing, even-floor + ≥320×200 clamp, each distinct
  size requested at most once — covers rejects and host rollbacks) as a
  pure, unit-tested decision; HUD line + title refresh on a switch.
- Session binary wires both --connect and --browse paths; the WinUI shell
  is session-always, so this covers Windows too.

Verified: workspace tests + clippy green; synthetic --remode end-to-end;
live session-binary run (window at persisted 1000×600 → Hello 1000×600@60).
On-glass per-backend matrix (Mutter/KWin/gamescope-reject, keep-alive
accumulation) still pending before any default flip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 12:53:47 +02:00
enricobuehler 38b9f310e2 feat(clients): tiered stats overlay everywhere — Compact/Normal/Detailed on every platform
ci / docs-site (push) Successful in 1m5s
apple / swift (push) Successful in 1m10s
ci / web (push) Successful in 1m12s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m46s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m57s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 53s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m10s
ci / bench (push) Successful in 5m43s
decky / build-publish (push) Successful in 17s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 9s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 6s
release / apple (push) Successful in 8m10s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 9s
arch / build-publish (push) Successful in 11m59s
android / android (push) Successful in 13m3s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 6m39s
docker / deploy-docs (push) Successful in 18s
apple / screenshots (push) Successful in 5m32s
deb / build-publish (push) Successful in 14m54s
ci / rust (push) Successful in 23m19s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m53s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m44s
flatpak / build-publish (push) Failing after 35s
Ship the Android client's 3-tier stats-overlay semantics in every other client
(design/stats-unification.md vocabulary): Off → Compact (one line: fps · e2e ms ·
Mb/s + loss flag) → Normal (mode + e2e p50/p95 + loss counters) → Detailed
(decoder path, HDR tag, per-stage latency equation).

Apple: new StatsVerbosity in PunktfunkKit persisted under punktfunk.statsVerbosity
(migrates the legacy hudEnabled bool: explicit off → Off, else Normal). The
existing three-finger tap (TouchMouse, trackpad/pointer modes only — touch
passthrough untouched) now cycles the tiers instead of toggling, matching
Android; ⌃⌥⇧S (menu + captured-state monitor) cycles the same ladder. Tiered
StreamHUDView (compact glass pill / headline HUD / full equation HUD); the iOS
corner disconnect also shows in Compact (the pill carries no button). Tier
pickers on iOS, macOS, tvOS and the gamepad settings UI.

Session stack (Linux + Windows + Deck share punktfunk-session): shared
pf_client_core::trust::StatsVerbosity; Settings grows stats_verbosity with a
show_stats fallback, and writes keep the legacy bool in sync so pre-tier
binaries reading the same JSON agree on off vs on. Ctrl+Alt+Shift+S cycles the
tier and re-renders the OSD immediately from the last stats window; the stdout
stats: line always carries the full Detailed text so the shell status card and
scripts keep a stable shape; --stats bumps Off → Normal without demoting a
richer tier. Tier pickers in the GTK dialog, the WinUI settings page and the
console-UI settings row; shortcut copy updated (GTK shortcuts window, Windows
help, session README). The Windows legacy builtin path keeps its bool HUD.

Tests: tier migration/round-trip in trust.rs, tiered stats_text output in
pf-presenter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 01:42:46 +02:00
enricobuehler f4850625bd feat(clients/windows): game library page + session window placement + help polish
apple / swift (push) Successful in 1m10s
android / android (push) Successful in 4m56s
arch / build-publish (push) Successful in 5m56s
audit / bun-audit (push) Successful in 13s
audit / cargo-audit (push) Successful in 1m34s
ci / web (push) Successful in 1m11s
windows-host / package (push) Successful in 7m57s
ci / docs-site (push) Successful in 1m27s
release / apple (push) Successful in 8m39s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m26s
ci / bench (push) Successful in 5m0s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m16s
apple / screenshots (push) Successful in 5m35s
ci / rust (push) Successful in 10m32s
decky / build-publish (push) Successful in 13s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 4m47s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m36s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
deb / build-publish (push) Successful in 6m38s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m39s
flatpak / build-publish (push) Successful in 5m32s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 11m0s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 10m33s
docker / deploy-docs (push) Successful in 18s
UX polish batch 2 (plan workstreams D/E5/E6):

- D: a mouse/keyboard game library page over pf-client-core::library (the GTK
  ui_library.rs counterpart): responsive 2-6 column poster grid (2:3 portraits,
  store badge, monogram placeholder while art streams in), loading / error+retry
  / empty / grid states, tap-to-play via a normal spawn carrying --launch id.
  Poster bytes land in a disk cache (%LOCALAPPDATA%\punktfunk\art-cache) so the
  Image widget loads file:/// URIs (reactor has no from-bytes source) and
  revisits render instantly. Reached from a paired host's "Browse library..."
  menu item behind the new "Show game library (experimental)" Settings toggle
  (the shared library_enabled field, Apple/GTK parity). A Shared::library_gen
  generation guard keeps a superseded fetch from publishing (speed-test pattern).

- E5: the session window opens at the shell's own top-left (--window-pos, new
  SessionOpts::window_pos) instead of centered on the primary display - streams
  land on the monitor the shell is on, and the hide/restore handoff reads as one
  window changing content. Fullscreen follows that display.

- E6: the Help shortcuts add Alt+Enter and the controller escape chord
  (LB+RB+Start+Back, hold to disconnect).

Also: rustfmt normalization of the merged probe helper.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 00:43:46 +02:00
enricobuehler 573b2af334 feat(clients/windows): single-window handoff, shared settings store, console-UI surfacing
UX polish batch 1 (clients/windows/ui-polish-plan.md, workstreams W0/A1/B/C/E):

- W0: the shell's duplicated trust/settings structs are gone — src/trust.rs
  re-exports pf-client-core's, so the shell and the spawned session binary share
  ONE Settings shape over client-windows-settings.json. Fixes real bugs: the
  shell's saves no longer drop session-side fields; the stats-overlay toggle
  (show_hud -> show_stats, serde alias migrates old files) and the forwarded-
  controller pick now actually reach the spawned session. The "Streaming engine"
  Settings combo is gone (PUNKTFUNK_BUILTIN_STREAM=1 stays as the dev A/B knob).

- Forwarded-controller pinning by stable key (vid:pid:name, pf-client-core's
  format): persisted as forward_pad, applied by the shell's own service at
  startup AND by the session binary in session_params (both OSes — the session
  never applied the pin before).

- A1 single window: the shell hides itself when the spawned session window
  presents its first frame ({"ready":true}) and restores + foregrounds on the
  child's exit — exactly one visible Punktfunk window at any time. Restore runs
  before the request-access cancel gate so a Ready/Cancel race can't strand the
  shell hidden.

- C console UI: punktfunk-session --browse gains --json-status (ready when the
  library window presents; error line on a failed start), and the shell
  surfaces it — "Open console UI" on paired hosts' menus, plus a controller-
  detected hint card targeting the most recent paired host (x64 only; aarch64
  ships no skia ui feature). Browse spawns hide/restore the shell like streams.

- B responsive: minimum window size (420x360); the hosts header collapses to
  icon-only buttons below 700 px; the session status card shrinks instead of
  clipping (max_width); busy pages, help actions, licenses and long labels wrap.

- E polish: session exe gets the app icon (winresource + WM_SETICON via the new
  pf-presenter win32.rs); both exes share an explicit AppUserModelID on
  unpackaged runs (packaged identity wins) so the windows group as one taskbar
  app across the visibility handoff; "Start streams fullscreen" toggle passes
  --fullscreen (GTK parity); connects stamp KnownHost::last_used; the connect
  target is stashed for every route so "Connecting to X" always names the host.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 00:25:02 +02:00
enricobuehler d6647b9183 feat(clients/windows): port the Vulkan session client to Windows — session-always
The punktfunk-session Vulkan client (clients/linux-session, now clients/session)
builds and runs on Windows; the WinUI shell spawns it for every stream. Verified
live: 10-bit HEVC via Vulkan Video on both AMD (iGPU) and NVIDIA, 5120x1440 at
130 fps / 8 ms end-to-end on the RTX 4090.

- pf-ffvk: Windows bindgen branch (FFMPEG_DIR + PF_FFVK_VULKAN_INCLUDE, no
  pkg-config); provisioning fetches Vulkan-Headers (pinned v1.4.309).
- pf-client-core: builds on Windows — WASAPI audio (audio_wasapi.rs, cfg-swapped
  via #[path], same surface as the PipeWire twin), VAAPI/dmabuf gated inline
  (chain = vulkan -> software), trust reads the WinUI shell's %APPDATA% stores
  (parity tests pin both serialized shapes), Settings gains adapter/hdr_enabled
  (serde-defaulted; Linux stores unaffected).
- pf-presenter: builds on Windows — dmabuf module Linux-gated; SDL keyboard grab
  while captured (Alt+Tab/Win reach the host); pick_device ranks discrete over
  integrated (device 0 was the iGPU on hybrid boxes — the silent footgun) and
  honors PUNKTFUNK_VK_ADAPTER (the Settings GPU pick, exported by the session).
- run loop: block in one SDL wait woken by input AND decoded frames (a per-
  session forwarder pushes a FrameWake user event) instead of a 1 ms poll —
  measured 111%% -> 5%% of a core (NVIDIA), 86%% -> 3.5%% (AMD), stats unchanged.
  The pump's decode-fence wait became once-per-window sampling (no per-frame
  pipeline stall; the stat now shows true backlog).
- pf-console-ui: builds on Windows (skia-safe msvc prebuilts); font lookup falls
  through fontconfig aliases to concrete DirectWrite families (Consolas/Segoe UI)
  — browse/coverflow works, verified against a live host.
- WinUI shell: session-always via new src/spawn.rs (GTK spawn.rs port —
  CREATE_NO_WINDOW, stdout contract, kill handle); the Stream screen is a status
  card (chips + stage lines from the child's stats). The legacy in-process
  D3D11VA path stays behind Settings "Streaming engine" / PUNKTFUNK_BUILTIN_
  STREAM=1 as the A/B baseline until Phase 8 deletes it. SessionParams.video_caps
  makes the HDR toggle real.
- clients/linux-session renamed to clients/session (builds for both OSes).
- CI/MSIX: both workflows build/test both bins with widened path filters; the
  MSIX ships punktfunk-session.exe. ARM64 session builds --no-default-features
  (rust-skia has no aarch64-pc-windows-msvc prebuilts; flip when it does).

A/B on this box (5120x1440 HEVC vs home-worker-5): NVIDIA Vulkan 130 fps / 8 ms
e2e / 1.6 ms decode — clearly better than the built-in path. The AMD iGPU VCN
saturates at ~52 fps where its own D3D11VA does ~70 — Adrenalin Vulkan decode is
slower on APU silicon; discrete RDNA validation gates Phase 8.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 23:21:36 +02:00
enricobuehler 8a4b0c7bae feat(windows): surface shortcuts on a Help screen; exit fullscreen when the stream stops
apple / swift (push) Successful in 1m10s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m13s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m13s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 44s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 41s
android / android (push) Successful in 4m11s
ci / rust (push) Failing after 1m21s
ci / web (push) Successful in 55s
apple / screenshots (push) Successful in 5m52s
ci / docs-site (push) Successful in 1m2s
arch / build-publish (push) Has been cancelled
ci / bench (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
The in-stream keyboard shortcuts were only reachable deep in Settings > Input.
Move them to a dedicated Help screen reached from a Help button on the host
list (mirrors the Licenses screen — a hook-free page routed from root), and drop
the reference card out of Settings so there's one home for it.

Fullscreen (F11) was a window-style toggle that stream stop never undid, so
disconnecting while fullscreen left the GUI borderless-fullscreen. Split
toggle_fullscreen into is_fullscreen/enter_fullscreen/exit_fullscreen sharing a
module-level SAVED_PLACEMENT, and have input::uninstall() call exit_fullscreen()
on teardown. exit_fullscreen is a no-op when nothing was saved, so it's safe on
every stream stop and idempotent with F11 — fullscreen is now streaming-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 11:17:19 +02:00
enricobuehler bf07700c74 feat(clients): windows shortcut parity (Ctrl+Alt+Shift+S, F11) + surface stream shortcuts
apple / swift (push) Successful in 1m7s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m39s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m19s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 54s
android / android (push) Successful in 4m45s
windows / build (x86_64-pc-windows-msvc) (push) Failing after 57s
arch / build-publish (push) Successful in 5m31s
ci / rust (push) Failing after 1m11s
ci / web (push) Successful in 56s
ci / docs-site (push) Successful in 1m0s
apple / screenshots (push) Successful in 5m56s
ci / bench (push) Successful in 5m17s
deb / build-publish (push) Successful in 4m53s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
decky / build-publish (push) Successful in 26s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 3s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m35s
flatpak / build-publish (push) Successful in 4m42s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Failing after 8m48s
docker / deploy-docs (push) Successful in 21s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Failing after 7m54s
Windows was missing two of the four stream shortcuts the GTK client has:
Ctrl+Alt+Shift+S (toggle the stats overlay live) and F11 (toggle fullscreen).
Add both to the low-level keyboard hook — S flips a HUD_VISIBLE atomic seeded
from Settings::show_hud at install (Settings is the default, the key overrides
it for the session, matching GTK), F11 drives a borderless-fullscreen toggle on
the window HWND and re-locks the pointer geometry for the new client rect. Both
are consumed locally, never sent on the wire.

Surface the full key set in two places, on both clients:
- in the UI: a read-only "In-stream keyboard shortcuts" reference card in the
  Windows Settings > Input section (the counterpart of the GTK Shortcuts
  window), plus the expanded HUD hint; the Linux keyboard hint gains F11.
- at stream start: a bottom-centre banner listing the shortcuts for the first
  few seconds of every session, independent of the HUD setting. Linux gets the
  matching start-flash of its capture hint (capture engages on map and hid it,
  so the keys were never shown until the first release).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 22:55:45 +02:00
enricobuehler 84fcbd3345 feat(clients/windows): WinUI UX batch - tile hover, Settings NavigationView, modal slide-up
Bump windows-reactor + windows to a4f7b2cb (from b4129fcc) for the new
PointerEntered/PointerExited events; migration is mechanical renames only
(SymbolGlyph->Symbol, placeholder->placeholder_text, on_changed->
on_text_changed/on_toggled, on_menu_item_clicked->on_item_clicked,
on_ready->on_mounted). New runtime model: reactor lost its build.rs, so the
client build.rs stages the WinAppSDK bootstrap via
windows-reactor-setup::as_framework_dependent() and main calls
windows_reactor::bootstrap() (missing either = 0x80040154 at launch);
staged filenames unchanged, so pack-msix and the MSIX manifest are untouched.

- Host tiles: WinUI pointer-over fill (ControlFillSecondary) via the new
  pointer enter/exit events, hover id in root state (backend-wired handlers
  bypass the reconciler flush, like the flyout clicks).
- Settings: stock NavigationView sidebar (Windows-Settings pattern) with
  Display/Video/Input/Audio/About panes, built-in back arrow, wide content
  column, and a per-section content slide-up tween. The section card is
  KEYED by section: an in-place diff across sections re-sets a reused
  ComboBox's items (clearing WinUI's selection) but skips selected_index
  when the values compare equal, rendering a blank selection - the key
  forces a remount. Card titles/descriptions dropped; per-control guidance
  moved to hover tooltips (ToolTipService).
- New "Show the stats overlay (HUD)" setting (show_hud, default on),
  honored mid-stream via the 400 ms HUD re-render.
- Add-host modal: entrance fade + slide-up tween (scrim fades with it).
- Self-initiated disconnect (Ctrl+Alt+Shift+D -> Ended(None)) returns to
  the host list silently instead of raising the error banner.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 18:23:25 +02:00
enricobuehler 9d6798b8e0 feat(clients/windows): GPU picker, disconnect shortcut, richer stream HUD
- Settings gains a GPU selector (shown only on multi-GPU boxes): the picked
  DXGI adapter drives decode + present, persisted as Settings.adapter and
  applied at the next stream - gpu.rs now caches the shared device keyed by
  the resolved preference (env PUNKTFUNK_ADAPTER > Settings > the window's
  monitor's adapter) so a change needs no app restart.
- Ctrl+Alt+Shift+D disconnects the session (consumed locally, captured or
  released): the hook releases capture and trips the session stop flag,
  plumbed through the stream-page handoff; the pump winds down and the UI
  navigates back to the host list.
- Stream HUD extended: codec chip (HEVC/H.264/AV1), display-side line from
  the render thread (presents/s + capture-to-decoded vs capture-to-on-glass
  p50), session line (host name, duration, network-lost frames, skipped
  backlog frames), and both shortcut hints incl. the new disconnect.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 16:41:16 +02:00
enricobuehler 670f5a40a6 feat(clients/windows): screen-module restructure + parity features (speed test, native mode, capture UX)
Structure: split the 1400-line app.rs into per-screen app/ modules (mod=root/
router, hosts, connect, pair, speed, settings, licenses, stream, style) with
shared card/header/busy-page builders and setting_combo/toggle helpers; the
re-render rule (thread-driven state lives in root use_async_state, flows down
as props) is now documented at the module root.

Parity features the other clients already had:
- "Native display" resolves the real monitor mode at connect
  (MonitorFromWindow -> EnumDisplaySettingsW; was a hardcoded 1080p60)
- per-host network speed test: saved-host card button + a results screen
  (probe burst -> goodput/loss -> ~70% recommended bitrate applied in one
  tap; stale runs invalidated by generation) and `--headless --speed-test`;
  the bitrate setting becomes a free-form NumberBox so the recommendation
  round-trips
- forget host (ContentDialog confirm -> KnownHosts::remove_by_fp)
- settings: forwarded-controller picker (pads/pinned/set_pinned now wired),
  gamepad type, host compositor, capture-system-shortcuts; the previously
  dead Settings.compositor / inhibit_shortcuts are honored (shortcuts off =
  Alt+Tab/Alt+Esc/Ctrl+Esc/Win act locally)
- click-to-recapture after a Ctrl+Alt+Shift+Q release; the HUD hint tracks
  the live capture state

Perf: the input hook caches lock geometry (clip rect + contain-fit scale) at
engage instead of GetClientRect per WM_MOUSEMOVE; the audio jitter ring trims
via drain() and reuses the render scratch buffer.

Validated on the bare-metal box: --discover, synthetic-host loopback E2E
(TOFU -> clock skew -> HEVC negotiate -> D3D11VA init -> session end),
speed-test E2E, and the WinUI shell rendering in the console session via
PsExec (SSH/session-0 cannot create windows, pre-existing 0x80070005).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 12:16:19 +02:00