We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 4463

Summary: Guide button on MFi Gamepad cannot be polled
Product: SDL Reporter: Caleb Cornett <spydog>
Component: joystickAssignee: Sam Lantinga <slouken>
Status: RESOLVED FIXED QA Contact: Sam Lantinga <slouken>
Severity: minor    
Priority: P2 CC: amaranth72, flibitijibibo, spydog
Version: 2.0.9   
Hardware: iPhone/iPod touch   
OS: iOS (All)   
Attachments: MFi Guide Button Patch

Description Caleb Cornett 2019-01-18 00:33:07 UTC
On iOS and tvOS, the guide/menu/pause button on an MFi controller behaves differently than any other button. When the BUTTONDOWN event is fired, it is immediately followed by a BUTTONUP event. See: https://hg.libsdl.org/SDL/file/a7d52e2db27a/src/joystick/iphoneos/SDL_sysjoystick.m#l600

This means that the state of the Guide button cannot be polled via SDL_GameControllerGetButton().

Would it be possible for the guide button state to remain pressed for at least a full frame before the BUTTONUP event is fired? Or is there an OS-level reason why this cannot be done?
Comment 1 Ethan Lee 2019-01-18 02:28:43 UTC
Example of what applications have to do if events can't be polled (hopefully you can, but in rare cases you can only GetState):

https://github.com/FNA-XNA/FNA/pull/232
Comment 2 Alex Szpakowski 2019-01-23 14:31:57 UTC
Unfortunately Apple doesn't provide APIs to query the state of the pause button on MFi controllers, they only have a callback which occurs at some point during the button press.

I suppose it would theoretically be possible to delay the release event for a frame, but it would add some code complexity.

It's also worth mentioning that you can *never* guarantee that you'll receive all input events if you only poll instead of using events. For example you could have a frame hitch while the user quickly presses and releases a button, and if the button is supposed to perform an action it would be missed completely if you check the button's state every frame instead of doing the action when a press or release event is received from event polling.
Comment 3 Sam Lantinga 2019-01-25 09:56:41 UTC
Yes, this can't be fixed with Apple's current API.

However, if you're using the game controller API, the guide button will remain "pressed" for 250 ms. Take a look at SDL_MINIMUM_GUIDE_BUTTON_DELAY_MS in SDL_gamecontroller.c for details.
Comment 4 Caleb Cornett 2019-01-30 15:49:10 UTC
Created attachment 3588 [details]
MFi Guide Button Patch
Comment 5 Caleb Cornett 2019-01-30 15:53:46 UTC
Thanks for pointing me in the right direction, Sam. The behavior you described isn't currently working, but I've figured out why.

SDL_GameControllerGetButton() doesn't detect the delayed press because the joystick->buttons array does not contain an element for the Guide button. This also has the side effect that polling for the Guide button with this function returns garbage data outside the bounds of the joystick->buttons array (since the array contains nbuttons-1 elements and Guide is always the nbuttons'th button).

I've attached a small patch that fixes both problems, enabling the detection of the delayed Guide press from SDL_GameControllerGetButton and thereby fixing the out-of-bounds access issue.
Comment 6 Alex Szpakowski 2019-01-31 23:55:16 UTC
Thanks Caleb, the patch looks good. I've applied it at https://hg.libsdl.org/SDL/rev/1fc2169984ad