Skip to content

Commit

Permalink
Don't use raw input while Remote Desktop is active
Browse files Browse the repository at this point in the history
Raw input will not send game controller events while Remote Desktop is active, so dynamically switch between XInput and raw input when Remote Desktop state changes.

Fixes libsdl-org#7759
  • Loading branch information
slouken committed Jun 2, 2023
1 parent a5a1844 commit 767507f
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 36 deletions.
4 changes: 2 additions & 2 deletions src/joystick/windows/SDL_dinputjoystick.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ static int SetDIerror(const char *function, HRESULT code)

static SDL_bool SDL_IsXInputDevice(Uint16 vendor_id, Uint16 product_id, const char *hidPath)
{
#ifdef SDL_JOYSTICK_XINPUT
#if defined(SDL_JOYSTICK_XINPUT) || defined(SDL_JOYSTICK_RAWINPUT)
SDL_GamepadType type;

/* XInput and RawInput backends will pick up XInput-compatible devices */
Expand All @@ -262,7 +262,7 @@ static SDL_bool SDL_IsXInputDevice(Uint16 vendor_id, Uint16 product_id, const ch
(vendor_id == USB_VENDOR_VALVE && product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD)) {
return SDL_TRUE;
}
#endif /* SDL_JOYSTICK_XINPUT */
#endif /* SDL_JOYSTICK_XINPUT || SDL_JOYSTICK_RAWINPUT */

return SDL_FALSE;
}
Expand Down
70 changes: 49 additions & 21 deletions src/joystick/windows/SDL_rawinputjoystick.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,11 @@ typedef struct WindowsGamingInputGamepadState WindowsGamingInputGamepadState;
#define GIDC_REMOVAL 2
#endif

extern void WINDOWS_RAWINPUTEnabledChanged(void);
extern void WINDOWS_JoystickDetect(void);

static SDL_bool SDL_RAWINPUT_inited = SDL_FALSE;
static SDL_bool SDL_RAWINPUT_remote_desktop = SDL_FALSE;
static int SDL_RAWINPUT_numjoysticks = 0;

static void RAWINPUT_JoystickClose(SDL_Joystick *joystick);
Expand Down Expand Up @@ -838,10 +842,36 @@ static void RAWINPUT_DelDevice(SDL_RAWINPUT_Device *device, SDL_bool send_event)
}
}

static int RAWINPUT_JoystickInit(void)
static void RAWINPUT_DetectDevices(void)
{
UINT device_count = 0;

if ((GetRawInputDeviceList(NULL, &device_count, sizeof(RAWINPUTDEVICELIST)) != -1) && device_count > 0) {
PRAWINPUTDEVICELIST devices = NULL;
UINT i;

devices = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * device_count);
if (devices) {
if (GetRawInputDeviceList(devices, &device_count, sizeof(RAWINPUTDEVICELIST)) != -1) {
for (i = 0; i < device_count; ++i) {
RAWINPUT_AddDevice(devices[i].hDevice);
}
}
SDL_free(devices);
}
}
}

static void RAWINPUT_RemoveDevices(void)
{
while (SDL_RAWINPUT_devices) {
RAWINPUT_DelDevice(SDL_RAWINPUT_devices, SDL_FALSE);
}
SDL_assert(SDL_RAWINPUT_numjoysticks == 0);
}

static int RAWINPUT_JoystickInit(void)
{
SDL_assert(!SDL_RAWINPUT_inited);

if (!WIN_IsWindowsVistaOrGreater()) {
Expand All @@ -859,20 +889,7 @@ static int RAWINPUT_JoystickInit(void)

SDL_RAWINPUT_inited = SDL_TRUE;

if ((GetRawInputDeviceList(NULL, &device_count, sizeof(RAWINPUTDEVICELIST)) != -1) && device_count > 0) {
PRAWINPUTDEVICELIST devices = NULL;
UINT i;

devices = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * device_count);
if (devices) {
if (GetRawInputDeviceList(devices, &device_count, sizeof(RAWINPUTDEVICELIST)) != -1) {
for (i = 0; i < device_count; ++i) {
RAWINPUT_AddDevice(devices[i].hDevice);
}
}
SDL_free(devices);
}
}
RAWINPUT_DetectDevices();

return 0;
}
Expand All @@ -884,7 +901,7 @@ static int RAWINPUT_JoystickGetCount(void)

SDL_bool RAWINPUT_IsEnabled()
{
return SDL_RAWINPUT_inited;
return SDL_RAWINPUT_inited && !SDL_RAWINPUT_remote_desktop;
}

SDL_bool RAWINPUT_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
Expand Down Expand Up @@ -986,6 +1003,21 @@ static void RAWINPUT_PostUpdate(void)

static void RAWINPUT_JoystickDetect(void)
{
SDL_bool remote_desktop = GetSystemMetrics(SM_REMOTESESSION) ? SDL_TRUE : SDL_FALSE;

if (remote_desktop != SDL_RAWINPUT_remote_desktop) {
SDL_RAWINPUT_remote_desktop = remote_desktop;

WINDOWS_RAWINPUTEnabledChanged();

if (remote_desktop) {
RAWINPUT_RemoveDevices();
WINDOWS_JoystickDetect();
} else {
WINDOWS_JoystickDetect();
RAWINPUT_DetectDevices();
}
}
RAWINPUT_PostUpdate();
}

Expand Down Expand Up @@ -1993,14 +2025,10 @@ static void RAWINPUT_JoystickQuit(void)
return;
}

while (SDL_RAWINPUT_devices) {
RAWINPUT_DelDevice(SDL_RAWINPUT_devices, SDL_FALSE);
}
RAWINPUT_RemoveDevices();

WIN_UnloadHIDDLL();

SDL_RAWINPUT_numjoysticks = 0;

SDL_RAWINPUT_inited = SDL_FALSE;
}

Expand Down
4 changes: 2 additions & 2 deletions src/joystick/windows/SDL_windows_gaming_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ extern SDL_bool SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16

static SDL_bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product)
{
#ifdef SDL_JOYSTICK_XINPUT
#if defined(SDL_JOYSTICK_XINPUT) || defined(SDL_JOYSTICK_RAWINPUT)
PRAWINPUTDEVICELIST raw_devices = NULL;
UINT i, raw_device_count = 0;
LONG vidpid = MAKELONG(vendor, product);
Expand Down Expand Up @@ -202,7 +202,7 @@ static SDL_bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product)
}

SDL_free(raw_devices);
#endif /* SDL_JOYSTICK_XINPUT */
#endif /* SDL_JOYSTICK_XINPUT || SDL_JOYSTICK_RAWINPUT */

return SDL_FALSE;
}
Expand Down
13 changes: 9 additions & 4 deletions src/joystick/windows/SDL_windowsjoystick.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ static CM_Register_NotificationFunc CM_Register_Notification;
static CM_Unregister_NotificationFunc CM_Unregister_Notification;
static HCMNOTIFICATION s_DeviceNotificationFuncHandle;

void WINDOWS_RAWINPUTEnabledChanged(void)
{
s_bWindowsDeviceChanged = SDL_TRUE;
}

static DWORD CALLBACK SDL_DeviceNotificationFunc(HCMNOTIFICATION hNotify, PVOID context, CM_NOTIFY_ACTION action, PCM_NOTIFY_EVENT_DATA eventData, DWORD event_data_size)
{
if (action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL ||
Expand Down Expand Up @@ -453,8 +458,8 @@ void WINDOWS_AddJoystickDevice(JoyStick_DeviceData *device)
SYS_Joystick = device;
}

static void WINDOWS_JoystickDetect(void);
static void WINDOWS_JoystickQuit(void);
void WINDOWS_JoystickDetect(void);
void WINDOWS_JoystickQuit(void);

/* Function to scan the system for joysticks.
* Joystick 0 should be the system default joystick.
Expand Down Expand Up @@ -515,7 +520,7 @@ static int WINDOWS_JoystickGetCount(void)
}

/* detect any new joysticks being inserted into the system */
static void WINDOWS_JoystickDetect(void)
void WINDOWS_JoystickDetect(void)
{
JoyStick_DeviceData *pCurList = NULL;

Expand Down Expand Up @@ -744,7 +749,7 @@ static void WINDOWS_JoystickClose(SDL_Joystick *joystick)
}

/* Function to perform any system-specific joystick related cleanup */
static void WINDOWS_JoystickQuit(void)
void WINDOWS_JoystickQuit(void)
{
JoyStick_DeviceData *device = SYS_Joystick;

Expand Down
14 changes: 7 additions & 7 deletions src/joystick/windows/SDL_xinputjoystick.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,6 @@ int SDL_XINPUT_JoystickInit(void)
{
s_bXInputEnabled = SDL_GetHintBoolean(SDL_HINT_XINPUT_ENABLED, SDL_TRUE);

#ifdef SDL_JOYSTICK_RAWINPUT
if (RAWINPUT_IsEnabled()) {
/* The raw input driver handles more than 4 controllers, so prefer that when available */
s_bXInputEnabled = SDL_FALSE;
}
#endif

if (s_bXInputEnabled && WIN_LoadXInputDLL() < 0) {
s_bXInputEnabled = SDL_FALSE; /* oh well. */
}
Expand Down Expand Up @@ -327,6 +320,13 @@ void SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
return;
}

#ifdef SDL_JOYSTICK_RAWINPUT
if (RAWINPUT_IsEnabled()) {
/* The raw input driver handles more than 4 controllers, so prefer that when available */
return;
}
#endif

/* iterate in reverse, so these are in the final list in ascending numeric order. */
for (iuserid = XUSER_MAX_COUNT - 1; iuserid >= 0; iuserid--) {
const Uint8 userid = (Uint8)iuserid;
Expand Down

0 comments on commit 767507f

Please sign in to comment.