mirror of https://github.com/encounter/SDL.git
Fixed bug 4286 - Joystick subsystem causes "not responding" when app is in the background
Added a hint to control whether a separate thread should be used for joystick events. This is off by default because dispatching messages in other threads appears to cause problems on some versions of Windows.
This commit is contained in:
parent
bca9decbda
commit
13a4caf1d7
|
@ -708,6 +708,17 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define SDL_HINT_JOYSTICK_RAWINPUT "SDL_JOYSTICK_RAWINPUT"
|
#define SDL_HINT_JOYSTICK_RAWINPUT "SDL_JOYSTICK_RAWINPUT"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief A variable controlling whether a separate thread should be used
|
||||||
|
* for handling joystick detection and raw input messages on Windows
|
||||||
|
*
|
||||||
|
* This variable can be set to the following values:
|
||||||
|
* "0" - A separate thread is not used (the default)
|
||||||
|
* "1" - A separate thread is used for handling raw input messages
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define SDL_HINT_JOYSTICK_THREAD "SDL_JOYSTICK_THREAD"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A variable controlling whether Linux joysticks adhere their HID-defined deadzones or return unfiltered values.
|
* \brief A variable controlling whether Linux joysticks adhere their HID-defined deadzones or return unfiltered values.
|
||||||
* This is useful for Wine which implements its own deadzone handler if requested by games, also it enables xinput
|
* This is useful for Wine which implements its own deadzone handler if requested by games, also it enables xinput
|
||||||
|
|
|
@ -705,8 +705,7 @@ LINUX_JoystickInit(void)
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_INPUT,
|
SDL_LogWarn(SDL_LOG_CATEGORY_INPUT,
|
||||||
"Unable to initialize inotify, falling back to polling: %s",
|
"Unable to initialize inotify, falling back to polling: %s",
|
||||||
strerror (errno));
|
strerror (errno));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
/* We need to watch for attribute changes in addition to
|
/* We need to watch for attribute changes in addition to
|
||||||
* creation, because when a device is first created, it has
|
* creation, because when a device is first created, it has
|
||||||
* permissions that we can't read. When udev chmods it to
|
* permissions that we can't read. When udev chmods it to
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
#include "SDL_error.h"
|
#include "SDL_error.h"
|
||||||
#include "SDL_events.h"
|
#include "SDL_events.h"
|
||||||
|
#include "SDL_hints.h"
|
||||||
#include "SDL_timer.h"
|
#include "SDL_timer.h"
|
||||||
#include "SDL_mutex.h"
|
#include "SDL_mutex.h"
|
||||||
#include "SDL_joystick.h"
|
#include "SDL_joystick.h"
|
||||||
|
@ -59,11 +60,12 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* local variables */
|
/* local variables */
|
||||||
|
static SDL_bool s_bJoystickThread = SDL_FALSE;
|
||||||
static SDL_bool s_bDeviceAdded = SDL_FALSE;
|
static SDL_bool s_bDeviceAdded = SDL_FALSE;
|
||||||
static SDL_bool s_bDeviceRemoved = SDL_FALSE;
|
static SDL_bool s_bDeviceRemoved = SDL_FALSE;
|
||||||
static SDL_cond *s_condJoystickThread = NULL;
|
static SDL_cond *s_condJoystickThread = NULL;
|
||||||
static SDL_mutex *s_mutexJoyStickEnum = 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;
|
static SDL_bool s_bJoystickThreadQuit = SDL_FALSE;
|
||||||
|
|
||||||
JoyStick_DeviceData *SYS_Joystick; /* array to hold joystick ID values */
|
JoyStick_DeviceData *SYS_Joystick; /* array to hold joystick ID values */
|
||||||
|
@ -227,18 +229,18 @@ SDL_WaitForDeviceNotification(SDL_DeviceNotificationData *data, SDL_mutex *mutex
|
||||||
|
|
||||||
#endif /* __WINRT__ */
|
#endif /* __WINRT__ */
|
||||||
|
|
||||||
|
static SDL_DeviceNotificationData s_notification_data;
|
||||||
|
|
||||||
/* Function/thread to scan the system for joysticks. */
|
/* Function/thread to scan the system for joysticks. */
|
||||||
static int
|
static int
|
||||||
SDL_JoystickThread(void *_data)
|
SDL_JoystickThread(void *_data)
|
||||||
{
|
{
|
||||||
SDL_DeviceNotificationData notification_data;
|
|
||||||
|
|
||||||
#if SDL_JOYSTICK_XINPUT
|
#if SDL_JOYSTICK_XINPUT
|
||||||
SDL_bool bOpenedXInputDevices[XUSER_MAX_COUNT];
|
SDL_bool bOpenedXInputDevices[XUSER_MAX_COUNT];
|
||||||
SDL_zeroa(bOpenedXInputDevices);
|
SDL_zeroa(bOpenedXInputDevices);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (SDL_CreateDeviceNotification(¬ification_data) < 0) {
|
if (SDL_CreateDeviceNotification(&s_notification_data) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +248,7 @@ SDL_JoystickThread(void *_data)
|
||||||
while (s_bJoystickThreadQuit == SDL_FALSE) {
|
while (s_bJoystickThreadQuit == SDL_FALSE) {
|
||||||
SDL_bool bXInputChanged = SDL_FALSE;
|
SDL_bool bXInputChanged = SDL_FALSE;
|
||||||
|
|
||||||
if (SDL_WaitForDeviceNotification(¬ification_data, s_mutexJoyStickEnum) == SDL_FALSE) {
|
if (SDL_WaitForDeviceNotification(&s_notification_data, s_mutexJoyStickEnum) == SDL_FALSE) {
|
||||||
#if SDL_JOYSTICK_XINPUT
|
#if SDL_JOYSTICK_XINPUT
|
||||||
/* WM_DEVICECHANGE not working, poll for new XINPUT controllers */
|
/* WM_DEVICECHANGE not working, poll for new XINPUT controllers */
|
||||||
SDL_CondWaitTimeout(s_condJoystickThread, s_mutexJoyStickEnum, 1000);
|
SDL_CondWaitTimeout(s_condJoystickThread, s_mutexJoyStickEnum, 1000);
|
||||||
|
@ -277,11 +279,58 @@ SDL_JoystickThread(void *_data)
|
||||||
}
|
}
|
||||||
SDL_UnlockMutex(s_mutexJoyStickEnum);
|
SDL_UnlockMutex(s_mutexJoyStickEnum);
|
||||||
|
|
||||||
SDL_CleanupDeviceNotification(¬ification_data);
|
SDL_CleanupDeviceNotification(&s_notification_data);
|
||||||
|
|
||||||
return 1;
|
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)
|
void WINDOWS_AddJoystickDevice(JoyStick_DeviceData *device)
|
||||||
{
|
{
|
||||||
device->send_add_event = SDL_TRUE;
|
device->send_add_event = SDL_TRUE;
|
||||||
|
@ -312,16 +361,19 @@ WINDOWS_JoystickInit(void)
|
||||||
return -1;
|
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_bDeviceAdded = SDL_TRUE; /* force a scan of the system for joysticks this first time */
|
||||||
|
|
||||||
WINDOWS_JoystickDetect();
|
WINDOWS_JoystickDetect();
|
||||||
|
|
||||||
if (!s_threadJoystick) {
|
s_bJoystickThread = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_THREAD, SDL_TRUE);
|
||||||
/* spin up the thread to detect hotplug of devices */
|
if (s_bJoystickThread) {
|
||||||
s_bJoystickThreadQuit = SDL_FALSE;
|
if (SDL_StartJoystickThread() < 0) {
|
||||||
s_threadJoystick = SDL_CreateThreadInternal(SDL_JoystickThread, "SDL_joystick", 64 * 1024, NULL);
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (SDL_CreateDeviceNotification(&s_notification_data) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -351,7 +403,9 @@ WINDOWS_JoystickDetect(void)
|
||||||
return; /* thread hasn't signaled, nothing to do right now. */
|
return; /* thread hasn't signaled, nothing to do right now. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s_mutexJoyStickEnum) {
|
||||||
SDL_LockMutex(s_mutexJoyStickEnum);
|
SDL_LockMutex(s_mutexJoyStickEnum);
|
||||||
|
}
|
||||||
|
|
||||||
s_bDeviceAdded = SDL_FALSE;
|
s_bDeviceAdded = SDL_FALSE;
|
||||||
s_bDeviceRemoved = SDL_FALSE;
|
s_bDeviceRemoved = SDL_FALSE;
|
||||||
|
@ -365,7 +419,9 @@ WINDOWS_JoystickDetect(void)
|
||||||
/* Look for XInput devices. Do this last, so they're first in the final list. */
|
/* Look for XInput devices. Do this last, so they're first in the final list. */
|
||||||
SDL_XINPUT_JoystickDetect(&pCurList);
|
SDL_XINPUT_JoystickDetect(&pCurList);
|
||||||
|
|
||||||
|
if (s_mutexJoyStickEnum) {
|
||||||
SDL_UnlockMutex(s_mutexJoyStickEnum);
|
SDL_UnlockMutex(s_mutexJoyStickEnum);
|
||||||
|
}
|
||||||
|
|
||||||
while (pCurList) {
|
while (pCurList) {
|
||||||
JoyStick_DeviceData *pListNext = NULL;
|
JoyStick_DeviceData *pListNext = NULL;
|
||||||
|
@ -577,21 +633,10 @@ WINDOWS_JoystickQuit(void)
|
||||||
}
|
}
|
||||||
SYS_Joystick = NULL;
|
SYS_Joystick = NULL;
|
||||||
|
|
||||||
if (s_threadJoystick) {
|
if (s_bJoystickThread) {
|
||||||
SDL_LockMutex(s_mutexJoyStickEnum);
|
SDL_StopJoystickThread();
|
||||||
s_bJoystickThreadQuit = SDL_TRUE;
|
} else {
|
||||||
SDL_CondBroadcast(s_condJoystickThread); /* signal the joystick thread to quit */
|
SDL_CleanupDeviceNotification(&s_notification_data);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_DINPUT_JoystickQuit();
|
SDL_DINPUT_JoystickQuit();
|
||||||
|
|
Loading…
Reference in New Issue