21 #include "../../SDL_internal.h"
28 #include "../SDL_sysjoystick.h"
29 #include "../SDL_joystick_c.h"
30 #include "../usb_ids.h"
34 #if !SDL_EVENTS_DISABLED
35 #include "../../events/SDL_events_c.h"
39 #define SDL_JOYSTICK_iOS_ACCELEROMETER
40 #import <CoreMotion/CoreMotion.h>
43 #if defined(__MACOSX__)
44 #include <IOKit/hid/IOHIDManager.h>
45 #include <AppKit/NSApplication.h>
46 #ifndef NSAppKitVersionNumber10_15
47 #define NSAppKitVersionNumber10_15 1894
51 #ifdef SDL_JOYSTICK_MFI
52 #import <GameController/GameController.h>
54 static id connectObserver = nil;
55 static id disconnectObserver = nil;
57 #include <Availability.h>
58 #include <objc/message.h>
63 @interface GCController (SDL)
64 #if defined(__MACOSX__) && (__MAC_OS_X_VERSION_MAX_ALLOWED <= 101600)
65 + (BOOL)supportsHIDDevice:(IOHIDDeviceRef)device;
68 @interface GCExtendedGamepad (SDL)
69 #if !((__IPHONE_OS_VERSION_MAX_ALLOWED >= 121000) || (__APPLETV_OS_VERSION_MAX_ALLOWED >= 121000) || (__MAC_OS_VERSION_MAX_ALLOWED >= 1401000))
70 @property (nonatomic, readonly, nullable) GCControllerButtonInput *leftThumbstickButton;
71 @property (nonatomic, readonly, nullable) GCControllerButtonInput *rightThumbstickButton;
73 #if !((__IPHONE_OS_VERSION_MAX_ALLOWED >= 130000) || (__APPLETV_OS_VERSION_MAX_ALLOWED >= 130000) || (__MAC_OS_VERSION_MAX_ALLOWED >= 1500000))
74 @property (nonatomic, readonly) GCControllerButtonInput *buttonMenu;
75 @property (nonatomic, readonly, nullable) GCControllerButtonInput *buttonOptions;
77 #if !((__IPHONE_OS_VERSION_MAX_ALLOWED >= 140000) || (__APPLETV_OS_VERSION_MAX_ALLOWED >= 140000) || (__MAC_OS_VERSION_MAX_ALLOWED > 1500000))
78 @property (nonatomic, readonly, nullable) GCControllerButtonInput *buttonHome;
81 @interface GCMicroGamepad (SDL)
82 #if !((__IPHONE_OS_VERSION_MAX_ALLOWED >= 130000) || (__APPLETV_OS_VERSION_MAX_ALLOWED >= 130000) || (__MAC_OS_VERSION_MAX_ALLOWED >= 1500000))
83 @property (nonatomic, readonly) GCControllerButtonInput *buttonMenu;
87 #if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 140000) || (__APPLETV_OS_VERSION_MAX_ALLOWED >= 140000) || (__MAC_OS_VERSION_MAX_ALLOWED > 1500000) || (__MAC_OS_X_VERSION_MAX_ALLOWED > 101600)
88 #define ENABLE_MFI_BATTERY
89 #define ENABLE_MFI_RUMBLE
90 #define ENABLE_MFI_LIGHT
91 #define ENABLE_MFI_SENSORS
92 #define ENABLE_PHYSICAL_INPUT_PROFILE
95 #ifdef ENABLE_MFI_RUMBLE
96 #import <CoreHaptics/CoreHaptics.h>
101 #ifdef SDL_JOYSTICK_iOS_ACCELEROMETER
102 static const char *accelerometerName =
"iOS Accelerometer";
103 static CMMotionManager *motionManager = nil;
117 while (
i < device_index) {
128 #ifdef SDL_JOYSTICK_MFI
140 device->controller = (__bridge GCController *) CFBridgingRetain(controller);
142 if (controller.vendorName) {
143 name = controller.vendorName.UTF8String;
147 name =
"MFi Gamepad";
152 if (controller.extendedGamepad) {
153 GCExtendedGamepad *gamepad = controller.extendedGamepad;
154 BOOL is_xbox = [controller.vendorName containsString: @"Xbox"];
155 BOOL is_ps4 = [controller.vendorName containsString: @"DUALSHOCK"];
157 BOOL is_MFi = (!is_xbox && !is_ps4);
171 #pragma clang diagnostic push
172 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
173 if ([gamepad respondsToSelector:
@selector(leftThumbstickButton)] && gamepad.leftThumbstickButton) {
177 if ([gamepad respondsToSelector:
@selector(rightThumbstickButton)] && gamepad.rightThumbstickButton) {
181 if ([gamepad respondsToSelector:
@selector(buttonOptions)] && gamepad.buttonOptions) {
185 if ([gamepad respondsToSelector:
@selector(buttonHome)] && gamepad.buttonHome) {
189 BOOL has_direct_menu = [gamepad respondsToSelector:@selector(buttonMenu)] && gamepad.buttonMenu;
193 has_direct_menu =
FALSE;
198 if (!has_direct_menu) {
202 #ifdef ENABLE_PHYSICAL_INPUT_PROFILE
203 if ([controller respondsToSelector:
@selector(physicalInputProfile)]) {
204 if (controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton] != nil) {
209 if (controller.physicalInputProfile.buttons[GCInputXboxPaddleOne] != nil) {
214 if (controller.physicalInputProfile.buttons[GCInputXboxPaddleTwo] != nil) {
219 if (controller.physicalInputProfile.buttons[GCInputXboxPaddleThree] != nil) {
224 if (controller.physicalInputProfile.buttons[GCInputXboxPaddleFour] != nil) {
231 #pragma clang diagnostic pop
235 if (
device->has_xbox_paddles) {
248 if (
device->has_dualshock_touchpad) {
261 device->nbuttons = nbuttons;
263 }
else if (controller.gamepad) {
282 device->nbuttons = nbuttons;
285 else if (controller.microGamepad) {
301 device->nbuttons = nbuttons;
320 device->guid.data[14] =
'm';
321 device->guid.data[15] = subtype;
323 device->guid.data[15] = subtype;
328 controller.playerIndex = -1;
332 #if defined(SDL_JOYSTICK_iOS_ACCELEROMETER) || defined(SDL_JOYSTICK_MFI)
334 IOS_AddJoystickDevice(GCController *controller,
SDL_bool accelerometer)
341 if (controller && !controller.extendedGamepad && !controller.gamepad && controller.microGamepad) {
348 if (
device->controller == controller) {
359 device->accelerometer = accelerometer;
363 #ifdef SDL_JOYSTICK_iOS_ACCELEROMETER
375 }
else if (controller) {
376 #ifdef SDL_JOYSTICK_MFI
377 IOS_AddMFIJoystickDevice(
device, controller);
389 lastdevice = lastdevice->
next;
413 while (item !=
NULL) {
432 #ifdef SDL_JOYSTICK_MFI
437 GCController *controller = CFBridgingRelease((__bridge CFTypeRef)(
device->controller));
438 controller.controllerPausedHandler = nil;
456 SDL_AppleTVRemoteRotationHintChanged(
void *udata,
const char *
name,
const char *oldValue,
const char *newValue)
458 BOOL allowRotation = newValue !=
NULL && *newValue !=
'0';
461 for (GCController *controller
in [GCController
controllers]) {
462 if (controller.microGamepad) {
463 controller.microGamepad.allowsRotation = allowRotation;
470 #if defined(__MACOSX__)
471 static int is_macos11(
void)
473 return (
floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_15);
480 #if defined(__MACOSX__)
487 #ifdef SDL_JOYSTICK_iOS_ACCELEROMETER
490 IOS_AddJoystickDevice(nil,
SDL_TRUE);
494 #ifdef SDL_JOYSTICK_MFI
496 if (![GCController
class]) {
502 for (GCController *controller
in [GCController
controllers]) {
503 IOS_AddJoystickDevice(controller,
SDL_FALSE);
508 SDL_AppleTVRemoteRotationHintChanged,
NULL);
511 NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
513 connectObserver = [center addObserverForName:GCControllerDidConnectNotification
516 usingBlock:^(NSNotification *note) {
517 GCController *controller = note.object;
518 IOS_AddJoystickDevice(controller, SDL_FALSE);
521 disconnectObserver = [center addObserverForName:GCControllerDidDisconnectNotification
524 usingBlock:^(NSNotification *note) {
525 GCController *controller = note.object;
526 SDL_JoystickDeviceItem *device = deviceList;
527 while (device != NULL) {
528 if (device->controller == controller) {
529 IOS_RemoveJoystickDevice(device);
532 device = device->next;
562 #ifdef SDL_JOYSTICK_MFI
565 return (
int)
device->controller.playerIndex;
574 #ifdef SDL_JOYSTICK_MFI
577 device->controller.playerIndex = player_index;
607 return SDL_SetError(
"Could not open Joystick: no hardware device for the specified index");
618 if (
device->has_dualshock_touchpad) {
625 if (
device->accelerometer) {
626 #ifdef SDL_JOYSTICK_iOS_ACCELEROMETER
627 if (motionManager == nil) {
628 motionManager = [[CMMotionManager alloc] init];
632 motionManager.accelerometerUpdateInterval = 0.1;
633 [motionManager startAccelerometerUpdates];
636 #ifdef SDL_JOYSTICK_MFI
637 if (
device->uses_pause_handler) {
638 GCController *controller =
device->controller;
639 controller.controllerPausedHandler = ^(GCController *
c) {
641 ++
joystick->hwdata->num_pause_presses;
646 #ifdef ENABLE_MFI_SENSORS
647 if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
648 GCController *controller =
joystick->hwdata->controller;
649 GCMotion *motion = controller.motion;
650 if (motion && motion.hasRotationRate) {
653 if (motion && motion.hasGravityAndUserAcceleration) {
672 #ifdef SDL_JOYSTICK_iOS_ACCELEROMETER
674 const SInt16 maxsint16 = 0x7FFF;
675 CMAcceleration accel;
678 if (!motionManager.isAccelerometerActive) {
682 accel = motionManager.accelerometerData.acceleration;
713 #ifdef SDL_JOYSTICK_MFI
715 IOS_MFIJoystickHatStateForDPad(GCControllerDirectionPad *dpad)
719 if (dpad.up.isPressed) {
721 }
else if (dpad.down.isPressed) {
725 if (dpad.left.isPressed) {
727 }
else if (dpad.right.isPressed) {
744 GCController *controller =
joystick->hwdata->controller;
747 int pause_button_index = 0;
749 if (controller.extendedGamepad) {
750 GCExtendedGamepad *gamepad = controller.extendedGamepad;
754 (
Sint16) (gamepad.leftThumbstick.xAxis.value * 32767),
755 (
Sint16) (gamepad.leftThumbstick.yAxis.value * -32767),
756 (
Sint16) ((gamepad.leftTrigger.value * 65535) - 32768),
757 (
Sint16) (gamepad.rightThumbstick.xAxis.value * 32767),
758 (
Sint16) (gamepad.rightThumbstick.yAxis.value * -32767),
759 (
Sint16) ((gamepad.rightTrigger.value * 65535) - 32768),
763 Uint8 buttons[joystick->nbuttons];
764 int button_count = 0;
767 buttons[button_count++] = gamepad.buttonA.isPressed;
768 buttons[button_count++] = gamepad.buttonB.isPressed;
769 buttons[button_count++] = gamepad.buttonX.isPressed;
770 buttons[button_count++] = gamepad.buttonY.isPressed;
771 buttons[button_count++] = gamepad.leftShoulder.isPressed;
772 buttons[button_count++] = gamepad.rightShoulder.isPressed;
775 #pragma clang diagnostic push
776 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
778 buttons[button_count++] = gamepad.leftThumbstickButton.isPressed;
781 buttons[button_count++] = gamepad.rightThumbstickButton.isPressed;
784 buttons[button_count++] = gamepad.buttonOptions.isPressed;
787 buttons[button_count++] = gamepad.buttonHome.isPressed;
791 if (
joystick->hwdata->uses_pause_handler) {
792 pause_button_index = button_count;
793 buttons[button_count++] =
joystick->delayed_guide_button;
795 buttons[button_count++] = gamepad.buttonMenu.isPressed;
799 #ifdef ENABLE_PHYSICAL_INPUT_PROFILE
800 if (
joystick->hwdata->has_dualshock_touchpad) {
801 buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputDualShockTouchpadButton].isPressed;
803 GCControllerDirectionPad *dpad;
805 dpad = controller.physicalInputProfile.dpads[GCInputDualShockTouchpadOne];
806 if (dpad.xAxis.value || dpad.yAxis.value) {
812 dpad = controller.physicalInputProfile.dpads[GCInputDualShockTouchpadTwo];
813 if (dpad.xAxis.value || dpad.yAxis.value) {
820 if (
joystick->hwdata->has_xbox_paddles) {
822 buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleOne].isPressed;
825 buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleTwo].isPressed;
828 buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleThree].isPressed;
831 buttons[button_count++] = controller.physicalInputProfile.buttons[GCInputXboxPaddleFour].isPressed;
843 #pragma clang diagnostic pop
845 hatstate = IOS_MFIJoystickHatStateForDPad(gamepad.dpad);
851 for (
i = 0;
i < button_count;
i++) {
855 #ifdef ENABLE_MFI_SENSORS
856 if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
857 GCMotion *motion = controller.motion;
858 if (motion && motion.sensorsActive) {
861 if (motion.hasRotationRate) {
862 GCRotationRate rate = motion.rotationRate;
868 if (motion.hasGravityAndUserAcceleration) {
869 GCAcceleration accel = motion.acceleration;
879 }
else if (controller.gamepad) {
880 GCGamepad *gamepad = controller.gamepad;
883 Uint8 buttons[joystick->nbuttons];
884 int button_count = 0;
885 buttons[button_count++] = gamepad.buttonA.isPressed;
886 buttons[button_count++] = gamepad.buttonB.isPressed;
887 buttons[button_count++] = gamepad.buttonX.isPressed;
888 buttons[button_count++] = gamepad.buttonY.isPressed;
889 buttons[button_count++] = gamepad.leftShoulder.isPressed;
890 buttons[button_count++] = gamepad.rightShoulder.isPressed;
891 pause_button_index = button_count;
892 buttons[button_count++] =
joystick->delayed_guide_button;
894 hatstate = IOS_MFIJoystickHatStateForDPad(gamepad.dpad);
896 for (
i = 0;
i < button_count;
i++) {
901 else if (controller.microGamepad) {
902 GCMicroGamepad *gamepad = controller.microGamepad;
905 (
Sint16) (gamepad.dpad.xAxis.value * 32767),
906 (
Sint16) (gamepad.dpad.yAxis.value * -32767),
913 Uint8 buttons[joystick->nbuttons];
914 int button_count = 0;
915 buttons[button_count++] = gamepad.buttonA.isPressed;
916 buttons[button_count++] = gamepad.buttonX.isPressed;
917 #pragma clang diagnostic push
918 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
921 if (
joystick->hwdata->uses_pause_handler) {
922 pause_button_index = button_count;
923 buttons[button_count++] =
joystick->delayed_guide_button;
925 buttons[button_count++] = gamepad.buttonMenu.isPressed;
928 #pragma clang diagnostic pop
930 for (
i = 0;
i < button_count;
i++) {
940 if (
joystick->hwdata->uses_pause_handler) {
941 for (
i = 0;
i <
joystick->hwdata->num_pause_presses;
i++) {
945 joystick->hwdata->num_pause_presses = 0;
948 #ifdef ENABLE_MFI_BATTERY
949 if (@available(macos 11.0, iOS 14.0, tvOS 14.0, *)) {
950 GCDeviceBattery *battery = controller.battery;
954 switch (battery.batteryState) {
955 case GCDeviceBatteryStateDischarging:
957 float power_level = battery.batteryLevel;
958 if (power_level <= 0.05
f) {
960 }
else if (power_level <= 0.20
f) {
962 }
else if (power_level <= 0.70
f) {
969 case GCDeviceBatteryStateCharging:
972 case GCDeviceBatteryStateFull:
987 #ifdef ENABLE_MFI_RUMBLE
989 @interface SDL_RumbleMotor : NSObject
992 @implementation SDL_RumbleMotor {
993 CHHapticEngine *engine API_AVAILABLE(macos(11.0), ios(13.0), tvos(14.0));
1000 if (self->player != nil) {
1001 [
self->player cancelAndReturnError:nil];
1004 if (self->engine != nil) {
1005 [
self->engine stopWithCompletionHandler:nil];
1010 -(
int)setIntensity:(
float)intensity
1013 if (@available(macos 11.0, iOS 14.0, tvOS 14.0, *)) {
1016 if (self->engine == nil) {
1020 if (intensity == 0.0
f) {
1021 if (self->player && self->active) {
1022 [
self->player stopAtTime:0 error:&error];
1024 self->active =
false;
1028 if (self->player == nil) {
1029 CHHapticEventParameter *
param = [[CHHapticEventParameter alloc] initWithParameterID:CHHapticEventParameterIDHapticIntensity value:1.0f];
1030 CHHapticEvent *
event = [[CHHapticEvent alloc] initWithEventType:CHHapticEventTypeHapticContinuous parameters:[NSArray arrayWithObjects:param, nil] relativeTime:0 duration:GCHapticDurationInfinite];
1031 CHHapticPattern *
pattern = [[CHHapticPattern alloc] initWithEvents:[NSArray arrayWithObject:event] parameters:[[NSArray alloc] init] error:&error];
1033 return SDL_SetError(
"Couldn't create haptic pattern: %s", [error.localizedDescription UTF8String]);
1036 self->player = [
self->engine createPlayerWithPattern:pattern error:&error];
1038 return SDL_SetError(
"Couldn't create haptic player: %s", [error.localizedDescription UTF8String]);
1040 self->active =
false;
1043 CHHapticDynamicParameter *
param = [[CHHapticDynamicParameter alloc] initWithParameterID:CHHapticDynamicParameterIDHapticIntensityControl value:intensity relativeTime:0];
1044 [
self->player sendParameters:[NSArray arrayWithObject:param] atTime:0 error:&error];
1046 return SDL_SetError(
"Couldn't update haptic player: %s", [error.localizedDescription UTF8String]);
1049 if (!self->active) {
1050 [
self->player startAtTime:0 error:&error];
1051 self->active =
true;
1059 -(
id) initWithController:(GCController*)controller locality:(GCHapticsLocality)locality API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0))
1062 self = [
super init];
1065 self->engine = [controller.haptics createEngineWithLocality:locality];
1066 if (self->engine == nil) {
1071 [
self->engine startAndReturnError:&error];
1077 __weak typeof(
self) weakSelf = self;
1078 self->engine.stoppedHandler = ^(CHHapticEngineStoppedReason stoppedReason) {
1079 SDL_RumbleMotor *
_this = weakSelf;
1084 _this->player = nil;
1085 _this->engine = nil;
1087 self->engine.resetHandler = ^{
1088 SDL_RumbleMotor *
_this = weakSelf;
1093 _this->player = nil;
1094 [_this->engine startAndReturnError:nil];
1103 @interface SDL_RumbleContext : NSObject
1106 @implementation SDL_RumbleContext {
1107 SDL_RumbleMotor *m_low_frequency_motor;
1108 SDL_RumbleMotor *m_high_frequency_motor;
1109 SDL_RumbleMotor *m_left_trigger_motor;
1110 SDL_RumbleMotor *m_right_trigger_motor;
1113 -(
id) initWithLowFrequencyMotor:(SDL_RumbleMotor*)low_frequency_motor
1114 HighFrequencyMotor:(SDL_RumbleMotor*)high_frequency_motor
1115 LeftTriggerMotor:(SDL_RumbleMotor*)left_trigger_motor
1116 RightTriggerMotor:(SDL_RumbleMotor*)right_trigger_motor
1118 self = [
super init];
1119 self->m_low_frequency_motor = low_frequency_motor;
1120 self->m_high_frequency_motor = high_frequency_motor;
1121 self->m_left_trigger_motor = left_trigger_motor;
1122 self->m_right_trigger_motor = right_trigger_motor;
1126 -(
int) rumbleWithLowFrequency:(
Uint16)low_frequency_rumble andHighFrequency:(
Uint16)high_frequency_rumble
1130 result += [self->m_low_frequency_motor setIntensity:((
float)low_frequency_rumble / 65535.0f)];
1131 result += [self->m_high_frequency_motor setIntensity:((
float)high_frequency_rumble / 65535.0f)];
1132 return ((
result < 0) ? -1 : 0);
1135 -(
int) rumbleLeftTrigger:(
Uint16)left_rumble andRightTrigger:(
Uint16)right_rumble
1139 if (self->m_left_trigger_motor && self->m_right_trigger_motor) {
1140 result += [self->m_left_trigger_motor setIntensity:((
float)left_rumble / 65535.0f)];
1141 result += [self->m_right_trigger_motor setIntensity:((
float)right_rumble / 65535.0f)];
1145 return ((
result < 0) ? -1 : 0);
1150 [
self->m_low_frequency_motor cleanup];
1151 [
self->m_high_frequency_motor cleanup];
1156 static SDL_RumbleContext *IOS_JoystickInitRumble(GCController *controller)
1159 if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
1160 SDL_RumbleMotor *low_frequency_motor = [[SDL_RumbleMotor alloc] initWithController:controller locality:GCHapticsLocalityLeftHandle];
1161 SDL_RumbleMotor *high_frequency_motor = [[SDL_RumbleMotor alloc] initWithController:controller locality:GCHapticsLocalityRightHandle];
1162 SDL_RumbleMotor *left_trigger_motor = [[SDL_RumbleMotor alloc] initWithController:controller locality:GCHapticsLocalityLeftTrigger];
1163 SDL_RumbleMotor *right_trigger_motor = [[SDL_RumbleMotor alloc] initWithController:controller locality:GCHapticsLocalityRightTrigger];
1164 if (low_frequency_motor && high_frequency_motor) {
1165 return [[SDL_RumbleContext alloc] initWithLowFrequencyMotor:low_frequency_motor
1166 HighFrequencyMotor:high_frequency_motor
1167 LeftTriggerMotor:left_trigger_motor
1168 RightTriggerMotor:right_trigger_motor];
1180 #ifdef ENABLE_MFI_RUMBLE
1183 if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
1185 SDL_RumbleContext *rumble = IOS_JoystickInitRumble(
device->controller);
1187 device->rumble = (
void *)CFBridgingRetain(rumble);
1193 SDL_RumbleContext *rumble = (__bridge SDL_RumbleContext *)
device->rumble;
1194 return [rumble rumbleWithLowFrequency:low_frequency_rumble andHighFrequency:high_frequency_rumble];
1206 #ifdef ENABLE_MFI_RUMBLE
1209 if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
1211 SDL_RumbleContext *rumble = IOS_JoystickInitRumble(
device->controller);
1213 device->rumble = (
void *)CFBridgingRetain(rumble);
1219 SDL_RumbleContext *rumble = (__bridge SDL_RumbleContext *)
device->rumble;
1220 return [rumble rumbleLeftTrigger:left_rumble andRightTrigger:right_rumble];
1232 #ifdef ENABLE_MFI_LIGHT
1234 if (@available(macos 11.0, iOS 14.0, tvOS 14.0, *)) {
1235 GCController *controller =
joystick->hwdata->controller;
1236 GCDeviceLight *
light = controller.light;
1250 #ifdef ENABLE_MFI_LIGHT
1252 if (@available(macos 11.0, iOS 14.0, tvOS 14.0, *)) {
1253 GCController *controller =
joystick->hwdata->controller;
1254 GCDeviceLight *
light = controller.light;
1256 light.color = [[GCColor alloc] initWithRed:(float)red / 255.0f
1257 green:(float)green / 255.0f
1258 blue:(float)blue / 255.0f];
1271 #ifdef ENABLE_MFI_SENSORS
1273 if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
1274 GCController *controller =
joystick->hwdata->controller;
1275 GCMotion *motion = controller.motion;
1277 motion.sensorsActive =
enabled ? YES : NO;
1296 if (
device->accelerometer) {
1298 }
else if (
device->controller) {
1315 #ifdef ENABLE_MFI_RUMBLE
1317 SDL_RumbleContext *rumble = (__bridge SDL_RumbleContext *)
device->rumble;
1320 CFRelease(
device->rumble);
1325 if (
device->accelerometer) {
1326 #ifdef SDL_JOYSTICK_iOS_ACCELEROMETER
1327 [motionManager stopAccelerometerUpdates];
1329 }
else if (
device->controller) {
1330 #ifdef SDL_JOYSTICK_MFI
1331 GCController *controller =
device->controller;
1332 controller.controllerPausedHandler = nil;
1333 controller.playerIndex = -1;
1346 #ifdef SDL_JOYSTICK_MFI
1347 NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
1349 if (connectObserver) {
1350 [center removeObserver:connectObserver name:GCControllerDidConnectNotification object:nil];
1351 connectObserver = nil;
1354 if (disconnectObserver) {
1355 [center removeObserver:disconnectObserver name:GCControllerDidDisconnectNotification object:nil];
1356 disconnectObserver = nil;
1361 SDL_AppleTVRemoteRotationHintChanged,
NULL);
1369 #ifdef SDL_JOYSTICK_iOS_ACCELEROMETER
1370 motionManager = nil;
1383 #if defined(SDL_JOYSTICK_MFI) && defined(__MACOSX__)
#define SDL_DelHintCallback
#define SDL_GetHintBoolean
#define SDL_AddHintCallback
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
#define SDL_Unsupported()
@ SDL_CONTROLLER_BUTTON_B
@ SDL_CONTROLLER_BUTTON_BACK
@ SDL_CONTROLLER_BUTTON_LEFTSTICK
@ SDL_CONTROLLER_BUTTON_START
@ SDL_CONTROLLER_BUTTON_PADDLE2
@ SDL_CONTROLLER_BUTTON_PADDLE1
@ SDL_CONTROLLER_BUTTON_RIGHTSHOULDER
@ SDL_CONTROLLER_BUTTON_LEFTSHOULDER
@ SDL_CONTROLLER_BUTTON_GUIDE
@ SDL_CONTROLLER_BUTTON_MISC1
@ SDL_CONTROLLER_BUTTON_X
@ SDL_CONTROLLER_BUTTON_RIGHTSTICK
@ SDL_CONTROLLER_BUTTON_PADDLE3
@ SDL_CONTROLLER_BUTTON_Y
@ SDL_CONTROLLER_BUTTON_A
@ SDL_CONTROLLER_BUTTON_PADDLE4
const GLubyte GLuint GLuint GLuint GLuint alpha GLboolean GLboolean GLboolean GLboolean alpha GLint GLint GLsizei GLsizei GLenum type GLenum GLint GLenum GLint GLint GLsizei GLsizei GLint border GLenum GLint GLint GLint GLint GLint GLsizei GLsizei height GLsizei GLsizei GLenum GLenum const GLvoid *pixels GLenum GLint GLint GLint GLint j2 GLdouble GLdouble GLdouble GLdouble GLdouble GLdouble zFar GLenum light
#define SDL_HINT_ACCELEROMETER_AS_JOYSTICK
A variable controlling whether the Android / iOS built-in accelerometer should be listed as a joystic...
#define SDL_HINT_TV_REMOTE_AS_JOYSTICK
A variable controlling whether the Android / tvOS remotes should be listed as joystick devices,...
#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_PrivateJoystickTouchpad(SDL_Joystick *joystick, int touchpad, int finger, Uint8 state, float x, float y, float pressure)
void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick, SDL_JoystickPowerLevel ePowerLevel)
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers)
void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
int SDL_PrivateJoystickSensor(SDL_Joystick *joystick, SDL_SensorType type, const float *data, int num_values)
void SDL_PrivateJoystickAddSensor(SDL_Joystick *joystick, SDL_SensorType type)
SDL_JoystickID SDL_GetNextJoystickInstanceID()
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
char * SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, const char *product_name)
#define SDL_IPHONE_MAX_GFORCE
@ SDL_JOYSTICK_POWER_FULL
@ SDL_JOYSTICK_POWER_MEDIUM
@ SDL_JOYSTICK_POWER_EMPTY
@ SDL_JOYSTICK_POWER_UNKNOWN
@ SDL_JOYSTICK_POWER_WIRED
static int IOS_JoystickGetDevicePlayerIndex(int device_index)
static void IOS_JoystickDetect(void)
static int IOS_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
static SDL_JoystickDeviceItem * deviceList
static void IOS_JoystickClose(SDL_Joystick *joystick)
static void IOS_AccelerometerUpdate(SDL_Joystick *joystick)
SDL_JoystickDriver SDL_IOS_JoystickDriver
static SDL_JoystickGUID IOS_JoystickGetDeviceGUID(int device_index)
static void IOS_JoystickSetDevicePlayerIndex(int device_index, int player_index)
static void IOS_JoystickUpdate(SDL_Joystick *joystick)
static int IOS_JoystickOpen(SDL_Joystick *joystick, int device_index)
static int IOS_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
static int IOS_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
static SDL_JoystickDeviceItem * IOS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
static int IOS_JoystickGetCount(void)
static int IOS_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
static const char * IOS_JoystickGetDeviceName(int device_index)
static void IOS_JoystickQuit(void)
static int IOS_JoystickInit(void)
static SDL_bool IOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
static SDL_bool IOS_JoystickHasLED(SDL_Joystick *joystick)
static SDL_JoystickDeviceItem * GetDeviceForIndex(int device_index)
static SDL_JoystickID IOS_JoystickGetDeviceInstanceID(int device_index)
int SDL_AppleTVRemoteOpenedAsJoystick
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLuint const GLchar * name
#define SDL_STANDARD_GRAVITY
#define SDL_arraysize(array)
#define SDL_HARDWARE_BUS_BLUETOOTH
static SDL_VideoDevice * _this
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)
static SDL_AudioDeviceID device
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d ®2 endm macro vzip8 reg2 vzip d d ®2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld cleanup[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1 beq endif SRC MASK if dst_r_bpp DST_R else add endif PF add sub src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head pixblock_size cache_preload_simple process_pixblock_tail pixinterleave dst_w_basereg irp beq endif process_pixblock_tail_head tst beq irp if pixblock_size chunk_size tst beq pixld_src SRC pixld MASK if DST_R else pixld DST_R endif if src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head if pixblock_size cache_preload_simple endif process_pixblock_tail pixinterleave dst_w_basereg irp if pixblock_size chunk_size tst beq if DST_W else pixst DST_W else mov ORIG_W endif add lsl if lsl endif if lsl endif lsl endif lsl endif lsl endif subs mov DST_W if regs_shortage str endif bge start_of_loop_label endm macro generate_composite_function
struct joystick_hwdata * next
static SDL_Joystick * joystick
#define USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH
#define USB_VENDOR_MICROSOFT
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH
#define USB_PRODUCT_SONY_DS4_SLIM
typedef int(__stdcall *FARPROC)()