From 9bea075791aef35729d831bf648d90228beba9c4 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Sun, 30 Aug 2026 22:43:30 +0200 Subject: [PATCH 1/2] fix(core): the ABI pin says 28, as the v28 bump demanded MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `abi_version_is_pinned` still asserted 27. The v28 bump (the touch capability, `punktfunk_connection_host_caps2`) arrived in Phase 0 without the pin update the test's own comment demands, and no gate on this branch ever ran punktfunk-core's tests — the PR's first full CI run is what caught it. The pin now says 28, with the v28 line beside it. Container tests: punktfunk-core 512 green, the pin suite included. --- crates/punktfunk-core/src/abi.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/punktfunk-core/src/abi.rs b/crates/punktfunk-core/src/abi.rs index b951ad83..6452fad4 100644 --- a/crates/punktfunk-core/src/abi.rs +++ b/crates/punktfunk-core/src/abi.rs @@ -6316,8 +6316,9 @@ mod abi_version_tests { /// exists so an accidental edit cannot drift the version silently. #[test] fn abi_version_is_pinned() { - assert_eq!(crate::ABI_VERSION, 27); - assert_eq!(super::punktfunk_abi_version(), 27); + // v28: `punktfunk_connection_host_caps2` + `PUNKTFUNK_HOST_CAP2_TOUCH` (additive). + assert_eq!(crate::ABI_VERSION, 28); + assert_eq!(super::punktfunk_abi_version(), 28); } } -- 2.54.0 From 5f786267dd3daf2bcd83fddb4b9c6a4c3b56a3f0 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Sun, 30 Aug 2026 22:43:32 +0200 Subject: [PATCH 2/2] fix(client): android and windows compile their own truth MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two platform breaks from the branch's first full CI run, invisible to the local gates. Android's cargoNdkClippy rejected the ring's in-stream surface as dead code, and it is right: the Android console holds the ring solely as the editor, so `input`, `take_command`, `take_cmds`, `damage`, `animating` and `key` (and the shell's `send_cmd`, and `MenuList::animating`) are driven only by the desktop overlay. They wear `cfg_attr(android, allow(dead_code))` rather than a cfg — cfg'ing them out cascades into their parameter types' imports — and the `host_actions::{self}` import shrinks to the one name every platform uses, with the desktop-only call fully qualified. Windows failed on the two `overlay_focus::gamescope_session()` calls T17 and the touch-devices log added: `overlay_focus` exists only on Linux (there is no gamescope to be inside anywhere else). Both go through a new `in_gamescope()` that answers `false` off Linux. Verified: the container gate green (64 / 242 / 227); clippy `-D warnings` for pf-presenter and the Windows client on the Windows box. The Android lints have no local run (cargo-ndk clippy dies in audiopus's cmake on a Mac) — the fixes answer exactly the four errors in the CI log, and CI is the check. --- crates/pf-console-ui/src/ring.rs | 14 ++++++++++++-- crates/pf-console-ui/src/shell.rs | 4 +++- crates/pf-console-ui/src/widgets.rs | 4 +++- crates/pf-presenter/src/run.rs | 19 +++++++++++++++---- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/crates/pf-console-ui/src/ring.rs b/crates/pf-console-ui/src/ring.rs index edd91cfb..1c767148 100644 --- a/crates/pf-console-ui/src/ring.rs +++ b/crates/pf-console-ui/src/ring.rs @@ -15,7 +15,7 @@ use crate::model::ConsoleCmd; use crate::pointer::{Pointer, PointerKind}; use crate::theme::{fill, glow_ring, rim_light, ring_scrim, soft_shadow, stroke, Fonts, W}; use crate::widgets::{ListMsg, MenuList, RowSpec}; -use pf_client_core::host_actions::{self, ActionInfo}; +use pf_client_core::host_actions::ActionInfo; use pf_client_core::menu_nav::{MenuDir, MenuEvent, MenuPulse}; use pf_client_core::overlay_actions::{chord_chip, key_vk, OverlayConfig, RingPlatform, SlotId}; use pf_client_core::ring::{RingCommand, RingFacts, RingInput}; @@ -254,6 +254,11 @@ impl Ring { self.facts = facts.clone(); } + // The next six are the IN-STREAM ring's surface, driven only by the desktop overlay + // (`skia_overlay`, Linux/Windows). The Android console holds the ring solely as the + // editor, so its clippy sees them unused — allowed rather than cfg'd out, because + // cfg'ing them would cascade into their parameter types' imports. + #[cfg_attr(target_os = "android", allow(dead_code))] pub(crate) fn input(&mut self, input: RingInput) { match input { RingInput::Turn { @@ -332,15 +337,18 @@ impl Ring { } } + #[cfg_attr(target_os = "android", allow(dead_code))] pub(crate) fn take_command(&mut self) -> Option { self.pending.pop_front() } + #[cfg_attr(target_os = "android", allow(dead_code))] pub(crate) fn take_cmds(&mut self) -> Vec { std::mem::take(&mut self.cmds) } /// Everything the drawing depends on, folded into one number for the damage gate. + #[cfg_attr(target_os = "android", allow(dead_code))] pub(crate) fn damage(&self) -> u64 { if !self.visible() { return 0; @@ -369,6 +377,7 @@ impl Ring { /// Is any spring, ease or entrance still short of where it is going? Read before a /// frame, so it describes the state the last render left behind. + #[cfg_attr(target_os = "android", allow(dead_code))] fn animating(&self) -> bool { if self.closing { return true; @@ -399,7 +408,7 @@ impl Ring { fn actions(&self) -> Vec { #[cfg(any(target_os = "linux", windows))] { - host_actions::cached(&self.facts.fp_hex) + pf_client_core::host_actions::cached(&self.facts.fp_hex) } #[cfg(not(any(target_os = "linux", windows)))] { @@ -788,6 +797,7 @@ impl Ring { /// Keyboard while open — the pad's vocabulary on keys: arrows move the highlight, Return /// activates, Escape backs out. Always consumed while open. + #[cfg_attr(target_os = "android", allow(dead_code))] pub(crate) fn key(&mut self, key: Key) -> bool { if !self.open() { return false; diff --git a/crates/pf-console-ui/src/shell.rs b/crates/pf-console-ui/src/shell.rs index 16b58cc9..ab1339ec 100644 --- a/crates/pf-console-ui/src/shell.rs +++ b/crates/pf-console-ui/src/shell.rs @@ -1070,7 +1070,9 @@ impl Shell { } /// One command straight onto the bus — the in-stream ring's host actions, which have no - /// screen and so no `Outbox`. + /// screen and so no `Outbox`. Only the desktop overlay calls it; the Android console's + /// ring is the editor alone. + #[cfg_attr(target_os = "android", allow(dead_code))] pub(crate) fn send_cmd(&self, cmd: ConsoleCmd) { self.bus.send(cmd); } diff --git a/crates/pf-console-ui/src/widgets.rs b/crates/pf-console-ui/src/widgets.rs index fb787ab8..b27e0548 100644 --- a/crates/pf-console-ui/src/widgets.rs +++ b/crates/pf-console-ui/src/widgets.rs @@ -188,7 +188,9 @@ impl MenuList { /// Is anything still on the move — an entrance, a focus ease, a spring, the scroll? /// The damage-gated stream overlay asks every frame and keeps redrawing until this is - /// false; the console draws every frame regardless and never needs to ask. + /// false; the console draws every frame regardless and never needs to ask — which is + /// why the Android console (editor only, no stream overlay) never calls it. + #[cfg_attr(target_os = "android", allow(dead_code))] pub(crate) fn animating(&self) -> bool { !self.settled } diff --git a/crates/pf-presenter/src/run.rs b/crates/pf-presenter/src/run.rs index f7d0b4a7..027e7d16 100644 --- a/crates/pf-presenter/src/run.rs +++ b/crates/pf-presenter/src/run.rs @@ -443,9 +443,7 @@ impl StreamState { cursor_chan: None, access: pf_client_core::access::SessionAccess::default(), session_notice: None, - touch_mouse: crate::touch::SteamTouchMouse::new( - pf_client_core::overlay_focus::gamescope_session(), - ), + touch_mouse: crate::touch::SteamTouchMouse::new(in_gamescope()), last_hint: None, hint_override: false, sent_client_draws: None, @@ -1631,7 +1629,7 @@ fn run_inner(mut opts: SessionOpts, mut mode: ModeCtl) -> Result // touch (design §5.5): no DIRECT device here, no twist can ever arrive. tracing::info!( devices = ?touch_devices(), - gamescope = pf_client_core::overlay_focus::gamescope_session(), + gamescope = in_gamescope(), "touch devices" ); window @@ -3030,6 +3028,19 @@ fn overlay_pointer(event: &Event, window: &sdl3::video::Window) -> Option bool { + #[cfg(target_os = "linux")] + { + pf_client_core::overlay_focus::gamescope_session() + } + #[cfg(not(target_os = "linux"))] + { + false + } +} + /// Every touch device SDL sees, as `(id, kind, name)` — logged at connect: under gamescope /// this is the tell for whether Steam Input hands the touchscreen through as touch (§5.5). fn touch_devices() -> Vec<(u64, &'static str, String)> { -- 2.54.0