SDL  2.0
SDL_sysjoystick.m
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 /* This is the iOS implementation of the SDL joystick API */
24 #include "SDL_sysjoystick_c.h"
25 
26 /* needed for SDL_IPHONE_MAX_GFORCE macro */
27 #include "SDL_config_iphoneos.h"
28 
29 #include "SDL_events.h"
30 #include "SDL_joystick.h"
31 #include "SDL_hints.h"
32 #include "SDL_stdinc.h"
33 #include "../SDL_sysjoystick.h"
34 #include "../SDL_joystick_c.h"
35 
36 #if !SDL_EVENTS_DISABLED
37 #include "../../events/SDL_events_c.h"
38 #endif
39 
40 #if !TARGET_OS_TV
41 #import <CoreMotion/CoreMotion.h>
42 #endif
43 
44 #ifdef SDL_JOYSTICK_MFI
45 #import <GameController/GameController.h>
46 
47 static id connectObserver = nil;
48 static id disconnectObserver = nil;
49 #endif /* SDL_JOYSTICK_MFI */
50 
51 #if !TARGET_OS_TV
52 static const char *accelerometerName = "iOS Accelerometer";
53 static CMMotionManager *motionManager = nil;
54 #endif /* !TARGET_OS_TV */
55 
57 
58 static int numjoysticks = 0;
60 
62 GetDeviceForIndex(int device_index)
63 {
65  int i = 0;
66 
67  while (i < device_index) {
68  if (device == NULL) {
69  return NULL;
70  }
71  device = device->next;
72  i++;
73  }
74 
75  return device;
76 }
77 
78 static void
80 {
81 #ifdef SDL_JOYSTICK_MFI
82  const char *name = NULL;
83  /* Explicitly retain the controller because SDL_JoystickDeviceItem is a
84  * struct, and ARC doesn't work with structs. */
85  device->controller = (__bridge GCController *) CFBridgingRetain(controller);
86 
87  if (controller.vendorName) {
88  name = controller.vendorName.UTF8String;
89  }
90 
91  if (!name) {
92  name = "MFi Gamepad";
93  }
94 
95  device->name = SDL_strdup(name);
96 
97  device->guid.data[0] = 'M';
98  device->guid.data[1] = 'F';
99  device->guid.data[2] = 'i';
100  device->guid.data[3] = 'G';
101  device->guid.data[4] = 'a';
102  device->guid.data[5] = 'm';
103  device->guid.data[6] = 'e';
104  device->guid.data[7] = 'p';
105  device->guid.data[8] = 'a';
106  device->guid.data[9] = 'd';
107 
108  if (controller.extendedGamepad) {
109  device->guid.data[10] = 1;
110  } else if (controller.gamepad) {
111  device->guid.data[10] = 2;
112  }
113 #if TARGET_OS_TV
114  else if (controller.microGamepad) {
115  device->guid.data[10] = 3;
116  }
117 #endif /* TARGET_OS_TV */
118 
119  if (controller.extendedGamepad) {
120  device->naxes = 6; /* 2 thumbsticks and 2 triggers */
121  device->nhats = 1; /* d-pad */
122  device->nbuttons = 7; /* ABXY, shoulder buttons, pause button */
123  } else if (controller.gamepad) {
124  device->naxes = 0; /* no traditional analog inputs */
125  device->nhats = 1; /* d-pad */
126  device->nbuttons = 7; /* ABXY, shoulder buttons, pause button */
127  }
128 #if TARGET_OS_TV
129  else if (controller.microGamepad) {
130  device->naxes = 2; /* treat the touch surface as two axes */
131  device->nhats = 0; /* apparently the touch surface-as-dpad is buggy */
132  device->nbuttons = 3; /* AX, pause button */
133 
134  controller.microGamepad.allowsRotation = SDL_GetHintBoolean(SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION, SDL_FALSE);
135  }
136 #endif /* TARGET_OS_TV */
137 
138  /* This will be set when the first button press of the controller is
139  * detected. */
140  controller.playerIndex = -1;
141 
142 #endif /* SDL_JOYSTICK_MFI */
143 }
144 
145 static void
147 {
149 
150  while (device != NULL) {
151  if (device->controller == controller) {
152  return;
153  }
154  device = device->next;
155  }
156 
158  if (device == NULL) {
159  return;
160  }
161 
162  SDL_zerop(device);
163 
164  device->accelerometer = accelerometer;
165  device->instance_id = instancecounter++;
166 
167  if (accelerometer) {
168 #if TARGET_OS_TV
169  SDL_free(device);
170  return;
171 #else
172  device->name = SDL_strdup(accelerometerName);
173  device->naxes = 3; /* Device acceleration in the x, y, and z axes. */
174  device->nhats = 0;
175  device->nbuttons = 0;
176 
177  /* Use the accelerometer name as a GUID. */
178  SDL_memcpy(&device->guid.data, device->name, SDL_min(sizeof(SDL_JoystickGUID), SDL_strlen(device->name)));
179 #endif /* TARGET_OS_TV */
180  } else if (controller) {
181  SDL_SYS_AddMFIJoystickDevice(device, controller);
182  }
183 
184  if (deviceList == NULL) {
185  deviceList = device;
186  } else {
187  SDL_JoystickDeviceItem *lastdevice = deviceList;
188  while (lastdevice->next != NULL) {
189  lastdevice = lastdevice->next;
190  }
191  lastdevice->next = device;
192  }
193 
194  ++numjoysticks;
195 
197 }
198 
199 static SDL_JoystickDeviceItem *
201 {
205 
206  if (device == NULL) {
207  return NULL;
208  }
209 
210  next = device->next;
211 
212  while (item != NULL) {
213  if (item == device) {
214  break;
215  }
216  prev = item;
217  item = item->next;
218  }
219 
220  /* Unlink the device item from the device list. */
221  if (prev) {
222  prev->next = device->next;
223  } else if (device == deviceList) {
224  deviceList = device->next;
225  }
226 
227  if (device->joystick) {
228  device->joystick->hwdata = NULL;
229  }
230 
231 #ifdef SDL_JOYSTICK_MFI
232  @autoreleasepool {
233  if (device->controller) {
234  /* The controller was explicitly retained in the struct, so it
235  * should be explicitly released before freeing the struct. */
236  GCController *controller = CFBridgingRelease((__bridge CFTypeRef)(device->controller));
237  controller.controllerPausedHandler = nil;
238  device->controller = nil;
239  }
240  }
241 #endif /* SDL_JOYSTICK_MFI */
242 
243  --numjoysticks;
244 
246 
247  SDL_free(device->name);
248  SDL_free(device);
249 
250  return next;
251 }
252 
253 #if TARGET_OS_TV
254 static void SDLCALL
255 SDL_AppleTVRemoteRotationHintChanged(void *udata, const char *name, const char *oldValue, const char *newValue)
256 {
257  BOOL allowRotation = newValue != NULL && *newValue != '0';
258 
259  @autoreleasepool {
260  for (GCController *controller in [GCController controllers]) {
261  if (controller.microGamepad) {
262  controller.microGamepad.allowsRotation = allowRotation;
263  }
264  }
265  }
266 }
267 #endif /* TARGET_OS_TV */
268 
269 /* Function to scan the system for joysticks.
270  * Joystick 0 should be the system default joystick.
271  * It should return 0, or -1 on an unrecoverable fatal error.
272  */
273 int
275 {
276  @autoreleasepool {
277  NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
278 
279 #if !TARGET_OS_TV
281  /* Default behavior, accelerometer as joystick */
283  }
284 #endif /* !TARGET_OS_TV */
285 
286 #ifdef SDL_JOYSTICK_MFI
287  /* GameController.framework was added in iOS 7. */
288  if (![GCController class]) {
289  return numjoysticks;
290  }
291 
292  for (GCController *controller in [GCController controllers]) {
294  }
295 
296 #if TARGET_OS_TV
298  SDL_AppleTVRemoteRotationHintChanged, NULL);
299 #endif /* TARGET_OS_TV */
300 
301  connectObserver = [center addObserverForName:GCControllerDidConnectNotification
302  object:nil
303  queue:nil
304  usingBlock:^(NSNotification *note) {
305  GCController *controller = note.object;
306  SDL_SYS_AddJoystickDevice(controller, SDL_FALSE);
307  }];
308 
309  disconnectObserver = [center addObserverForName:GCControllerDidDisconnectNotification
310  object:nil
311  queue:nil
312  usingBlock:^(NSNotification *note) {
313  GCController *controller = note.object;
314  SDL_JoystickDeviceItem *device = deviceList;
315  while (device != NULL) {
316  if (device->controller == controller) {
317  SDL_SYS_RemoveJoystickDevice(device);
318  break;
319  }
320  device = device->next;
321  }
322  }];
323 #endif /* SDL_JOYSTICK_MFI */
324  }
325 
326  return numjoysticks;
327 }
328 
329 int
331 {
332  return numjoysticks;
333 }
334 
335 void
337 {
338 }
339 
340 /* Function to get the device-dependent name of a joystick */
341 const char *
343 {
345  return device ? device->name : "Unknown";
346 }
347 
348 /* Function to perform the mapping from device index to the instance id for this index */
350 {
352  return device ? device->instance_id : 0;
353 }
354 
355 /* Function to open a joystick for use.
356  The joystick to open is specified by the device index.
357  This should fill the nbuttons and naxes fields of the joystick structure.
358  It returns 0, or -1 if there is an error.
359  */
360 int
361 SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
362 {
364  if (device == NULL) {
365  return SDL_SetError("Could not open Joystick: no hardware device for the specified index");
366  }
367 
368  joystick->hwdata = device;
369  joystick->instance_id = device->instance_id;
370 
371  joystick->naxes = device->naxes;
372  joystick->nhats = device->nhats;
373  joystick->nbuttons = device->nbuttons;
374  joystick->nballs = 0;
375 
376  device->joystick = joystick;
377 
378  @autoreleasepool {
379  if (device->accelerometer) {
380 #if !TARGET_OS_TV
381  if (motionManager == nil) {
382  motionManager = [[CMMotionManager alloc] init];
383  }
384 
385  /* Shorter times between updates can significantly increase CPU usage. */
386  motionManager.accelerometerUpdateInterval = 0.1;
387  [motionManager startAccelerometerUpdates];
388 #endif /* !TARGET_OS_TV */
389  } else {
390 #ifdef SDL_JOYSTICK_MFI
391  GCController *controller = device->controller;
392  controller.controllerPausedHandler = ^(GCController *c) {
393  if (joystick->hwdata) {
394  ++joystick->hwdata->num_pause_presses;
395  }
396  };
397 #endif /* SDL_JOYSTICK_MFI */
398  }
399  }
400 
401  return 0;
402 }
403 
404 /* Function to determine if this joystick is attached to the system right now */
405 SDL_bool
407 {
408  return joystick->hwdata != NULL;
409 }
410 
411 static void
413 {
414 #if !TARGET_OS_TV
415  const float maxgforce = SDL_IPHONE_MAX_GFORCE;
416  const SInt16 maxsint16 = 0x7FFF;
417  CMAcceleration accel;
418 
419  @autoreleasepool {
420  if (!motionManager.isAccelerometerActive) {
421  return;
422  }
423 
424  accel = motionManager.accelerometerData.acceleration;
425  }
426 
427  /*
428  Convert accelerometer data from floating point to Sint16, which is what
429  the joystick system expects.
430 
431  To do the conversion, the data is first clamped onto the interval
432  [-SDL_IPHONE_MAX_G_FORCE, SDL_IPHONE_MAX_G_FORCE], then the data is multiplied
433  by MAX_SINT16 so that it is mapped to the full range of an Sint16.
434 
435  You can customize the clamped range of this function by modifying the
436  SDL_IPHONE_MAX_GFORCE macro in SDL_config_iphoneos.h.
437 
438  Once converted to Sint16, the accelerometer data no longer has coherent
439  units. You can convert the data back to units of g-force by multiplying
440  it in your application's code by SDL_IPHONE_MAX_GFORCE / 0x7FFF.
441  */
442 
443  /* clamp the data */
444  accel.x = SDL_min(SDL_max(accel.x, -maxgforce), maxgforce);
445  accel.y = SDL_min(SDL_max(accel.y, -maxgforce), maxgforce);
446  accel.z = SDL_min(SDL_max(accel.z, -maxgforce), maxgforce);
447 
448  /* pass in data mapped to range of SInt16 */
449  SDL_PrivateJoystickAxis(joystick, 0, (accel.x / maxgforce) * maxsint16);
450  SDL_PrivateJoystickAxis(joystick, 1, -(accel.y / maxgforce) * maxsint16);
451  SDL_PrivateJoystickAxis(joystick, 2, (accel.z / maxgforce) * maxsint16);
452 #endif /* !TARGET_OS_TV */
453 }
454 
455 #ifdef SDL_JOYSTICK_MFI
456 static Uint8
457 SDL_SYS_MFIJoystickHatStateForDPad(GCControllerDirectionPad *dpad)
458 {
459  Uint8 hat = 0;
460 
461  if (dpad.up.isPressed) {
462  hat |= SDL_HAT_UP;
463  } else if (dpad.down.isPressed) {
464  hat |= SDL_HAT_DOWN;
465  }
466 
467  if (dpad.left.isPressed) {
468  hat |= SDL_HAT_LEFT;
469  } else if (dpad.right.isPressed) {
470  hat |= SDL_HAT_RIGHT;
471  }
472 
473  if (hat == 0) {
474  return SDL_HAT_CENTERED;
475  }
476 
477  return hat;
478 }
479 #endif
480 
481 static void
483 {
484 #if SDL_JOYSTICK_MFI
485  @autoreleasepool {
486  GCController *controller = joystick->hwdata->controller;
487  Uint8 hatstate = SDL_HAT_CENTERED;
488  int i;
489  int updateplayerindex = 0;
490 
491  if (controller.extendedGamepad) {
492  GCExtendedGamepad *gamepad = controller.extendedGamepad;
493 
494  /* Axis order matches the XInput Windows mappings. */
495  Sint16 axes[] = {
496  (Sint16) (gamepad.leftThumbstick.xAxis.value * 32767),
497  (Sint16) (gamepad.leftThumbstick.yAxis.value * -32767),
498  (Sint16) ((gamepad.leftTrigger.value * 65535) - 32768),
499  (Sint16) (gamepad.rightThumbstick.xAxis.value * 32767),
500  (Sint16) (gamepad.rightThumbstick.yAxis.value * -32767),
501  (Sint16) ((gamepad.rightTrigger.value * 65535) - 32768),
502  };
503 
504  /* Button order matches the XInput Windows mappings. */
505  Uint8 buttons[] = {
506  gamepad.buttonA.isPressed, gamepad.buttonB.isPressed,
507  gamepad.buttonX.isPressed, gamepad.buttonY.isPressed,
508  gamepad.leftShoulder.isPressed,
509  gamepad.rightShoulder.isPressed,
510  };
511 
512  hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad);
513 
514  for (i = 0; i < SDL_arraysize(axes); i++) {
515  /* The triggers (axes 2 and 5) are resting at -32768 but SDL
516  * initializes its values to 0. We only want to make sure the
517  * player index is up to date if the user actually moves an axis. */
518  if ((i != 2 && i != 5) || axes[i] != -32768) {
519  updateplayerindex |= (joystick->axes[i].value != axes[i]);
520  }
521  SDL_PrivateJoystickAxis(joystick, i, axes[i]);
522  }
523 
524  for (i = 0; i < SDL_arraysize(buttons); i++) {
525  updateplayerindex |= (joystick->buttons[i] != buttons[i]);
526  SDL_PrivateJoystickButton(joystick, i, buttons[i]);
527  }
528  } else if (controller.gamepad) {
529  GCGamepad *gamepad = controller.gamepad;
530 
531  /* Button order matches the XInput Windows mappings. */
532  Uint8 buttons[] = {
533  gamepad.buttonA.isPressed, gamepad.buttonB.isPressed,
534  gamepad.buttonX.isPressed, gamepad.buttonY.isPressed,
535  gamepad.leftShoulder.isPressed,
536  gamepad.rightShoulder.isPressed,
537  };
538 
539  hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad);
540 
541  for (i = 0; i < SDL_arraysize(buttons); i++) {
542  updateplayerindex |= (joystick->buttons[i] != buttons[i]);
543  SDL_PrivateJoystickButton(joystick, i, buttons[i]);
544  }
545  }
546 #if TARGET_OS_TV
547  else if (controller.microGamepad) {
548  GCMicroGamepad *gamepad = controller.microGamepad;
549 
550  Sint16 axes[] = {
551  (Sint16) (gamepad.dpad.xAxis.value * 32767),
552  (Sint16) (gamepad.dpad.yAxis.value * -32767),
553  };
554 
555  for (i = 0; i < SDL_arraysize(axes); i++) {
556  updateplayerindex |= (joystick->axes[i].value != axes[i]);
557  SDL_PrivateJoystickAxis(joystick, i, axes[i]);
558  }
559 
560  /* Apparently the dpad values are not accurate enough to be useful. */
561  /* hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad); */
562 
563  Uint8 buttons[] = {
564  gamepad.buttonA.isPressed,
565  gamepad.buttonX.isPressed,
566  };
567 
568  for (i = 0; i < SDL_arraysize(buttons); i++) {
569  updateplayerindex |= (joystick->buttons[i] != buttons[i]);
570  SDL_PrivateJoystickButton(joystick, i, buttons[i]);
571  }
572 
573  /* TODO: Figure out what to do with reportsAbsoluteDpadValues */
574  }
575 #endif /* TARGET_OS_TV */
576 
577  if (joystick->nhats > 0) {
578  updateplayerindex |= (joystick->hats[0] != hatstate);
579  SDL_PrivateJoystickHat(joystick, 0, hatstate);
580  }
581 
582  for (i = 0; i < joystick->hwdata->num_pause_presses; i++) {
583  /* The pause button is always last. */
584  Uint8 pausebutton = joystick->nbuttons - 1;
585 
586  SDL_PrivateJoystickButton(joystick, pausebutton, SDL_PRESSED);
587  SDL_PrivateJoystickButton(joystick, pausebutton, SDL_RELEASED);
588 
589  updateplayerindex = YES;
590  }
591 
592  joystick->hwdata->num_pause_presses = 0;
593 
594  if (updateplayerindex && controller.playerIndex == -1) {
595  BOOL usedPlayerIndexSlots[4] = {NO, NO, NO, NO};
596 
597  /* Find the player index of all other connected controllers. */
598  for (GCController *c in [GCController controllers]) {
599  if (c != controller && c.playerIndex >= 0) {
600  usedPlayerIndexSlots[c.playerIndex] = YES;
601  }
602  }
603 
604  /* Set this controller's player index to the first unused index.
605  * FIXME: This logic isn't great... but SDL doesn't expose this
606  * concept in its external API, so we don't have much to go on. */
607  for (i = 0; i < SDL_arraysize(usedPlayerIndexSlots); i++) {
608  if (!usedPlayerIndexSlots[i]) {
609  controller.playerIndex = i;
610  break;
611  }
612  }
613  }
614  }
615 #endif /* SDL_JOYSTICK_MFI */
616 }
617 
618 /* Function to update the state of a joystick - called as a device poll.
619  * This function shouldn't update the joystick structure directly,
620  * but instead should call SDL_PrivateJoystick*() to deliver events
621  * and update joystick device state.
622  */
623 void
625 {
626  SDL_JoystickDeviceItem *device = joystick->hwdata;
627 
628  if (device == NULL) {
629  return;
630  }
631 
632  if (device->accelerometer) {
633  SDL_SYS_AccelerometerUpdate(joystick);
634  } else if (device->controller) {
635  SDL_SYS_MFIJoystickUpdate(joystick);
636  }
637 }
638 
639 /* Function to close a joystick after use */
640 void
642 {
643  SDL_JoystickDeviceItem *device = joystick->hwdata;
644 
645  if (device == NULL) {
646  return;
647  }
648 
649  device->joystick = NULL;
650 
651  @autoreleasepool {
652  if (device->accelerometer) {
653 #if !TARGET_OS_TV
654  [motionManager stopAccelerometerUpdates];
655 #endif /* !TARGET_OS_TV */
656  } else if (device->controller) {
657 #ifdef SDL_JOYSTICK_MFI
658  GCController *controller = device->controller;
659  controller.controllerPausedHandler = nil;
660  controller.playerIndex = -1;
661 #endif
662  }
663  }
664 }
665 
666 /* Function to perform any system-specific joystick related cleanup */
667 void
669 {
670  @autoreleasepool {
671 #ifdef SDL_JOYSTICK_MFI
672  NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
673 
674  if (connectObserver) {
675  [center removeObserver:connectObserver name:GCControllerDidConnectNotification object:nil];
676  connectObserver = nil;
677  }
678 
679  if (disconnectObserver) {
680  [center removeObserver:disconnectObserver name:GCControllerDidDisconnectNotification object:nil];
681  disconnectObserver = nil;
682  }
683 
684 #if TARGET_OS_TV
686  SDL_AppleTVRemoteRotationHintChanged, NULL);
687 #endif /* TARGET_OS_TV */
688 #endif /* SDL_JOYSTICK_MFI */
689 
690  while (deviceList != NULL) {
691  SDL_SYS_RemoveJoystickDevice(deviceList);
692  }
693 
694 #if !TARGET_OS_TV
695  motionManager = nil;
696 #endif /* !TARGET_OS_TV */
697  }
698 
699  numjoysticks = 0;
700 }
701 
703 SDL_SYS_JoystickGetDeviceGUID( int device_index )
704 {
707  if (device) {
708  guid = device->guid;
709  } else {
710  SDL_zero(guid);
711  }
712  return guid;
713 }
714 
717 {
719  if (joystick->hwdata) {
720  guid = joystick->hwdata->guid;
721  } else {
722  SDL_zero(guid);
723  }
724  return guid;
725 }
726 
727 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_min(x, y)
Definition: SDL_stdinc.h:375
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
Definition: SDL_joystick.c:641
SDL_JoystickGUID guid
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
Definition: SDL_joystick.c:718
static SDL_JoystickDeviceItem * deviceList
SDL_Joystick * joystick
static void SDL_SYS_MFIJoystickUpdate(SDL_Joystick *joystick)
#define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION
A variable controlling whether the Apple TV remote's joystick axes will automatically match the rotat...
Definition: SDL_hints.h:355
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
Definition: SDL_joystick.c:794
static const char * accelerometerName
struct joystick_hwdata * next
void SDL_SYS_JoystickQuit(void)
static SDL_JoystickDeviceItem * GetDeviceForIndex(int device_index)
Uint8 data[16]
Definition: SDL_joystick.h:71
#define SDL_zerop(x)
Definition: SDL_stdinc.h:386
#define SDL_max(x, y)
Definition: SDL_stdinc.h:376
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
Definition: SDL_joystick.c:661
GLuint const GLchar * name
#define SDL_GetHintBoolean
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)
Definition: SDL_x11sym.h:50
static SDL_AudioDeviceID device
Definition: loopwave.c:37
#define SDL_HAT_RIGHT
Definition: SDL_joystick.h:304
#define SDL_memcpy
#define SDL_HINT_ACCELEROMETER_AS_JOYSTICK
A variable controlling whether the Android / iOS built-in accelerometer should be listed as a joystic...
Definition: SDL_hints.h:366
Sint32 SDL_JoystickID
Definition: SDL_joystick.h:81
#define SDL_HAT_LEFT
Definition: SDL_joystick.h:306
uint8_t Uint8
Definition: SDL_stdinc.h:157
void SDL_free(void *mem)
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
static void SDL_SYS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller)
const GLubyte * c
void SDL_PrivateJoystickAdded(int device_index)
Definition: SDL_joystick.c:595
#define SDL_zero(x)
Definition: SDL_stdinc.h:385
const char * SDL_SYS_JoystickNameForDeviceIndex(int device_index)
void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick *joystick)
int SDL_SYS_JoystickInit(void)
#define SDL_IPHONE_MAX_GFORCE
#define NULL
Definition: begin_code.h:164
SDL_bool
Definition: SDL_stdinc.h:139
int SDL_SYS_NumJoysticks(void)
#define SDL_SetError
static void SDL_SYS_AccelerometerUpdate(SDL_Joystick *joystick)
static SDL_JoystickID instancecounter
#define SDL_strlen
#define SDL_strdup
struct SDL_joylist_item * item
#define SDL_AddHintCallback
#define SDL_DelHintCallback
static SDL_JoystickDeviceItem * SDL_SYS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
static int numjoysticks
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
int SDL_SYS_JoystickOpen(SDL_Joystick *joystick, int device_index)
#define SDL_malloc
#define SDL_PRESSED
Definition: SDL_events.h:50
#define SDL_HAT_CENTERED
Definition: SDL_joystick.h:302
void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
#define SDL_RELEASED
Definition: SDL_events.h:49
GLuint in
#define SDL_HAT_UP
Definition: SDL_joystick.h:303
static void SDL_SYS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
#define SDLCALL
Definition: SDL_internal.h:45
#define SDL_HAT_DOWN
Definition: SDL_joystick.h:305
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int device_index)
GCController __unsafe_unretained * controller
int16_t Sint16
Definition: SDL_stdinc.h:163
void SDL_SYS_JoystickDetect(void)
static CMMotionManager * motionManager