Skip to content

fix(macos): let GameController decode virtual Xbox controllers - #208

Merged
ReenigneArcher merged 2 commits into
LizardByte:masterfrom
neroshooter:claude/sunshine-controller-detection-47baa4
Oct 30, 2026
Merged

ReenigneArcher merged 2 commits into
LizardByte:masterfrom
neroshooter:claude/sunshine-controller-detection-47baa4

Conversation

@neroshooter

@neroshooter neroshooter commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Description

On macOS, virtual Xbox One/Series gamepads (045e:0b13 / 0b20) only sent wired GIP input report 0x20. Steam decodes it, but Apple's GameController framework ignores it: the controller shows up with no inputs. This affected Sunshine streams from Moonlight with the Xbox gamepad type; the DualSense profile worked.

Changes:

  • macos_xbox_transport.hpp: the descriptor now declares the Xbox Bluetooth gamepad collection (report 0x01, plus its 0x03 rumble output) followed by the existing GIP vendor collection (0x20 input, 0x09 output). New xbox_bluetooth_transport_input_report() builds report 0x01 in the compact firmware-5 button order GameController expects (A, B, X, Y, LB, RB, View, Menu / LS, RS), zero-padded to the broker's fixed 25-byte input size.
  • macos_broker_client.cpp: Xbox One/Series submissions send the Bluetooth report, then the GIP report. Client-only change; the protocol and the installed broker are unchanged.
  • Unit tests for descriptor report IDs, the compact button layout, and axis/hat copying.

Notes for reviewers:

  • The Linux "gapped" Bluetooth layout does not work here: GameController reads it with shifted buttons (X arrives as Y; Menu, View and the D-pad are missing).
  • Guide and Share never surface in GameController in any tested position (likely reserved for macOS system gestures). Steam still receives them via GIP.

Screenshot

Issues Fixed or Closed

Roadmap Issues

Testing

  • Added XboxBluetoothTransportUsesCompactGameControllerLayout and XboxBluetoothTransportCopiesAxesAndHat, and extended XboxOneAndSeriesUseDistinctIdentitiesAndGipInput to require report IDs 0x01, 0x03, 0x09 and 0x20 in the descriptor (the 0x01 check fails without the fix).
  • Full unit test suite on macOS: 151 passed, 2 Linux-only tests skipped.
  • clang-format --dry-run --Werror (23.1.0) passes on the changed files.
  • End-to-end against the installed signed broker with a harness driving xbox_series and xbox_one:
    • GameController receives every face button, bumper, Menu/View, D-pad, stick click, both sticks with correct directions, and triggers.
    • Steam (Settings > Controller) recognizes the Xbox controller and every button, stick, and trigger lights up correctly.
  • Not run: the broker target (its local build fails on an unrelated pre-existing Objective-C++ standard issue), and Sunshine itself, which bundles its own libvirtualhid.

Type of Change

  • feat: New feature (non-breaking change which adds functionality)
  • fix: Bug fix (non-breaking change which fixes an issue)
  • docs: Documentation only changes
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semicolons, etc.)
  • refactor: Code change that neither fixes a bug nor adds a feature
  • perf: Code change that improves performance
  • test: Adding missing tests or correcting existing tests
  • build: Changes that affect the build system or external dependencies
  • ci: Changes to CI configuration files and scripts
  • chore: Other changes that don't modify src or test files
  • revert: Reverts a previous commit
  • BREAKING CHANGE: Introduces a breaking change (can be combined with any type above)

Checklist

  • Code follows the style guidelines of this project
  • Code has been self-reviewed
  • Code has been commented, particularly in hard-to-understand areas
  • Code docstring/documentation-blocks for new or existing methods/components have been added or updated
  • Tests have been added or updated for new or modified functionality, including regression tests for bug fixes

AI Usage

See our AI usage policy.

  • AI tools were used while preparing this PR

Claude Code diagnosed the issue with HID and GameController monitors, implemented the fix and tests, and ran the end-to-end harness; Steam behaviour was checked by hand.

🤖 Generated with Claude Code

@ReenigneArcher ReenigneArcher left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The behavior checks passed; the remaining correction is the test include order, which fails the required formatter check.

Verified locally on macOS: library and example builds; 132 unit tests passed and 2 Linux-only tests skipped (diagnostic tools disabled); both Xbox profiles passed gamepad_adapter; a temporary GameController consumer verified face/shoulder/Menu/View/stick-click buttons, D-pad, both sticks, triggers, and device removal against the installed signed broker. The consumer disabled its system gesture handling to observe button states directly. git diff --check passed. Steam was not retested.

Hosted verification remains limited: Actions await maintainer approval, and the GH-Pages Read the Docs status reports failure but its build log was inaccessible. Neither is a code finding. The current head is mergeable against master.

Review completed by Codex | Model: gpt-6.1-sol | Thinking: xhigh

Copy link
Copy Markdown
Member

Please update the PR description to use the full LizardByte pull request template. Keep the existing description and testing details, and complete the applicable Type of Change, Checklist, and AI Usage fields. Preserve all template sections and comments; sections that do not apply may remain empty and their boxes unchecked.

Review completed by Codex | Model: gpt-6.1-sol | Thinking: xhigh

neroshooter and others added 2 commits October 29, 2026 22:17
The macOS Xbox One/Series transport only sent wired GIP report 0x20,
which Steam reads but Apple's GameController framework ignores, so
streamed Xbox pads appeared with no inputs. Declare the Xbox Bluetooth
gamepad collection alongside the GIP vendor collection and send a
compact Bluetooth report 0x01 before each GIP report.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ReenigneArcher
ReenigneArcher force-pushed the claude/sunshine-controller-detection-47baa4 branch from 3f9afdb to b1531cc Compare October 30, 2026 02:17
@sonarqubecloud

Copy link
Copy Markdown

@codecov

codecov Bot commented Oct 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 38.23529% with 21 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.67%. Comparing base (3e18cd7) to head (b1531cc).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/platform/macos/macos_broker_client.cpp 0.00% 16 Missing ⚠️
src/platform/macos/macos_xbox_transport.hpp 72.22% 0 Missing and 5 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff            @@
##           master     #208    +/-   ##
========================================
  Coverage   73.67%   73.67%            
========================================
  Files          44       44            
  Lines       10686    10705    +19     
  Branches     3646     3651     +5     
========================================
+ Hits         7873     7887    +14     
- Misses       2212     2424   +212     
+ Partials      601      394   -207     
Flag Coverage Δ
FreeBSD 53.99% <ø> (ø)
Linux-Clang 68.61% <ø> (+0.01%) ⬆️
Linux-GCC 80.55% <ø> (ø)
PowerShell 75.60% <ø> (ø)
Windows-MSVC 74.28% <ø> (ø)
Windows-MinGW-UCRT64 66.07% <ø> (-0.06%) ⬇️
macOS 50.94% <38.23%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/platform/macos/macos_xbox_transport.hpp 64.51% <72.22%> (+0.87%) ⬆️
src/platform/macos/macos_broker_client.cpp 0.96% <0.00%> (-0.02%) ⬇️

... and 12 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3e18cd7...b1531cc. Read the comment docs.

@ReenigneArcher
ReenigneArcher merged commit dd0ff88 into LizardByte:master Oct 30, 2026
34 of 35 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants