Mac: Xbox controller shows the right button icons but nothing responds — cause found, workaround works

+
SUMMARY
On macOS the game detects a game controller, switches the on-screen prompts to
Xbox glyphs, and then responds to no button. Keyboard and mouse work normally.
The input is not lost — it is queued and delivered in a single burst when the
render loop exits.

ENVIRONMENT
macOS 26.6.2 (25G83), Apple silicon
Cyberpunk 2077 Ultimate 2.3.1, build 5314028, native arm64, Steam appid 1091500
Xbox Wireless Controller model 1914 (VID 0x045E, PID 0x0B13 over Bluetooth LE,
PID 0x0B12 over USB), firmware 5.23.6.0
Reproduced over both Bluetooth LE and USB, and on both a Steam launch and a
direct launch of Cyberpunk2077.app.

STEPS TO REPRODUCE
1. Connect an Xbox Wireless Controller to the Mac.
2. Launch the game and wait for the main menu.
3. Press any controller button.

EXPECTED
The menu responds to the controller.

ACTUAL
Nothing happens. The Xbox button glyphs are displayed correctly, so the game
knows a controller is attached. Every press is silently queued. All queued
presses execute at once, in the correct order and with correct values, at the
moment the player exits and the engine leaves its render loop.

ROOT CAUSE
The game installs a valueChangedHandler block on all 38 elements of the
controller at load, which is correct. It then never calls
-[GCController extendedGamepad] again, so it does not poll element values; the
callbacks are the only input path.

GameController delivers those blocks on GCController.handlerQueue, which
defaults to the main dispatch queue. The engine does not drain the main queue
while it renders, so no handler block runs during gameplay.

EVIDENCE
Measured by injecting a dylib that wraps each handler block and logs the
instant it actually executes (the app carries
cs.allow-dyld-environment-variables and cs.disable-library-validation).

Handlers installed:
14:31:09.309 SET button handler on 'A Button' block=0x16fc2ac18
14:31:09.309 SET button handler on 'B Button' block=0x16fc2abf0
... 38 elements ...

Player presses buttons for ~45 s. No response on screen.

All 40 events then fire inside a 3 ms window, 56 s later, as the render loop
exits:
14:32:05.747 FIRE button 'B Button' value=1.000 pressed=1 (#1)
14:32:05.749 FIRE button 'B Button' value=0.000 pressed=0 (#2)
14:32:05.750 FIRE button 'A Button' value=1.000 pressed=1 (#13)
14:32:05.750 FIRE button 'A Button' value=0.000 pressed=0 (#40)

Values and ordering match the real presses. Nothing was dropped by the OS.

Keyboard and mouse are unaffected because the binary contains no reference to
GCKeyboard or GCMouse and reads them through AppKit (NSEvent,
addLocalMonitorForEventsMatchingMask:, keyDown), which the engine pumps itself.

CONFIRMED NOT THE CAUSE
Controller hardware (342 events, every element, to a normal frontmost macOS
app), Bluetooth pairing, USB transport, Steam Input (disabled, loads
controller_base/empty.vdf), the Steam overlay, the macOS per-game controller
profile, and a full reset of UserSettings.json. A test binary restamped to the
same LC_BUILD_VERSION as the game (minos 15.5, sdk 15.2) receives input
normally on this OS, so this is not an SDK gating issue.

SUGGESTED FIX
Set GCController.handlerQueue explicitly to a queue the engine services, or
read element values in the frame loop instead of relying on block delivery.

WORKAROUND VERIFIED
Setting handlerQueue to a private serial queue at GCControllerDidConnect makes
the controller work immediately, with no other change. The same 40 events then
arrive spread across 58.650 s instead of 0.003 s. No crash across a full
session, so the handler code appears thread-safe.
Post automatically merged:

Workaround is now on GitHub, with the source and the raw in-process measurements: https://github.com/SL33PiNg/cyberpunk2077-mac-controller-fix

git clone -> ./build.sh -> cp2077

It builds a small dylib that points GCController.handlerQueue at a queue that actually runs. It changes no file in the game and does not touch saves. Remove it by launching normally; game updates neither break it nor undo it.

The evidence folder has both raw logs. Stock game: all 40 button events fire inside a single 3 ms window, 56 s after the handlers were installed, at the moment the render loop exits. With the fix: the same 40 events arrive spread across 58.6 s, as the thumb moves.

If you have a Mac and a controller, please try it and reply whether it works for you. A reproduction from a second machine carries far more weight than one detailed report.
 
Last edited:
Top Bottom