feat(clients/input): system buttons route around local overlays
ci / rust-arm64 (pull_request) Failing after 48s
apple / swift (pull_request) Successful in 1m18s
apple / screenshots (pull_request) Skipped
ci / docs-site (pull_request) Successful in 1m22s
android / android (pull_request) Successful in 3m22s
ci / web (pull_request) Successful in 1m39s
windows / build (aarch64-pc-windows-msvc) (pull_request) Successful in 1m0s
ci / rust (pull_request) Canceled after 10m44s
windows / build (x86_64-pc-windows-msvc) (pull_request) Canceled after 1m43s
ci / rust-arm64 (pull_request) Failing after 48s
apple / swift (pull_request) Successful in 1m18s
apple / screenshots (pull_request) Skipped
ci / docs-site (pull_request) Successful in 1m22s
android / android (pull_request) Successful in 3m22s
ci / web (pull_request) Successful in 1m39s
windows / build (aarch64-pc-windows-msvc) (pull_request) Successful in 1m0s
ci / rust (pull_request) Canceled after 10m44s
windows / build (x86_64-pc-windows-msvc) (pull_request) Canceled after 1m43s
Pressing guide/Steam/QAM collided with the client device's own shell: iOS 26 opens its Game Overlay for the Home press (no app opt-out until iOS 27 makes it a user setting), and a Gaming-Mode client opened BOTH Steam overlays for one press — the local one covering the stream. Two cross-client tier-P settings, zero wire changes: - system_buttons (auto|forward|local): raw guide+misc1 passthrough. Auto forwards everywhere EXCEPT under gamescope, where SteamOS reacts to the same physical press no matter what. - guide_gesture (auto|on|off): hold Select ALONE ~350ms sends the HOST's guide, down until release — held on, that's the host's long-press, which opens a Gaming-Mode host's QAM for regular pads. A Select tap is delivered on release with its up TAP_PRESS (50ms) behind, because per-transition sends fold into seq'd GamepadState snapshots and a back-to-back pair can coalesce into no press at all. A Select inside a combo (the escape chord) passes through untouched. Auto arms it only where the raw press can't reach the host cleanly: gamescope, iOS/iPadOS, tvOS. The same SelectGesture rules live in pf-client-core (pure state machine + unit tests), the Apple client (mask-diff adaptation in GamepadCapture), and Android's GamepadRouter. Settings rows on every surface (GTK, WinUI, console UI, Decky, Apple x2, Android x2) with profile plumbing throughout. punktfunk-session grows a control socket ($XDG_RUNTIME_DIR[/app/$FLATPAK_ID]/punktfunk-session-ctl.sock — the one runtime path a flatpak and the host see identically): 'guide'/'qam' verbs inject synthetic taps. The Decky panel gains a Host menus section (visible while the client runs) whose buttons press the host's Steam/QAM and close the local menu so the host's shows through. iOS 27's GCControllerHomeButtonSettingsManager deep-link is a TODO (the class needs the Xcode 27 SDK to compile). Docs: input, client-settings, steam-deck. Design: punktfunk-planning design/system-buttons-routing.md. Gates: docker clippy --all-targets --locked -D warnings + tests (pf-client-core 88 incl. 6 new gesture tests, pf-console-ui 47), cargo fmt --all --check, swift build (macOS), gradle kit+app compile, decky tsc --noEmit + py_compile. clients/windows not compiled (no box).
This commit is contained in:
@@ -98,6 +98,39 @@ there the client stops opening the controller at all, which is the point of the
|
||||
**Ctrl+Alt+Shift+D** or the client's own UI to leave instead. The Apple and Android apps keep
|
||||
watching for the chord either way.
|
||||
|
||||
### The guide button (Xbox / PS / Steam) and Quick Access
|
||||
|
||||
A controller's **guide button** — the Xbox logo, the PS button, the Deck's **Steam** button — is
|
||||
meant to open menus **on the host**: the Steam overlay, or a Gaming-Mode host's Steam menu. Some
|
||||
devices want that button for themselves, so every client also carries a gesture that works
|
||||
everywhere:
|
||||
|
||||
**Hold Select (Back / View) on its own for about a third of a second.** The host sees its guide
|
||||
button go down, and it stays down for as long as you hold — so keeping it held reads as a long
|
||||
press on the host, which is how SteamOS opens the **Quick Access Menu** for a regular pad. A quick
|
||||
tap of Select still reaches the game, delivered when you let go (a beat late). Select pressed as
|
||||
part of a combo — including the leave chord above — passes through untouched.
|
||||
|
||||
What the raw button does, per client:
|
||||
|
||||
- **Linux & Windows desktop, macOS, Android** — the guide press is forwarded to the host. If
|
||||
Steam Big Picture or the Xbox Game Bar is also watching for it *on the device in your hands*,
|
||||
both may react — that's a local setting on that device, not something the stream can suppress.
|
||||
- **Steam Deck / Gaming Mode** — the **Steam** and **`…`** buttons stay with the Deck by default:
|
||||
SteamOS always opens its own menus for them, so forwarding the raw press as well opened BOTH
|
||||
menus at once, the Deck's on top of the stream. Reach the host's menus with **hold-Select**, or
|
||||
with the Punktfunk panel's **Host menus** buttons ([Steam Deck page](/docs/steam-deck)). The
|
||||
old behavior is one setting away: **Steam / guide button → Send to host**.
|
||||
- **iPhone / iPad** — iOS reserves the Home press for its own Game Overlay, so hold-Select is the
|
||||
reliable route to the host's overlay. On iOS 27 or later you can also hand the button to the
|
||||
app yourself, in the system's per-controller Home-button setting.
|
||||
- **Apple TV** — tvOS never delivers the Home press to apps; hold-Select is the only route.
|
||||
|
||||
Both halves are [settings](/docs/client-settings#input), per profile like everything else:
|
||||
**Steam / guide button** (Automatic / Send to host / This device) and **Hold Select for guide**
|
||||
(Automatic / On / Off). Automatic picks the behavior above for each platform — the gesture stays
|
||||
off where the raw button already works, so games that use a *held* Select keep it.
|
||||
|
||||
## Mouse modes
|
||||
|
||||
There are two, and they are a per-client setting called **Mouse input**:
|
||||
|
||||
Reference in New Issue
Block a user