Commit Graph

8 Commits

Author SHA1 Message Date
enricobuehler e4b10f057a fix(headless/kde): make libei input work headlessly — portal + pre-seeded RemoteDesktop grant
ci / web (push) Successful in 27s
ci / bench (push) Successful in 1m41s
ci / docs-site (push) Successful in 31s
apple / swift (push) Successful in 1m31s
ci / rust (push) Successful in 2m5s
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 3s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
deb / build-publish (push) Successful in 2m17s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 4m56s
docker / deploy-docs (push) Successful in 17s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 4m25s
On a headless KDE appliance, libei input injection silently failed: the EIS socket comes from the
xdg RemoteDesktop portal, which never came up, and even up it would pop an unanswerable "Allow
remote control?" dialog. Three fixes in run-headless-kde.sh, all idempotent + safe on the dev box:
- Reach graphical-session.target: xdg-desktop-portal is ordered behind it and its start job fails
  without it, but a headless linger session never gets there and Fedora's target has
  RefuseManualStart=yes — drop that in once, then start the target.
- Start the portal with `start` (the old `try-restart` is a no-op when inactive — the first-boot
  case), so it actually comes up.
- Pre-seed the RemoteDesktop grant: vendor the `kde-authorized` permission-store GVariant DB and
  copy it to ~/.local/share/flatpak/db/ (never clobbering an existing one), so the portal grants
  RemoteDesktop without a dialog. Shipped by the RPM + .deb.

Diagnosed + fixed live on the Fedora 44 KDE box: libei devices RESUME and emit (MouseMove/keys).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 21:22:20 +00:00
enricobuehler 268733f968 fix(headless/kde): find the probe binary on PATH for packaged installs
apple / swift (push) Successful in 1m16s
ci / rust (push) Successful in 1m25s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6s
ci / web (push) Successful in 27s
ci / docs-site (push) Successful in 30s
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 6s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
deb / build-publish (push) Successful in 3m2s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 4m54s
docker / deploy-docs (push) Successful in 17s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 4m19s
run-headless-kde.sh gated KWin readiness on `$ROOT/target/release/punktfunk-host
probe-compositor`, else `cargo run`. On an RPM/.deb install ROOT resolves to /usr/share (no
target/ tree) and there's no Cargo.toml either, so the probe could never succeed: the session
unit hit its 30s readiness timeout, exited, and systemd restart-looped it forever — KWin never
reached the plasmashell step, so the streamed virtual output was an empty black desktop.
Add a `command -v punktfunk-host` branch (the packaged /usr/bin binary) between the source-tree
and cargo-run fallbacks. Verified live on the Fedora 44 KDE host: session goes stable
(NRestarts 0), plasmashell comes up, and a client streams the real desktop.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 18:21:31 +00:00
enricobuehler e1242546f2 fix(headless-kde): don't let set -e abort the session when Xwayland isn't up yet
ci / rust (push) Has been cancelled
The Xwayland-DISPLAY poll did `d=$(pgrep -a Xwayland | grep … | head -1)`, but
under `set -euo pipefail` pgrep/grep exit non-zero when Xwayland isn't running,
so the command substitution failed and `set -e` aborted the WHOLE script —
killing KWin with it — on the loop's first iteration instead of polling.

It only ever worked when launched from an interactive shell where Xwayland
happened to already be up (so pgrep matched on try 1). Under the systemd boot
appliance (punktfunk-kde-session.service) Xwayland isn't up that early, so the
session crash-looped (restart counter climbing, KWin never staying), the host
had no compositor, and clients couldn't connect.

Append `|| true` to the substitution so the loop polls as intended and a session
with no Xwayland at all still proceeds (DISPLAY just stays unset → warn).
Verified live: the unit now stays active (0 restarts), KWin + the wayland-kde
socket persist, probe-compositor reports ready, and a real client session
captured 4.8 MB of H.265 off the running serve --native host.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 21:25:28 +00:00
enricobuehler f3ff5f648a fix(headless-kde): complete the bare session — export DISPLAY, polkit agent, supervise plasmashell
ci / rust (push) Has been cancelled
A full Plasma login starts several pieces our bare headless session was missing, which
surfaced as three separate failures while streaming the KDE desktop:

- Steam (and other X11 apps) failed "can't open display": Xwayland runs, but KWin only
  sets DISPLAY for its own children — apps launched via the plasma menu / D-Bus activation
  never saw it. Detect the Xwayland display after KWin is ready and export it into the
  systemd/D-Bus activation environment.
- Discover / PackageKit couldn't install apps: polkitd (the policy engine) was running but
  no authentication *agent* (the prompt) was — so privileged installs got no authorization.
  Start polkit-kde-authentication-agent-1 (forcing the Qt Wayland platform, or it exits).
- The streamed desktop showed app windows but no wallpaper/panels: plasmashell had crashed
  and the old unsupervised `plasmashell &` never brought it back. Supervise it — restart for
  as long as KWin lives, so the desktop shell self-heals.

Validated live on this box: DISPLAY=:0 now in the --user environment (xdpyinfo on :0 works),
the polkit agent registers ("Listener online"), and plasmashell stays up under the supervisor.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 21:44:33 +00:00
enricobuehler 49d31b9cad fix(headless-kde): --no-block the portal restart so bring-up isn't blocked ~30s
ci / rust (push) Has been cancelled
A synchronous systemctl try-restart of the portal chain (xdg-desktop-portal is Type=dbus,
waits for its bus name) blocked the script ~30-40s before plasmashell started. --no-block
queues the restart and returns immediately — the portal only needs to be ready before the
first client streams (seconds later), not before plasmashell. Validated: plasmashell up in
1s (was ~30s); a virtual capture session against the fresh session streamed 720/720 frames
@720p120, zero-copy CUDA, no black screen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 19:33:54 +00:00
enricobuehler 9fdc3c3246 feat(headless-kde): reliable bring-up — readiness probe, fix portal ordering/env (roadmap #1 phase 1)
ci / rust (push) Has been cancelled
Headless KDE startup was a chain of timing-sensitive handoffs gated by a blind `sleep 2`,
the dominant source of black screens. Phase-1 fixes:

- New `punktfunk-host probe-compositor` subcommand: exits 0 iff the detected compositor is
  up AND ready to create a virtual output now. KWin gets a real check (connect + registry
  roundtrip + the privileged zkde_screencast global must be advertised — what the backend
  needs); gamescope/Mutter/wlroots create on demand so the probe just confirms Linux.
  (vdisplay::probe dispatcher + kwin::probe; reuses kwin.rs's existing roundtrip path.)
- run-headless-kde.sh: replace `sleep 2` with an active readiness wait (poll probe-compositor
  until ready, 30s deadline, and bail with kwin's log if kwin_wayland exits during init).
  Move the portal restart to AFTER readiness, and precede it with `systemctl --user
  import-environment` + `dbus-update-activation-environment` (the missing env import — the
  Sway script does this; without it a restarted portal inherits a stale/empty WAYLAND_DISPLAY,
  which is the "streams but eats no input/audio" failure). kwin's stderr → a log file.

Validated: probe-compositor exits 0 "Kwin ready" against the live session, exit 1 with a
clear diagnostic when the compositor is absent. 114 tests green, clippy/fmt clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 19:25:52 +00:00
enricobuehler 187c173e01 fix(headless-kde): restart xdg-desktop-portal after kwin comes up
ci / rust (push) Has been cancelled
The portal processes bind to the compositor that existed when they started; after a kwin
restart the stale instances point at a dead socket and RemoteDesktop/EIS input injection
times out ("EIS setup timed out"). Hit live: a fresh session streamed fine but ate no
mouse/keyboard until the portals were restarted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 14:29:31 +00:00
enricobuehler bfd64ce871 rename: lumen → punktfunk, everywhere
ci / rust (push) Has been cancelled
Full project rename, decided 2026-06-10:
- Crates/binaries: punktfunk-core / punktfunk-host / punktfunk-client-rs.
- C ABI: punktfunk_* symbols, Punktfunk* types, include/punktfunk_core.h,
  PUNKTFUNK_FEATURE_QUIC guard (header regenerated; cbindgen renames updated, incl.
  PUNKTFUNK_BTN_*/PUNKTFUNK_AXIS_* wire constants).
- Protocol: punktfunk/1 — control-plane magic LMN1 → PKF1, nonce salt lmn1 → pkf1.
  WIRE BREAK: clients must be rebuilt from this revision.
- Env knobs: PUNKTFUNK_VIDEO_SOURCE / PUNKTFUNK_COMPOSITOR / PUNKTFUNK_ZEROCOPY / ….
- Host config dir: ~/.config/punktfunk (the box's dir was migrated in place — the
  persistent identity is unchanged, pinned fingerprints stay valid).
- Swift package: PunktfunkKit + PunktfunkCore.xcframework + PunktfunkConnection
  (Sources/PunktfunkClient app + tests renamed with it); build-xcframework.sh updated.
- scripts/: 60-punktfunk.rules, punktfunk-host.service; OpenAPI doc regenerated.

Also: scripts/headless/run-headless-kde.sh — full headless Plasma bringup. Root cause of
"desktop but no apps/settings" over the stream: plasmashell launched without
XDG_MENU_PREFIX=plasma-, so the launcher resolved a nonexistent applications.menu and
rendered an empty menu. The script sets the complete KDE session env (menu prefix,
KDE_FULL_SESSION, session version) and rebuilds ksycoca before starting plasmashell.

Gate: 97/97 tests, clippy -D warnings (both feature sets), fmt, C-ABI harness PASS,
zero lumen references left outside .git.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 13:11:59 +00:00