21 #include "../../SDL_internal.h" 34 #include "../SDL_sysjoystick.h" 35 #include "../SDL_joystick_c.h" 38 #if !SDL_EVENTS_DISABLED 39 #include "../../events/SDL_events_c.h" 43 #import <CoreMotion/CoreMotion.h> 46 #ifdef SDL_JOYSTICK_MFI 47 #import <GameController/GameController.h> 49 static id connectObserver = nil;
50 static id disconnectObserver = nil;
69 while (i < device_index) {
73 device = device->
next;
83 #ifdef SDL_JOYSTICK_MFI 84 const Uint16 VENDOR_APPLE = 0x05AC;
94 device->
controller = (__bridge GCController *) CFBridgingRetain(controller);
96 if (controller.vendorName) {
97 name = controller.vendorName.UTF8String;
101 name =
"MFi Gamepad";
106 if (controller.extendedGamepad) {
107 vendor = VENDOR_APPLE;
113 }
else if (controller.gamepad) {
114 vendor = VENDOR_APPLE;
122 else if (controller.microGamepad) {
123 vendor = VENDOR_APPLE;
151 controller.playerIndex = -1;
164 if (controller && !controller.extendedGamepad && !controller.gamepad && controller.microGamepad) {
170 while (device !=
NULL) {
174 device = device->
next;
178 if (device ==
NULL) {
198 }
else if (controller) {
202 if (deviceList ==
NULL) {
207 lastdevice = lastdevice->
next;
224 if (device ==
NULL) {
230 while (item !=
NULL) {
231 if (item == device) {
241 }
else if (device == deviceList) {
242 deviceList = device->
next;
249 #ifdef SDL_JOYSTICK_MFI 254 GCController *controller = CFBridgingRelease((__bridge CFTypeRef)(device->
controller));
255 controller.controllerPausedHandler = nil;
273 SDL_AppleTVRemoteRotationHintChanged(
void *udata,
const char *
name,
const char *oldValue,
const char *newValue)
275 BOOL allowRotation = newValue !=
NULL && *newValue !=
'0';
278 for (GCController *controller
in [GCController
controllers]) {
279 if (controller.microGamepad) {
280 controller.microGamepad.allowsRotation = allowRotation;
291 NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
300 #ifdef SDL_JOYSTICK_MFI 302 if (![GCController
class]) {
306 for (GCController *controller
in [GCController
controllers]) {
312 SDL_AppleTVRemoteRotationHintChanged,
NULL);
315 connectObserver = [center addObserverForName:GCControllerDidConnectNotification
318 usingBlock:^(NSNotification *note) {
319 GCController *controller = note.object;
320 IOS_AddJoystickDevice(controller, SDL_FALSE);
323 disconnectObserver = [center addObserverForName:GCControllerDidDisconnectNotification
326 usingBlock:^(NSNotification *note) {
327 GCController *controller = note.object;
328 SDL_JoystickDeviceItem *device = deviceList;
329 while (device != NULL) {
330 if (device->controller == controller) {
331 IOS_RemoveJoystickDevice(device);
334 device = device->next;
358 return device ? device->
name :
"Unknown";
391 if (device ==
NULL) {
392 return SDL_SetError(
"Could not open Joystick: no hardware device for the specified index");
395 joystick->hwdata =
device;
398 joystick->naxes = device->
naxes;
399 joystick->nhats = device->
nhats;
400 joystick->nbuttons = device->
nbuttons;
401 joystick->nballs = 0;
414 [motionManager startAccelerometerUpdates];
417 #ifdef SDL_JOYSTICK_MFI 418 GCController *controller = device->
controller;
419 controller.controllerPausedHandler = ^(GCController *
c) {
420 if (joystick->hwdata) {
421 ++joystick->hwdata->num_pause_presses;
439 const SInt16 maxsint16 = 0x7FFF;
440 CMAcceleration accel;
478 #ifdef SDL_JOYSTICK_MFI 480 IOS_MFIJoystickHatStateForDPad(GCControllerDirectionPad *dpad)
484 if (dpad.up.isPressed) {
486 }
else if (dpad.down.isPressed) {
490 if (dpad.left.isPressed) {
492 }
else if (dpad.right.isPressed) {
509 GCController *controller = joystick->hwdata->controller;
512 int updateplayerindex = 0;
514 if (controller.extendedGamepad) {
515 GCExtendedGamepad *gamepad = controller.extendedGamepad;
519 (
Sint16) (gamepad.leftThumbstick.xAxis.value * 32767),
520 (
Sint16) (gamepad.leftThumbstick.yAxis.value * -32767),
521 (
Sint16) ((gamepad.leftTrigger.value * 65535) - 32768),
522 (
Sint16) (gamepad.rightThumbstick.xAxis.value * 32767),
523 (
Sint16) (gamepad.rightThumbstick.yAxis.value * -32767),
524 (
Sint16) ((gamepad.rightTrigger.value * 65535) - 32768),
529 gamepad.buttonA.isPressed, gamepad.buttonB.isPressed,
530 gamepad.buttonX.isPressed, gamepad.buttonY.isPressed,
531 gamepad.leftShoulder.isPressed,
532 gamepad.rightShoulder.isPressed,
535 hatstate = IOS_MFIJoystickHatStateForDPad(gamepad.dpad);
541 if ((i != 2 && i != 5) || axes[i] != -32768) {
542 updateplayerindex |= (joystick->axes[i].value != axes[i]);
548 updateplayerindex |= (joystick->buttons[i] != buttons[i]);
551 }
else if (controller.gamepad) {
552 GCGamepad *gamepad = controller.gamepad;
556 gamepad.buttonA.isPressed, gamepad.buttonB.isPressed,
557 gamepad.buttonX.isPressed, gamepad.buttonY.isPressed,
558 gamepad.leftShoulder.isPressed,
559 gamepad.rightShoulder.isPressed,
562 hatstate = IOS_MFIJoystickHatStateForDPad(gamepad.dpad);
565 updateplayerindex |= (joystick->buttons[i] != buttons[i]);
570 else if (controller.microGamepad) {
571 GCMicroGamepad *gamepad = controller.microGamepad;
574 (
Sint16) (gamepad.dpad.xAxis.value * 32767),
575 (
Sint16) (gamepad.dpad.yAxis.value * -32767),
579 updateplayerindex |= (joystick->axes[i].value != axes[i]);
584 gamepad.buttonA.isPressed,
585 gamepad.buttonX.isPressed,
589 updateplayerindex |= (joystick->buttons[i] != buttons[i]);
595 if (joystick->nhats > 0) {
596 updateplayerindex |= (joystick->hats[0] != hatstate);
600 for (i = 0; i < joystick->hwdata->num_pause_presses; i++) {
601 const Uint8 pausebutton = joystick->nbuttons - 1;
604 updateplayerindex = YES;
606 joystick->hwdata->num_pause_presses = 0;
608 if (updateplayerindex && controller.playerIndex == -1) {
609 BOOL usedPlayerIndexSlots[4] = {NO, NO, NO, NO};
613 if (
c != controller &&
c.playerIndex >= 0) {
622 if (!usedPlayerIndexSlots[i]) {
623 controller.playerIndex =
i;
643 if (device ==
NULL) {
659 if (device ==
NULL) {
668 [motionManager stopAccelerometerUpdates];
671 #ifdef SDL_JOYSTICK_MFI 672 GCController *controller = device->
controller;
673 controller.controllerPausedHandler = nil;
674 controller.playerIndex = -1;
687 #ifdef SDL_JOYSTICK_MFI 688 NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
690 if (connectObserver) {
691 [center removeObserver:connectObserver name:GCControllerDidConnectNotification object:nil];
692 connectObserver = nil;
695 if (disconnectObserver) {
696 [center removeObserver:disconnectObserver name:GCControllerDidDisconnectNotification object:nil];
697 disconnectObserver = nil;
702 SDL_AppleTVRemoteRotationHintChanged,
NULL);
706 while (deviceList !=
NULL) {
static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
#define SDL_HINT_TV_REMOTE_AS_JOYSTICK
A variable controlling whether the Android / tvOS remotes should be listed as joystick devices...
static int IOS_JoystickGetCount(void)
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
static void IOS_JoystickUpdate(SDL_Joystick *joystick)
static SDL_JoystickDeviceItem * IOS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
static SDL_JoystickDeviceItem * deviceList
static int IOS_JoystickInit(void)
#define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION
A variable controlling whether the Apple TV remote's joystick axes will automatically match the rotat...
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
static void IOS_JoystickDetect(void)
static const char * accelerometerName
struct joystick_hwdata * next
static SDL_JoystickDeviceItem * GetDeviceForIndex(int device_index)
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
GLuint const GLchar * name
#define SDL_GetHintBoolean
#define SDL_HARDWARE_BUS_BLUETOOTH
SDL_JoystickDriver SDL_IOS_JoystickDriver
static SDL_AudioDeviceID device
static SDL_JoystickID IOS_JoystickGetDeviceInstanceID(int device_index)
static const char * IOS_JoystickGetDeviceName(int device_index)
static void IOS_JoystickQuit(void)
#define SDL_HINT_ACCELEROMETER_AS_JOYSTICK
A variable controlling whether the Android / iOS built-in accelerometer should be listed as a joystic...
static void IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller)
static int IOS_JoystickOpen(SDL_Joystick *joystick, int device_index)
static SDL_JoystickGUID IOS_JoystickGetDeviceGUID(int device_index)
static void IOS_AccelerometerUpdate(SDL_Joystick *joystick)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
#define SDL_IPHONE_MAX_GFORCE
void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
SDL_JoystickID SDL_GetNextJoystickInstanceID()
int SDL_AppleTVRemoteOpenedAsJoystick
#define SDL_AddHintCallback
#define SDL_DelHintCallback
static int IOS_JoystickGetDevicePlayerIndex(int device_index)
static void IOS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
#define SDL_arraysize(array)
static int IOS_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
#define SDL_Unsupported()
GCController __unsafe_unretained * controller
static void IOS_JoystickClose(SDL_Joystick *joystick)
static CMMotionManager * motionManager