mirror of https://github.com/encounter/SDL.git
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!
This commit is contained in:
parent
8b28009105
commit
5d7562c7e2
|
@ -38,6 +38,8 @@
|
||||||
#include "../../events/SDL_events_c.h"
|
#include "../../events/SDL_events_c.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SDL_JOYSTICK_RUNLOOP_MODE CFSTR("SDLJoystick")
|
||||||
|
|
||||||
/* The base object of the HID Manager API */
|
/* The base object of the HID Manager API */
|
||||||
static IOHIDManagerRef hidman = NULL;
|
static IOHIDManagerRef hidman = NULL;
|
||||||
|
|
||||||
|
@ -67,6 +69,11 @@ FreeDevice(recDevice *removeDevice)
|
||||||
{
|
{
|
||||||
recDevice *pDeviceNext = NULL;
|
recDevice *pDeviceNext = NULL;
|
||||||
if (removeDevice) {
|
if (removeDevice) {
|
||||||
|
if (removeDevice->deviceRef) {
|
||||||
|
IOHIDDeviceUnscheduleFromRunLoop(removeDevice->deviceRef, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
|
||||||
|
removeDevice->deviceRef = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* save next device prior to disposing of this device */
|
/* save next device prior to disposing of this device */
|
||||||
pDeviceNext = removeDevice->pNext;
|
pDeviceNext = removeDevice->pNext;
|
||||||
|
|
||||||
|
@ -378,7 +385,7 @@ JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDevic
|
||||||
|
|
||||||
/* Get notified when this device is disconnected. */
|
/* Get notified when this device is disconnected. */
|
||||||
IOHIDDeviceRegisterRemovalCallback(ioHIDDeviceObject, JoystickDeviceWasRemovedCallback, device);
|
IOHIDDeviceRegisterRemovalCallback(ioHIDDeviceObject, JoystickDeviceWasRemovedCallback, device);
|
||||||
IOHIDDeviceScheduleWithRunLoop(ioHIDDeviceObject, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
IOHIDDeviceScheduleWithRunLoop(ioHIDDeviceObject, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
|
||||||
|
|
||||||
/* Allocate an instance ID for this device */
|
/* Allocate an instance ID for this device */
|
||||||
device->instance_id = ++s_joystick_instance_id;
|
device->instance_id = ++s_joystick_instance_id;
|
||||||
|
@ -420,25 +427,19 @@ ConfigHIDManager(CFArrayRef matchingArray)
|
||||||
{
|
{
|
||||||
CFRunLoopRef runloop = CFRunLoopGetCurrent();
|
CFRunLoopRef runloop = CFRunLoopGetCurrent();
|
||||||
|
|
||||||
/* Run in a custom RunLoop mode just while initializing,
|
|
||||||
so we can detect sticks without messing with everything else. */
|
|
||||||
CFStringRef tempRunLoopMode = CFSTR("SDLJoystickInit");
|
|
||||||
|
|
||||||
if (IOHIDManagerOpen(hidman, kIOHIDOptionsTypeNone) != kIOReturnSuccess) {
|
if (IOHIDManagerOpen(hidman, kIOHIDOptionsTypeNone) != kIOReturnSuccess) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
IOHIDManagerRegisterDeviceMatchingCallback(hidman, JoystickDeviceWasAddedCallback, NULL);
|
IOHIDManagerRegisterDeviceMatchingCallback(hidman, JoystickDeviceWasAddedCallback, NULL);
|
||||||
IOHIDManagerScheduleWithRunLoop(hidman, runloop, tempRunLoopMode);
|
IOHIDManagerScheduleWithRunLoop(hidman, runloop, SDL_JOYSTICK_RUNLOOP_MODE);
|
||||||
IOHIDManagerSetDeviceMatchingMultiple(hidman, matchingArray);
|
IOHIDManagerSetDeviceMatchingMultiple(hidman, matchingArray);
|
||||||
|
|
||||||
while (CFRunLoopRunInMode(tempRunLoopMode,0,TRUE)==kCFRunLoopRunHandledSource) {
|
while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE,0,TRUE) == kCFRunLoopRunHandledSource) {
|
||||||
/* no-op. Callback fires once per existing device. */
|
/* no-op. Callback fires once per existing device. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put this in the normal RunLoop mode now, for future hotplug events. */
|
/* future hotplug events will come through SDL_JOYSTICK_RUNLOOP_MODE now. */
|
||||||
IOHIDManagerUnscheduleFromRunLoop(hidman, runloop, tempRunLoopMode);
|
|
||||||
IOHIDManagerScheduleWithRunLoop(hidman, runloop, kCFRunLoopDefaultMode);
|
|
||||||
|
|
||||||
return SDL_TRUE; /* good to go. */
|
return SDL_TRUE; /* good to go. */
|
||||||
}
|
}
|
||||||
|
@ -544,6 +545,10 @@ SDL_SYS_NumJoysticks()
|
||||||
void
|
void
|
||||||
SDL_SYS_JoystickDetect()
|
SDL_SYS_JoystickDetect()
|
||||||
{
|
{
|
||||||
|
while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE,0,TRUE) == kCFRunLoopRunHandledSource) {
|
||||||
|
/* no-op. Pending callbacks will fire in CFRunLoopRunInMode(). */
|
||||||
|
}
|
||||||
|
|
||||||
if (s_bDeviceAdded || s_bDeviceRemoved) {
|
if (s_bDeviceAdded || s_bDeviceRemoved) {
|
||||||
recDevice *device = gpDeviceList;
|
recDevice *device = gpDeviceList;
|
||||||
s_bDeviceAdded = SDL_FALSE;
|
s_bDeviceAdded = SDL_FALSE;
|
||||||
|
@ -793,6 +798,7 @@ SDL_SYS_JoystickQuit(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hidman) {
|
if (hidman) {
|
||||||
|
IOHIDManagerUnscheduleFromRunLoop(hidman, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
|
||||||
IOHIDManagerClose(hidman, kIOHIDOptionsTypeNone);
|
IOHIDManagerClose(hidman, kIOHIDOptionsTypeNone);
|
||||||
CFRelease(hidman);
|
CFRelease(hidman);
|
||||||
hidman = NULL;
|
hidman = NULL;
|
||||||
|
|
Loading…
Reference in New Issue