For initial detection, we run joystick events in a temporary runloop,
and then move it over to the main runloop, so the events land with
everything else. Maybe we should leave these in the separate runloop,
and run it in SDL_JoystickUpdate()?
(by ārunloopā I mean ārunloop mode,ā fwiw.)
Attached is a patch that implements what I described here. Iām away from
the office and donāt have any joysticks with me, so Iāll push this when
I get home and test, but if anyone wants to test in the meantime, this
should fix the problem.
āryan.
-------------- next part --------------
HG changeset patch
User Ryan C. Gordon <@icculus>
Date 1398396288 14400
Thu Apr 24 23:24:48 2014 -0400
Node ID 09d8e949731014ba3226aecf73050e35a54a5cdd
Parent 94af945dbb573f9de82036c3fa0759f495ac9a0a
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!
diff --git a/src/joystick/darwin/SDL_sysjoystick.c b/src/joystick/darwin/SDL_sysjoystick.c
ā a/src/joystick/darwin/SDL_sysjoystick.c
+++ b/src/joystick/darwin/SDL_sysjoystick.c
@@ -38,6 +38,8 @@
#include āā¦/ā¦/events/SDL_events_c.hā
#endif
+#define SDL_JOYSTICK_RUNLOOP_MODE CFSTR(āSDLJoystickā)+
/* The base object of the HID Manager API */
static IOHIDManagerRef hidman = NULL;
@@ -67,6 +69,11 @@
{
recDevice *pDeviceNext = NULL;
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 */
pDeviceNext = removeDevice->pNext;
@@ -378,7 +385,7 @@
/* Get notified when this device is disconnected. */
IOHIDDeviceRegisterRemovalCallback(ioHIDDeviceObject, JoystickDeviceWasRemovedCallback, device);
- IOHIDDeviceScheduleWithRunLoop(ioHIDDeviceObject, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
-
IOHIDDeviceScheduleWithRunLoop(ioHIDDeviceObject, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
/* Allocate an instance ID for this device */
device->instance_id = ++s_joystick_instance_id;
@@ -420,25 +427,19 @@
{
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) {
return SDL_FALSE;
}
IOHIDManagerRegisterDeviceMatchingCallback(hidman, JoystickDeviceWasAddedCallback, NULL);
-
IOHIDManagerScheduleWithRunLoop(hidman, runloop, tempRunLoopMode);
- IOHIDManagerScheduleWithRunLoop(hidman, runloop, SDL_JOYSTICK_RUNLOOP_MODE);
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. */
}
- /* Put this in the normal RunLoop mode now, for future hotplug events. */
- IOHIDManagerUnscheduleFromRunLoop(hidman, runloop, tempRunLoopMode);
- IOHIDManagerScheduleWithRunLoop(hidman, runloop, kCFRunLoopDefaultMode);
-
/* future hotplug events will come through SDL_JOYSTICK_RUNLOOP_MODE now. */
return SDL_TRUE; /* good to go. */
}
@@ -544,6 +545,10 @@
void
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) {
recDevice *device = gpDeviceList;
s_bDeviceAdded = SDL_FALSE;
@@ -793,6 +798,7 @@
}
if (hidman) {
-
IOHIDManagerUnscheduleFromRunLoop(hidman, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
IOHIDManagerClose(hidman, kIOHIDOptionsTypeNone);
CFRelease(hidman);
hidman = NULL;