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:
@@ -193,6 +193,21 @@ which forwards *every* connected controller, each as its own player, on Linux, W
|
||||
console home. Pinning one restricts the session to that controller alone — single-player. The Android
|
||||
app has no such picker.
|
||||
|
||||
**Steam / guide button** (*Guide button* on Apple and Android) — *default: Automatic*, on every
|
||||
client. Where the guide (Xbox/PS/Steam) and quick-access presses go while streaming: **Send to
|
||||
host** forwards them raw, **This device** keeps them local. Automatic forwards everywhere except
|
||||
Gaming Mode, where SteamOS opens its own menus for those buttons no matter what — forwarding raw
|
||||
there opens *both* menus at once, the local one covering the stream. The full story, including how
|
||||
to reach the host's menus when the raw press stays local, is on the
|
||||
[Input page](/docs/input#the-guide-button-xbox--ps--steam-and-quick-access).
|
||||
|
||||
**Hold Select for guide** — *default: Automatic*, on every client. The gesture that presses the
|
||||
host's guide button from any controller: hold Select (Back/View) on its own for about a third of a
|
||||
second, and keep holding for the host's long-press (a Gaming-Mode host's Quick Access Menu, on a
|
||||
regular pad). Automatic arms it only where the raw guide press can't reach the host cleanly —
|
||||
Gaming Mode, iPhone/iPad, Apple TV — because the gesture has a cost: a Select *tap* arrives a beat
|
||||
late, and a game that expects a *held* Select would trigger it. Set **On** or **Off** to overrule.
|
||||
|
||||
**Capture system shortcuts** — *default: on.* Offered by the Linux and Windows apps, the console home
|
||||
and Decky; Windows spells the row out as *Capture system shortcuts (Alt+Tab, Win, …)*. On a Deck it
|
||||
matters only for a keyboard you attached yourself, for the reason the paragraph below gives: Gaming
|
||||
|
||||
@@ -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**:
|
||||
|
||||
@@ -111,6 +111,15 @@ for about a second and a half, or close the "game" from the Steam overlay. Eithe
|
||||
and drops you straight back to Gaming Mode. A quick press of the same four only releases captured
|
||||
input, so it is safe to hit by accident.
|
||||
|
||||
**The Steam and `…` buttons stay with the Deck while streaming.** SteamOS opens its own menus for
|
||||
them no matter what, so forwarding the raw press as well opened *both* menus at once — the Deck's
|
||||
covering the stream. To reach the **host's** menus instead: **hold Select** for the host's Steam
|
||||
menu ([how it works](/docs/input#the-guide-button-xbox--ps--steam-and-quick-access)), or open the
|
||||
Punktfunk panel — while a stream runs it grows a **Host menus** section whose two buttons,
|
||||
**Steam menu on host** and **Quick access on host**, press the button on the host and close the
|
||||
Deck's own menu so the host's shows through. Want the raw forwarding back? Settings →
|
||||
**Steam / guide button** → *Send to host*.
|
||||
|
||||
## Updating
|
||||
|
||||
The plugin **checks for updates itself** — no Decky store needed. It covers **both** the plugin *and*
|
||||
|
||||
Reference in New Issue
Block a user