From: David Lawrie Subject: [v1 2/2] winejoystick.drv/joystick_osx.c: sorts devices by location ID Message-Id: <1466818397-52671-4-git-send-email-david.dljunk@gmail.com> Date: Fri, 24 Jun 2016 18:33:17 -0700 In-Reply-To: <1466818397-52671-1-git-send-email-david.dljunk@gmail.com> References: <1466818397-52671-1-git-send-email-david.dljunk@gmail.com> Fixes https://bugs.winehq.org/show_bug.cgi?id=38997 for winmm joysticks Note: if multiple virtual joysticks have the same location ID, they will still be unordered Tested on OS X 10.10.5. Signed-off-by: David Lawrie --- dlls/winejoystick.drv/joystick_osx.c | 46 +++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/dlls/winejoystick.drv/joystick_osx.c b/dlls/winejoystick.drv/joystick_osx.c index 4ef30cc..b7f35fb 100644 --- a/dlls/winejoystick.drv/joystick_osx.c +++ b/dlls/winejoystick.drv/joystick_osx.c @@ -321,6 +321,34 @@ static CFIndex find_top_level(IOHIDDeviceRef hid_device, CFMutableArrayRef main_ /************************************************************************** * find_osx_devices */ + +/* + * Helper to sort array by location ID since they are consistent across boots & launches + */ +static CFComparisonResult CFDeviceArrayComparatorFunction(const void *val1, const void *val2, void *context) +{ +#pragma unused(context) + CFComparisonResult result = kCFCompareEqualTo; + + long loc1 = IOHIDDevice_GetLocationID((IOHIDDeviceRef)val1); + long loc2 = IOHIDDevice_GetLocationID((IOHIDDeviceRef)val2); + + if (loc1 < loc2) { + result = kCFCompareLessThan; + } else if (loc1 > loc2) { + result = kCFCompareGreaterThan; + } + return result; +} + +/* + * Helper to copy the CFSet to a CFArray + */ +static void CFSetApplierFunctionCopyToCFArray(const void *value, void *context) +{ + CFArrayAppendValue((CFMutableArrayRef)context, value); +} + static int find_osx_devices(void) { IOHIDManagerRef hid_manager; @@ -363,20 +391,16 @@ static int find_osx_devices(void) if (devset) { CFIndex num_devices, num_main_elements; - const void** refs; - CFArrayRef devices; + CFMutableArrayRef devices; num_devices = CFSetGetCount(devset); - refs = HeapAlloc(GetProcessHeap(), 0, num_devices * sizeof(*refs)); - if (!refs) - { - CFRelease(devset); - goto fail; - } - CFSetGetValues(devset, refs); - devices = CFArrayCreate(NULL, refs, num_devices, &kCFTypeArrayCallBacks); - HeapFree(GetProcessHeap(), 0, refs); + devices = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + /* copy devices from (unordered) set to array */ + CFSetApplyFunction(devset, CFSetApplierFunctionCopyToCFArray, (void *)devices); + /* now sort the array by location ID's */ + CFArraySortValues(devices, CFRangeMake(0, num_devices), CFDeviceArrayComparatorFunction, NULL); + CFRelease(devset); if (!devices) goto fail; -- 1.7.12.4 (Apple Git-37)