Skip to content

SDL2 on macOS detects joysticks only with SDL2_INIT_VIDEO #12886

@EliaCereda

Description

@EliaCereda

It appears that SDL can detect joysticks connected at startup only if SDL2_INIT_VIDEO is also initialised.

When only SDL_INIT_JOYSTICK is initialised, for some reason gamepads are detected correctly if they're hot plugged while the program is running (e.g. inside the while(true) loop below), but not if they are already connected at startup.

SDL version: 2.32.54
macOS version: 14.7.4 arm64

Reproduction code (from https://github.com/ros-drivers/joystick_drivers/blob/ros2/joy/src/joy_enumerate_devices.cpp)

// On Windows, we have to be sure that SDL doesn't generate its own main.
#define SDL_MAIN_HANDLED
#include <SDL.h>

#include <cstdio>
#include <stdexcept>

int main()
{
  // SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK
  if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC ) < 0) {
    fprintf(stderr, "SDL could not be initialized: %s\n", SDL_GetError());
    return 1;
  }

  fprintf(stdout, "SDL initialized. Joystick subsystem version: %d.%d.%d\n", 
    SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL);

  while (true) {
    SDL_PumpEvents();

    fprintf(
      stdout,
      "ID : GUID                             : GamePad : Mapped : Joystick Device Name\n");
    fprintf(
      stdout,
      "-------------------------------------------------------------------------------\n");
    for (int i = 0; i < SDL_NumJoysticks(); ++i) {
      SDL_JoystickGUID joystick_guid;
      const char * joystick_name = "Unknown";
      const char * has_mapping_string = "false";
      const char * is_gamepad = "false";

      if (SDL_IsGameController(i)) {
        SDL_GameController * controller = SDL_GameControllerOpen(i);
        joystick_guid = SDL_JoystickGetGUID(SDL_GameControllerGetJoystick(controller));
        joystick_name = SDL_GameControllerName(controller);
        if (nullptr != SDL_GameControllerMapping(controller)) {
          has_mapping_string = "true";
        }
        is_gamepad = "true";

      } else {
        joystick_name = SDL_JoystickNameForIndex(i);
        joystick_guid = SDL_JoystickGetDeviceGUID(i);
      }

      char guid_string[33];
      SDL_JoystickGetGUIDString(joystick_guid, guid_string, sizeof(guid_string));

      fprintf(
        stdout, "%2d : %32s : %7s : %6s : %s\n", i, guid_string, is_gamepad, has_mapping_string,
        joystick_name);
    }

    SDL_Delay(1000);
  }

  SDL_Quit();

  return 0;
}

Output with SDL2_INIT_VIDEO:

SDL initialized. Joystick subsystem version: 2.32.54
ID : GUID                             : GamePad : Mapped : Joystick Device Name
-------------------------------------------------------------------------------
ID : GUID                             : GamePad : Mapped : Joystick Device Name
-------------------------------------------------------------------------------
ID : GUID                             : GamePad : Mapped : Joystick Device Name
-------------------------------------------------------------------------------
 0 : 05005d8eac0500000400000065706d04 :    true :   true : Logitech Cordless RumblePad 2
ID : GUID                             : GamePad : Mapped : Joystick Device Name
-------------------------------------------------------------------------------
 0 : 05005d8eac0500000400000065706d04 :    true :   true : Logitech Cordless RumblePad 2
ID : GUID                             : GamePad : Mapped : Joystick Device Name
-------------------------------------------------------------------------------
 0 : 05005d8eac0500000400000065706d04 :    true :   true : Logitech Cordless RumblePad 2
ID : GUID                             : GamePad : Mapped : Joystick Device Name
-------------------------------------------------------------------------------
 0 : 05005d8eac0500000400000065706d04 :    true :   true : Logitech Cordless RumblePad 2
ID : GUID                             : GamePad : Mapped : Joystick Device Name
-------------------------------------------------------------------------------
 0 : 05005d8eac0500000400000065706d04 :    true :   true : Logitech Cordless RumblePad 2
ID : GUID                             : GamePad : Mapped : Joystick Device Name
-------------------------------------------------------------------------------
 0 : 05005d8eac0500000400000065706d04 :    true :   true : Logitech Cordless RumblePad 2
ID : GUID                             : GamePad : Mapped : Joystick Device Name
-------------------------------------------------------------------------------
 0 : 05005d8eac0500000400000065706d04 :    true :   true : Logitech Cordless RumblePad 2

Output without SDL2_INIT_VIDEO:

SDL initialized. Joystick subsystem version: 2.32.54
ID : GUID                             : GamePad : Mapped : Joystick Device Name
-------------------------------------------------------------------------------
ID : GUID                             : GamePad : Mapped : Joystick Device Name
-------------------------------------------------------------------------------
ID : GUID                             : GamePad : Mapped : Joystick Device Name
-------------------------------------------------------------------------------
ID : GUID                             : GamePad : Mapped : Joystick Device Name
-------------------------------------------------------------------------------
ID : GUID                             : GamePad : Mapped : Joystick Device Name
-------------------------------------------------------------------------------
ID : GUID                             : GamePad : Mapped : Joystick Device Name
-------------------------------------------------------------------------------
ID : GUID                             : GamePad : Mapped : Joystick Device Name
-------------------------------------------------------------------------------
[... never detects it ...]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions