Commit Graph
5 Commits
Author SHA1 Message Date
enricobuehler 2d43275fcb fix(core/abi)!: stop exporting 149 unprefixed macros into every embedder's namespace
ci / rust-arm64 (pull_request) Failing after 15s
ci / web (pull_request) Successful in 1m6s
windows / build (aarch64-pc-windows-msvc) (pull_request) Successful in 1m8s
ci / docs-site (pull_request) Successful in 1m15s
apple / swift (pull_request) Successful in 1m26s
apple / screenshots (pull_request) Skipped
android / android (pull_request) Successful in 3m10s
windows / build (x86_64-pc-windows-msvc) (pull_request) Successful in 1m57s
ci / rust (pull_request) Successful in 6m25s
BREAKING (C header only): constants such as MAX_PADS, TAG_LEN, ABI_VERSION,
INPUT_MAGIC and the whole BTN_/AXIS_ family are now PUNKTFUNK_-prefixed.

cbindgen emits a bare #define per `pub const`, so those names landed in the
namespace of every C program that includes the header. The rename table already
said this was the rule and already carried the handful someone had noticed —
and its own comment spells out why it matters: a clashing #define silently
takes the last definition rather than failing to compile, so the failure mode
is a wrong value, not a build error. This is the remaining 149.

Associated constants are deliberately left alone. cbindgen already qualifies
those with their type name, which is the very property whose absence makes a
bare MAX_PADS dangerous — they are namespaced, just not by us.

Nothing in this repository consumed the unprefixed spellings except one Swift
test, which sat next to lines already using the prefixed form because its
constant happened never to have been added to the table; it is updated here.
The C harness links and runs against the regenerated header.

Scheduled deliberately: the sweep flagged this for a release boundary, and
0.24.0 has shipped. External C embedders using the old spellings must add the
prefix; there is no silent breakage, since the old names simply stop existing.
2026-08-04 20:52:58 +02:00
enricobuehlerandClaude Opus 5 6edd700910 fix(client/gamepad): honor an explicit controller type — the per-pad arrival was re-declaring the physical pad
The "Controller type" setting reached the Hello and stopped there. Every pad then
opened with a GamepadArrival carrying its DETECTED kind, and the host builds each
virtual device from that arrival — the session default is only the fallback for a
pad that never declares one. So "emulate my DualSense as a DualShock 4" put a
DualSense on the host the instant the controller connected, and no amount of
reconnecting helped. Apple and the native clients both; Android already applied
the setting per pad.

The setting now rides the declaration too: explicit wins for every slot, Automatic
keeps per-pad detection so a mixed session stays honest. The physical kind still
drives the LOCAL feedback paths — a DualSense emulated as a DualShock 4 keeps its
lightbar and adaptive triggers, and a Deck keeps its rumble keep-alive.

Regressed in 97c67b26 / 76be4c3e (multi-controller support); ships in 0.19.x.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 16:56:44 +02:00
enricobuehlerandClaude Opus 4.8 68b9f108ab feat(gamepad/apple): send Share/Create as BTN_MISC1 + pin wire bits to the C ABI
G5: buttonMask mapped the dedicated share/create/capture element onto BTN_BACK,
the same bit as View (buttonOptions). On an Xbox-Series pad those are two
distinct physical buttons, so Share was indistinguishable from View on the
host and never delivered the capture bit the host already decodes (DualSense
mute / Steam quick-access). Route it to BTN_MISC1 instead, matching the Rust
client's `Button::Misc1 => wire::BTN_MISC1`. Adds `misc1` to GamepadWire and
allButtons so a held capture button is released on flush like the others.
(On-glass verify owed on a real Xbox-Series pad; a clone pad that exposes one
button as both buttonOptions and Share now emits back+misc1 for it — harmless
on a plain xpad session and rare otherwise.)

G22 (partial): define paddle1..4 for wire completeness, but leave them out of
buttonMask/allButtons until the GameController paddleButton1..4 ↔ BTN_PADDLE
physical correspondence is confirmed on a real Elite pad.

G15: replace the 3-bit spot-check with an exhaustive assertion of every
GamepadWire button/axis constant against the generated C ABI header
(punktfunk_core.h), so any Swift-side drift from punktfunk_core::input::gamepad
fails CI.

swift build + full PunktfunkKit suite green (124 passed, 5 skipped).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 11:14:26 +02:00
enricobuehlerandClaude Opus 4.8 97c67b2692 feat(apple): multi-controller support
Roll the pf-client-core slot pattern to the Apple client (Swift):

- GamepadManager tracks all connected GCControllers, assigning each a stable
  lowest-free wire pad index + concrete type, emitting GamepadArrival on
  connect and GamepadRemove on disconnect (index freed for reuse on re-plug).
- GamepadCapture binds every controller with per-controller Slot state
  (buttons/axes/fingers/motion), threading the pad index into flags on every
  event; GamepadWire/InputEvents carry the pad + the two new events.
- GamepadFeedback + RumbleRenderer go per-pad (rumbleByPad, slots[pad]),
  routing rumble/HID back to the correct controller by wire index.
- ContentView/Settings surface every forwarded controller.

pad 0 => flags 0, so single-controller wire is byte-identical. Cannot build
on the Linux dev box (no Swift toolchain / Apple frameworks); wire bytes
hand-checked against input.rs and GamepadWireTests extended for multi-pad.
CI apple.yml (swift build/test on macOS) is the compile gate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 21:53:07 +02:00
enricobuehlerandClaude Fable 5 bd1df14d4e feat(gamepad): controller discovery + client-negotiated pad type + rich DualSense end to end
The Apple client grows full gamepad support and punktfunk/1 learns to negotiate
the virtual pad type:

- Protocol: Hello carries a GamepadPref byte (offset 21, the same trailing-byte
  back-compat pattern as the compositor; echoed resolved in Welcome at 54).
  Host precedence: explicit client choice > PUNKTFUNK_GAMEPAD env > Xbox 360,
  DualSense (UHID) only where available. ABI: punktfunk_connect_ex2 +
  punktfunk_connection_gamepad (connect_ex delegates; ABI_VERSION stays 2 — the
  trailing byte IS the compat mechanism). punktfunk-client-rs gets --gamepad.

- Swift client: GamepadManager (app-lifetime discovery + selection — Settings
  lists every controller with capabilities/battery/"In use"; exactly ONE pad
  forwards as pad 0, auto = most recently connected, or pinned), GamepadCapture
  (snapshot-diff button/axis events, DualSense touchpad + ~250 Hz motion on the
  rich-input plane, held state released on switch/deactivate/stop),
  GamepadFeedback (rumble → CoreHaptics per-handle engines; lightbar →
  GCDeviceLight; player LEDs → playerIndex; adaptive-trigger blocks → the
  table-driven DualSenseTriggerEffect parser → GCDualSenseAdaptiveTrigger,
  exact for the 10-zone positional modes). The pad type auto-resolves from the
  physical controller at connect time, user-overridable in Settings.

- Host DualSense fixes surfaced by adversarial review against hid-playstation /
  SDL / Nielk1 ground truth: input-report sensor/touch offsets were off by one
  (the kernel read garbage motion + phantom touches), the L2/R2 trigger blocks
  were swapped (the report is right-trigger-first), feedback now gates on the
  report's valid-flags (a plain rumble write no longer blanks lightbar/
  triggers), and the touchpad rescale clamps to the advertised ABS_MT extents.

- Tests: Hello/Welcome trailing-byte back-compat, pick_gamepad precedence,
  byte-exact input-report layout, valid-flag gating, per-mode trigger-parser
  table (incl. packed 3-bit zones), wire conversions, and a scripted loopback
  feedback burst (PUNKTFUNK_TEST_FEEDBACK=1) asserted through the xcframework
  on the rumble + HID-output planes.

Validated: cargo test/clippy/fmt green on macOS + Linux (61 host tests), swift
build/test green, test-loopback.sh green, tvOS/iOS targets compile. DualSense
motion sign/scale is derived from the calibration blob, not yet live-verified
(constants isolated in GamepadWire).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 16:28:33 +02:00