@@ -319,6 +319,20 @@ static void add_elements(CFArrayRef elements, ALLEGRO_JOYSTICK_OSX *joy)
319319 joy->parent .info .num_buttons = num_buttons;
320320}
321321
322+ static NSInteger element_compare_func (id val1, id val2)
323+ {
324+ IOHIDElementRef elem1 = [(NSValue *)val1 pointerValue ];
325+ IOHIDElementRef elem2 = [(NSValue *)val2 pointerValue ];
326+
327+ int usage1 = IOHIDElementGetUsage (elem1);
328+ int usage2 = IOHIDElementGetUsage (elem2);
329+ if (usage1 < usage2)
330+ return kCFCompareLessThan ;
331+ if (usage1 > usage2)
332+ return kCFCompareGreaterThan ;
333+ return kCFCompareEqualTo ;
334+ }
335+
322336static bool add_elements_with_mapping (CFArrayRef elements, ALLEGRO_JOYSTICK_OSX *joy, const _AL_JOYSTICK_MAPPING *mapping)
323337{
324338 int num_buttons = 0 ;
@@ -329,6 +343,10 @@ static bool add_elements_with_mapping(CFArrayRef elements, ALLEGRO_JOYSTICK_OSX
329343 int num_axes_mapped = 0 ;
330344 _AL_JOYSTICK_OUTPUT *output;
331345
346+ NSMutableArray * buttons_elems = [[[NSMutableArray alloc ] init ] autorelease ];
347+ NSMutableArray * axes_elems = [[[NSMutableArray alloc ] init ] autorelease ];
348+ NSMutableArray * hats_elems = [[[NSMutableArray alloc ] init ] autorelease ];
349+
332350 for (int i = 0 ; i < CFArrayGetCount (elements); i++) {
333351 IOHIDElementRef elem = (IOHIDElementRef)CFArrayGetValueAtIndex (
334352 elements,
@@ -338,83 +356,107 @@ static bool add_elements_with_mapping(CFArrayRef elements, ALLEGRO_JOYSTICK_OSX
338356 int usage = IOHIDElementGetUsage (elem);
339357 int usage_page = IOHIDElementGetUsagePage (elem);
340358 if (IOHIDElementGetType (elem) == kIOHIDElementTypeInput_Button ) {
341- int idx = num_buttons;
342359 // 0x09 is the Button Page.
343360 if (usage_page != 0x09 )
344361 continue ;
345- if (idx >= 0 && idx < _AL_MAX_JOYSTICK_BUTTONS && !joy->buttons [idx].elem ) {
346- joy->buttons [idx].elem = elem;
347- output = _al_get_joystick_output (&mapping->button_map , idx);
348- if (output) {
349- joy->buttons [idx].output = *output;
350- num_buttons_mapped++;
351- }
352- num_buttons++;
353- }
362+ [buttons_elems addObject: [NSValue valueWithPointer: elem]];
354363 }
355364 else if (IOHIDElementGetType (elem) == kIOHIDElementTypeInput_Misc ) {
356- long min = IOHIDElementGetLogicalMin (elem);
357- long max = IOHIDElementGetLogicalMax (elem);
358-
359- int elem_kind = -1 ;
360365 switch (usage) {
361366 case kHIDUsage_GD_X :
362367 case kHIDUsage_GD_Y :
363368 case kHIDUsage_GD_Z :
364369 case kHIDUsage_GD_Rx :
365370 case kHIDUsage_GD_Ry :
366- case kHIDUsage_GD_Rz : {
367- elem_kind = 0 ;
371+ case kHIDUsage_GD_Rz :
372+ case kHIDUsage_GD_Slider :
373+ case kHIDUsage_GD_Dial :
374+ case kHIDUsage_GD_Wheel : {
375+ [axes_elems addObject: [NSValue valueWithPointer: elem]];
368376 break ;
369377 }
370378 case kHIDUsage_GD_Hatswitch : {
371- elem_kind = 1 ;
379+ [hats_elems addObject: [ NSValue valueWithPointer: elem]] ;
372380 break ;
373381 }
374382 default :
375383 continue ;
376384 }
385+ }
386+ }
377387
378- if (elem_kind < 0 )
379- continue ;
388+ // This sorting is inspired by what GLFW does.
389+ [buttons_elems sortWithOptions: NSSortStable
390+ usingComparator: ^NSComparisonResult (id val1, id val2) {
391+ return element_compare_func (val1, val2);
392+ }];
393+ [axes_elems sortWithOptions: NSSortStable
394+ usingComparator: ^NSComparisonResult (id val1, id val2) {
395+ return element_compare_func (val1, val2);
396+ }];
397+ [hats_elems sortWithOptions: NSSortStable
398+ usingComparator: ^NSComparisonResult (id val1, id val2) {
399+ return element_compare_func (val1, val2);
400+ }];
401+
402+ for (int i = 0 ; i < (int )[buttons_elems count ]; i++) {
403+ IOHIDElementRef elem = [(NSValue *)buttons_elems[i] pointerValue ];
404+ int idx = num_buttons;
405+ if (idx >= 0 && idx < _AL_MAX_JOYSTICK_BUTTONS && !joy->buttons [idx].elem ) {
406+ joy->buttons [idx].elem = elem;
407+ output = _al_get_joystick_output (&mapping->button_map , idx);
408+ if (output) {
409+ joy->buttons [idx].output = *output;
410+ num_buttons_mapped++;
411+ }
412+ num_buttons++;
413+ }
414+ }
380415
381- if (elem_kind == 1 ) {
382- if (num_hats >= _AL_MAX_JOYSTICK_AXES)
383- continue ;
416+ for (int i = 0 ; i < (int )[axes_elems count ]; i++) {
417+ IOHIDElementRef elem = [(NSValue *)axes_elems[i] pointerValue ];
418+ int usage = IOHIDElementGetUsage (elem);
419+ long min = IOHIDElementGetLogicalMin (elem);
420+ long max = IOHIDElementGetLogicalMax (elem);
421+ if (num_axes >= _AL_MAX_JOYSTICK_AXES)
422+ continue ;
384423
385- HAT_MAPPING *map = &joy->hats [num_hats];
386- map->min = min;
387- map->max = max;
388- map->elem = elem;
389- output = _al_get_joystick_output (&mapping->hat_map , 2 * num_hats);
390- if (output) {
391- map->x_output = *output;
392- num_hats_mapped++;
393- }
394- output = _al_get_joystick_output (&mapping->hat_map , 2 * num_hats + 1 );
395- if (output) {
396- map->y_output = *output;
397- num_hats_mapped++;
398- }
399- num_hats++;
400- }
401- else {
402- if (num_axes >= _AL_MAX_JOYSTICK_AXES)
403- continue ;
424+ AXIS_MAPPING *map = &joy->axes [num_axes];
425+ map->min = min;
426+ map->max = max;
427+ map->elem = elem;
428+ output = _al_get_joystick_output (&mapping->axis_map , num_axes);
429+ if (output) {
430+ map->output = *output;
431+ num_axes_mapped++;
432+ }
433+ num_axes++;
434+ }
404435
405- AXIS_MAPPING *map = &joy->axes [num_axes];
406- map->min = min;
407- map->max = max;
408- map->elem = elem;
409- output = _al_get_joystick_output (&mapping->axis_map , num_axes);
410- if (output) {
411- map->output = *output;
412- num_axes_mapped++;
413- }
414- num_axes++;
415- }
436+ for (int i = 0 ; i < (int )[hats_elems count ]; i++) {
437+ IOHIDElementRef elem = [(NSValue *)hats_elems[i] pointerValue ];
438+ long min = IOHIDElementGetLogicalMin (elem);
439+ long max = IOHIDElementGetLogicalMax (elem);
440+ if (num_hats >= _AL_MAX_JOYSTICK_AXES)
441+ continue ;
442+
443+ HAT_MAPPING *map = &joy->hats [num_hats];
444+ map->min = min;
445+ map->max = max;
446+ map->elem = elem;
447+ output = _al_get_joystick_output (&mapping->hat_map , 2 * num_hats);
448+ if (output) {
449+ map->x_output = *output;
450+ num_hats_mapped++;
416451 }
452+ output = _al_get_joystick_output (&mapping->hat_map , 2 * num_hats + 1 );
453+ if (output) {
454+ map->y_output = *output;
455+ num_hats_mapped++;
456+ }
457+ num_hats++;
417458 }
459+
418460 if (num_axes_mapped != (int )_al_vector_size (&mapping->axis_map )) {
419461 ALLEGRO_ERROR (" Could not use mapping, some axes are not mapped.\n " );
420462 return false ;
0 commit comments