Skip to content

Commit 5d7562c

Browse files
committedApr 25, 2014
Mac OS X: Look for joystick hotplug in its own CFRunLoop.
This allows the joystick hotplug to function without the main event loop (specifically: without SDL_INIT_VIDEO), and moves explicit polling for joysticks where it belongs at the low-level: in SDL_SYS_JoystickDetect(). This lets apps call SDL_JoystickUpdate() to get hotplug events and keep SDL_NumJoysticks() correct, as expected. As SDL_PumpEvents() (and SDL_PollEvents, etc) calls SDL_JoystickUpdate(), existing apps will function as before. Thanks to "raskie" on the forums for pointing this out!
1 parent 8b28009 commit 5d7562c

File tree

1 file changed

+16
-10
lines changed

1 file changed

+16
-10
lines changed
 

‎src/joystick/darwin/SDL_sysjoystick.c

+16-10
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
#include "../../events/SDL_events_c.h"
3939
#endif
4040

41+
#define SDL_JOYSTICK_RUNLOOP_MODE CFSTR("SDLJoystick")
42+
4143
/* The base object of the HID Manager API */
4244
static IOHIDManagerRef hidman = NULL;
4345

@@ -67,6 +69,11 @@ FreeDevice(recDevice *removeDevice)
6769
{
6870
recDevice *pDeviceNext = NULL;
6971
if (removeDevice) {
72+
if (removeDevice->deviceRef) {
73+
IOHIDDeviceUnscheduleFromRunLoop(removeDevice->deviceRef, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
74+
removeDevice->deviceRef = NULL;
75+
}
76+
7077
/* save next device prior to disposing of this device */
7178
pDeviceNext = removeDevice->pNext;
7279

@@ -378,7 +385,7 @@ JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDevic
378385

379386
/* Get notified when this device is disconnected. */
380387
IOHIDDeviceRegisterRemovalCallback(ioHIDDeviceObject, JoystickDeviceWasRemovedCallback, device);
381-
IOHIDDeviceScheduleWithRunLoop(ioHIDDeviceObject, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
388+
IOHIDDeviceScheduleWithRunLoop(ioHIDDeviceObject, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
382389

383390
/* Allocate an instance ID for this device */
384391
device->instance_id = ++s_joystick_instance_id;
@@ -420,25 +427,19 @@ ConfigHIDManager(CFArrayRef matchingArray)
420427
{
421428
CFRunLoopRef runloop = CFRunLoopGetCurrent();
422429

423-
/* Run in a custom RunLoop mode just while initializing,
424-
so we can detect sticks without messing with everything else. */
425-
CFStringRef tempRunLoopMode = CFSTR("SDLJoystickInit");
426-
427430
if (IOHIDManagerOpen(hidman, kIOHIDOptionsTypeNone) != kIOReturnSuccess) {
428431
return SDL_FALSE;
429432
}
430433

431434
IOHIDManagerRegisterDeviceMatchingCallback(hidman, JoystickDeviceWasAddedCallback, NULL);
432-
IOHIDManagerScheduleWithRunLoop(hidman, runloop, tempRunLoopMode);
435+
IOHIDManagerScheduleWithRunLoop(hidman, runloop, SDL_JOYSTICK_RUNLOOP_MODE);
433436
IOHIDManagerSetDeviceMatchingMultiple(hidman, matchingArray);
434437

435-
while (CFRunLoopRunInMode(tempRunLoopMode,0,TRUE)==kCFRunLoopRunHandledSource) {
438+
while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE,0,TRUE) == kCFRunLoopRunHandledSource) {
436439
/* no-op. Callback fires once per existing device. */
437440
}
438441

439-
/* Put this in the normal RunLoop mode now, for future hotplug events. */
440-
IOHIDManagerUnscheduleFromRunLoop(hidman, runloop, tempRunLoopMode);
441-
IOHIDManagerScheduleWithRunLoop(hidman, runloop, kCFRunLoopDefaultMode);
442+
/* future hotplug events will come through SDL_JOYSTICK_RUNLOOP_MODE now. */
442443

443444
return SDL_TRUE; /* good to go. */
444445
}
@@ -544,6 +545,10 @@ SDL_SYS_NumJoysticks()
544545
void
545546
SDL_SYS_JoystickDetect()
546547
{
548+
while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE,0,TRUE) == kCFRunLoopRunHandledSource) {
549+
/* no-op. Pending callbacks will fire in CFRunLoopRunInMode(). */
550+
}
551+
547552
if (s_bDeviceAdded || s_bDeviceRemoved) {
548553
recDevice *device = gpDeviceList;
549554
s_bDeviceAdded = SDL_FALSE;
@@ -793,6 +798,7 @@ SDL_SYS_JoystickQuit(void)
793798
}
794799

795800
if (hidman) {
801+
IOHIDManagerUnscheduleFromRunLoop(hidman, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
796802
IOHIDManagerClose(hidman, kIOHIDOptionsTypeNone);
797803
CFRelease(hidman);
798804
hidman = NULL;

0 commit comments

Comments
 (0)