Mac and Linux SDL2 binary snapshots
Edward Rudd
2021-06-15 dec7875a6e23212021e4d9080330a42832dfe02a
source/src/joystick/windows/SDL_windowsjoystick.c
@@ -33,8 +33,8 @@
 * let it return 0 events. */
#include "SDL_error.h"
#include "SDL_assert.h"
#include "SDL_events.h"
#include "SDL_hints.h"
#include "SDL_timer.h"
#include "SDL_mutex.h"
#include "SDL_joystick.h"
@@ -49,6 +49,7 @@
#include "SDL_windowsjoystick_c.h"
#include "SDL_dinputjoystick_c.h"
#include "SDL_xinputjoystick_c.h"
#include "SDL_rawinputjoystick_c.h"
#include "../../haptic/windows/SDL_dinputhaptic_c.h"    /* For haptic hot plugging */
#include "../../haptic/windows/SDL_xinputhaptic_c.h"    /* For haptic hot plugging */
@@ -59,16 +60,14 @@
#endif
/* local variables */
static SDL_bool s_bDeviceAdded = SDL_FALSE;
static SDL_bool s_bDeviceRemoved = SDL_FALSE;
static SDL_bool s_bJoystickThread = SDL_FALSE;
static SDL_bool s_bWindowsDeviceChanged = SDL_FALSE;
static SDL_cond *s_condJoystickThread = NULL;
static SDL_mutex *s_mutexJoyStickEnum = NULL;
static SDL_Thread *s_threadJoystick = NULL;
static SDL_Thread *s_joystickThread = NULL;
static SDL_bool s_bJoystickThreadQuit = SDL_FALSE;
JoyStick_DeviceData *SYS_Joystick;    /* array to hold joystick ID values */
static SDL_bool s_bWindowsDeviceChanged = SDL_FALSE;
#ifdef __WINRT__
@@ -109,9 +108,9 @@
/* windowproc for our joystick detect thread message only window, to detect any USB device addition/removal */
static LRESULT CALLBACK
SDL_PrivateJoystickDetectProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
SDL_PrivateJoystickDetectProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (message) {
    switch (msg) {
    case WM_DEVICECHANGE:
        switch (wParam) {
        case DBT_DEVICEARRIVAL:
@@ -125,17 +124,29 @@
        }
        return 0;
    case WM_TIMER:
        KillTimer(hwnd, wParam);
        s_bWindowsDeviceChanged = SDL_TRUE;
        return 0;
        if (wParam == IDT_SDL_DEVICE_CHANGE_TIMER_1 ||
            wParam == IDT_SDL_DEVICE_CHANGE_TIMER_2) {
            KillTimer(hwnd, wParam);
            s_bWindowsDeviceChanged = SDL_TRUE;
            return 0;
        }
        break;
    }
    return DefWindowProc (hwnd, message, wParam, lParam);
#if SDL_JOYSTICK_RAWINPUT
    return CallWindowProc(RAWINPUT_WindowProc, hwnd, msg, wParam, lParam);
#else
    return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
#endif
}
static void
SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *data)
{
#if SDL_JOYSTICK_RAWINPUT
    RAWINPUT_UnregisterNotifications();
#endif
    if (data->hNotify)
        UnregisterDeviceNotification(data->hNotify);
@@ -188,6 +199,10 @@
        SDL_CleanupDeviceNotification(data);
        return -1;
    }
#if SDL_JOYSTICK_RAWINPUT
    RAWINPUT_RegisterNotifications(data->messageWindow);
#endif
    return 0;
}
@@ -215,26 +230,24 @@
#endif /* __WINRT__ */
static SDL_DeviceNotificationData s_notification_data;
/* Function/thread to scan the system for joysticks. */
static int
SDL_JoystickThread(void *_data)
{
    SDL_DeviceNotificationData notification_data;
#if SDL_JOYSTICK_XINPUT
    SDL_bool bOpenedXInputDevices[XUSER_MAX_COUNT];
    SDL_zeroa(bOpenedXInputDevices);
#endif
    if (SDL_CreateDeviceNotification(&notification_data) < 0) {
    if (SDL_CreateDeviceNotification(&s_notification_data) < 0) {
        return -1;
    }
    SDL_LockMutex(s_mutexJoyStickEnum);
    while (s_bJoystickThreadQuit == SDL_FALSE) {
        SDL_bool bXInputChanged = SDL_FALSE;
        if (SDL_WaitForDeviceNotification(&notification_data, s_mutexJoyStickEnum) == SDL_FALSE) {
        if (SDL_WaitForDeviceNotification(&s_notification_data, s_mutexJoyStickEnum) == SDL_FALSE) {
#if SDL_JOYSTICK_XINPUT
            /* WM_DEVICECHANGE not working, poll for new XINPUT controllers */
            SDL_CondWaitTimeout(s_condJoystickThread, s_mutexJoyStickEnum, 1000);
@@ -246,7 +259,7 @@
                    const DWORD result = XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities);
                    const SDL_bool available = (result == ERROR_SUCCESS);
                    if (bOpenedXInputDevices[userId] != available) {
                        bXInputChanged = SDL_TRUE;
                        s_bWindowsDeviceChanged = SDL_TRUE;
                        bOpenedXInputDevices[userId] = available;
                    }
                }
@@ -256,18 +269,59 @@
            break;
#endif /* SDL_JOYSTICK_XINPUT */
        }
        if (s_bWindowsDeviceChanged || bXInputChanged) {
            s_bDeviceRemoved = SDL_TRUE;
            s_bDeviceAdded = SDL_TRUE;
            s_bWindowsDeviceChanged = SDL_FALSE;
        }
    }
    SDL_UnlockMutex(s_mutexJoyStickEnum);
    SDL_CleanupDeviceNotification(&notification_data);
    SDL_CleanupDeviceNotification(&s_notification_data);
    return 1;
}
/* spin up the thread to detect hotplug of devices */
static int
SDL_StartJoystickThread(void)
{
    s_mutexJoyStickEnum = SDL_CreateMutex();
    if (!s_mutexJoyStickEnum) {
        return -1;
    }
    s_condJoystickThread = SDL_CreateCond();
    if (!s_condJoystickThread) {
        return -1;
    }
    s_bJoystickThreadQuit = SDL_FALSE;
    s_joystickThread = SDL_CreateThreadInternal(SDL_JoystickThread, "SDL_joystick", 64 * 1024, NULL);
    if (!s_joystickThread) {
        return -1;
    }
    return 0;
}
static void
SDL_StopJoystickThread(void)
{
    if (!s_joystickThread) {
        return;
    }
    SDL_LockMutex(s_mutexJoyStickEnum);
    s_bJoystickThreadQuit = SDL_TRUE;
    SDL_CondBroadcast(s_condJoystickThread); /* signal the joystick thread to quit */
    SDL_UnlockMutex(s_mutexJoyStickEnum);
#ifndef __WINRT__
    PostThreadMessage(SDL_GetThreadID(s_joystickThread), WM_QUIT, 0, 0);
#endif
    SDL_WaitThread(s_joystickThread, NULL); /* wait for it to bugger off */
    SDL_DestroyCond(s_condJoystickThread);
    s_condJoystickThread = NULL;
    SDL_DestroyMutex(s_mutexJoyStickEnum);
    s_mutexJoyStickEnum = NULL;
    s_joystickThread = NULL;
}
void WINDOWS_AddJoystickDevice(JoyStick_DeviceData *device)
@@ -276,8 +330,6 @@
    device->nInstanceID = SDL_GetNextJoystickInstanceID();
    device->pNext = SYS_Joystick;
    SYS_Joystick = device;
    s_bDeviceAdded = SDL_TRUE;
}
static void WINDOWS_JoystickDetect(void);
@@ -300,16 +352,19 @@
        return -1;
    }
    s_mutexJoyStickEnum = SDL_CreateMutex();
    s_condJoystickThread = SDL_CreateCond();
    s_bDeviceAdded = SDL_TRUE; /* force a scan of the system for joysticks this first time */
    s_bWindowsDeviceChanged = SDL_TRUE; /* force a scan of the system for joysticks this first time */
    WINDOWS_JoystickDetect();
    if (!s_threadJoystick) {
        /* spin up the thread to detect hotplug of devices */
        s_bJoystickThreadQuit = SDL_FALSE;
        s_threadJoystick = SDL_CreateThreadInternal(SDL_JoystickThread, "SDL_joystick", 64 * 1024, NULL);
    s_bJoystickThread = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_THREAD, SDL_FALSE);
    if (s_bJoystickThread) {
        if (SDL_StartJoystickThread() < 0) {
            return -1;
        }
    } else {
        if (SDL_CreateDeviceNotification(&s_notification_data) < 0) {
            return -1;
        }
    }
    return 0;
}
@@ -332,17 +387,19 @@
static void
WINDOWS_JoystickDetect(void)
{
    int device_index = 0;
    JoyStick_DeviceData *pCurList = NULL;
    /* only enum the devices if the joystick thread told us something changed */
    if (!s_bDeviceAdded && !s_bDeviceRemoved) {
    if (!s_bWindowsDeviceChanged) {
        return;  /* thread hasn't signaled, nothing to do right now. */
    }
    SDL_LockMutex(s_mutexJoyStickEnum);
    if (s_mutexJoyStickEnum) {
        SDL_LockMutex(s_mutexJoyStickEnum);
    }
    s_bDeviceAdded = SDL_FALSE;
    s_bDeviceRemoved = SDL_FALSE;
    s_bWindowsDeviceChanged = SDL_FALSE;
    pCurList = SYS_Joystick;
    SYS_Joystick = NULL;
@@ -353,15 +410,21 @@
    /* Look for XInput devices. Do this last, so they're first in the final list. */
    SDL_XINPUT_JoystickDetect(&pCurList);
    SDL_UnlockMutex(s_mutexJoyStickEnum);
    if (s_mutexJoyStickEnum) {
        SDL_UnlockMutex(s_mutexJoyStickEnum);
    }
    while (pCurList) {
        JoyStick_DeviceData *pListNext = NULL;
        if (pCurList->bXInputDevice) {
#if SDL_HAPTIC_XINPUT
            SDL_XINPUT_MaybeRemoveDevice(pCurList->XInputUserId);
#endif
        } else {
#if SDL_HAPTIC_DINPUT
            SDL_DINPUT_MaybeRemoveDevice(&pCurList->dxdevice);
#endif
        }
        SDL_PrivateJoystickRemoved(pCurList->nInstanceID);
@@ -372,25 +435,21 @@
        pCurList = pListNext;
    }
    if (s_bDeviceAdded) {
        JoyStick_DeviceData *pNewJoystick;
        int device_index = 0;
        s_bDeviceAdded = SDL_FALSE;
        pNewJoystick = SYS_Joystick;
        while (pNewJoystick) {
            if (pNewJoystick->send_add_event) {
                if (pNewJoystick->bXInputDevice) {
                    SDL_XINPUT_MaybeAddDevice(pNewJoystick->XInputUserId);
                } else {
                    SDL_DINPUT_MaybeAddDevice(&pNewJoystick->dxdevice);
                }
                SDL_PrivateJoystickAdded(pNewJoystick->nInstanceID);
                pNewJoystick->send_add_event = SDL_FALSE;
    for (device_index = 0, pCurList = SYS_Joystick; pCurList; ++device_index, pCurList = pCurList->pNext) {
        if (pCurList->send_add_event) {
            if (pCurList->bXInputDevice) {
#if SDL_HAPTIC_XINPUT
                SDL_XINPUT_MaybeAddDevice(pCurList->XInputUserId);
#endif
            } else {
#if SDL_HAPTIC_DINPUT
                SDL_DINPUT_MaybeAddDevice(&pCurList->dxdevice);
#endif
            }
            device_index++;
            pNewJoystick = pNewJoystick->pNext;
            SDL_PrivateJoystickAdded(pCurList->nInstanceID);
            pCurList->send_add_event = SDL_FALSE;
        }
    }
}
@@ -400,8 +459,9 @@
WINDOWS_JoystickGetDeviceName(int device_index)
{
    JoyStick_DeviceData *device = SYS_Joystick;
    int index;
    for (; device_index > 0; device_index--)
    for (index = device_index; index > 0; index--)
        device = device->pNext;
    return device->joystickname;
@@ -458,25 +518,26 @@
static int
WINDOWS_JoystickOpen(SDL_Joystick * joystick, int device_index)
{
    JoyStick_DeviceData *joystickdevice = SYS_Joystick;
    JoyStick_DeviceData *device = SYS_Joystick;
    int index;
    for (; device_index > 0; device_index--)
        joystickdevice = joystickdevice->pNext;
    for (index = device_index; index > 0; index--)
        device = device->pNext;
    /* allocate memory for system specific hardware data */
    joystick->instance_id = joystickdevice->nInstanceID;
    joystick->instance_id = device->nInstanceID;
    joystick->hwdata =
        (struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata));
    if (joystick->hwdata == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_zerop(joystick->hwdata);
    joystick->hwdata->guid = joystickdevice->guid;
    joystick->hwdata->guid = device->guid;
    if (joystickdevice->bXInputDevice) {
        return SDL_XINPUT_JoystickOpen(joystick, joystickdevice);
    if (device->bXInputDevice) {
        return SDL_XINPUT_JoystickOpen(joystick, device);
    } else {
        return SDL_DINPUT_JoystickOpen(joystick, joystickdevice);
        return SDL_DINPUT_JoystickOpen(joystick, device);
    }
}
@@ -488,6 +549,30 @@
    } else {
        return SDL_DINPUT_JoystickRumble(joystick, low_frequency_rumble, high_frequency_rumble);
    }
}
static int
WINDOWS_JoystickRumbleTriggers(SDL_Joystick * joystick, Uint16 left_rumble, Uint16 right_rumble)
{
    return SDL_Unsupported();
}
static SDL_bool
WINDOWS_JoystickHasLED(SDL_Joystick * joystick)
{
    return SDL_FALSE;
}
static int
WINDOWS_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
{
    return SDL_Unsupported();
}
static int
WINDOWS_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
{
    return SDL_Unsupported();
}
static void
@@ -531,28 +616,22 @@
    }
    SYS_Joystick = NULL;
    if (s_threadJoystick) {
        SDL_LockMutex(s_mutexJoyStickEnum);
        s_bJoystickThreadQuit = SDL_TRUE;
        SDL_CondBroadcast(s_condJoystickThread); /* signal the joystick thread to quit */
        SDL_UnlockMutex(s_mutexJoyStickEnum);
#ifndef __WINRT__
        PostThreadMessage(SDL_GetThreadID(s_threadJoystick), WM_QUIT, 0, 0);
#endif
        SDL_WaitThread(s_threadJoystick, NULL); /* wait for it to bugger off */
        SDL_DestroyMutex(s_mutexJoyStickEnum);
        SDL_DestroyCond(s_condJoystickThread);
        s_condJoystickThread= NULL;
        s_mutexJoyStickEnum = NULL;
        s_threadJoystick = NULL;
    if (s_bJoystickThread) {
        SDL_StopJoystickThread();
    } else {
        SDL_CleanupDeviceNotification(&s_notification_data);
    }
    SDL_DINPUT_JoystickQuit();
    SDL_XINPUT_JoystickQuit();
    s_bDeviceAdded = SDL_FALSE;
    s_bDeviceRemoved = SDL_FALSE;
    s_bWindowsDeviceChanged = SDL_FALSE;
}
static SDL_bool
WINDOWS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
{
    return SDL_FALSE;
}
SDL_JoystickDriver SDL_WINDOWS_JoystickDriver =
@@ -567,9 +646,14 @@
    WINDOWS_JoystickGetDeviceInstanceID,
    WINDOWS_JoystickOpen,
    WINDOWS_JoystickRumble,
    WINDOWS_JoystickRumbleTriggers,
    WINDOWS_JoystickHasLED,
    WINDOWS_JoystickSetLED,
    WINDOWS_JoystickSetSensorsEnabled,
    WINDOWS_JoystickUpdate,
    WINDOWS_JoystickClose,
    WINDOWS_JoystickQuit,
    WINDOWS_JoystickGetGamepadMapping
};
#endif /* SDL_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT */