Fix joystick device add events containing invalid device indexes
This can happen if the application has not yet processed SDL_JOYDEVICEADD when
the same joystick is removed. It may also happen if two joysticks are added
and the second joystick is removed before the first joystick's SDL_JOYDEVICEADD
has been processed by the application.
diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c
index 0069860..fe5a788 100644
--- a/src/joystick/SDL_gamecontroller.c
+++ b/src/joystick/SDL_gamecontroller.c
@@ -202,7 +202,7 @@
* to have the right value for which, because the number of controllers in
* the system is now one less.
*/
-static void UpdateEventsForDeviceRemoval()
+static void UpdateEventsForDeviceRemoval(int device_index)
{
int i, num_events;
SDL_Event *events;
@@ -220,7 +220,19 @@
num_events = SDL_PeepEvents(events, num_events, SDL_GETEVENT, SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEADDED);
for (i = 0; i < num_events; ++i) {
- --events[i].cdevice.which;
+ if (events[i].cdevice.which < device_index) {
+ /* No change for index values lower than the removed device */
+ }
+ else if (events[i].cdevice.which == device_index) {
+ /* Drop this event entirely */
+ SDL_memmove(&events[i], &events[i + 1], sizeof(*events) * (num_events - (i + 1)));
+ --i;
+ --num_events;
+ }
+ else {
+ /* Fix up the device index if greater than the removed device */
+ --events[i].cdevice.which;
+ }
}
SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);
@@ -427,6 +439,7 @@
case SDL_JOYDEVICEREMOVED:
{
SDL_GameController *controllerlist = SDL_gamecontrollers;
+ int device_index = 0;
while (controllerlist) {
if (controllerlist->joystick->instance_id == event->jdevice.which) {
SDL_Event deviceevent;
@@ -437,10 +450,11 @@
deviceevent.cdevice.which = event->jdevice.which;
SDL_PushEvent(&deviceevent);
- UpdateEventsForDeviceRemoval();
+ UpdateEventsForDeviceRemoval(device_index);
break;
}
controllerlist = controllerlist->next;
+ ++device_index;
}
}
break;
diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index 1ab7e0b..7ea93b4 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -1184,7 +1184,7 @@
* to have the right value for which, because the number of controllers in
* the system is now one less.
*/
-static void UpdateEventsForDeviceRemoval()
+static void UpdateEventsForDeviceRemoval(int device_index)
{
int i, num_events;
SDL_Event *events;
@@ -1202,7 +1202,19 @@
num_events = SDL_PeepEvents(events, num_events, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
for (i = 0; i < num_events; ++i) {
- --events[i].jdevice.which;
+ if (events[i].cdevice.which < device_index) {
+ /* No change for index values lower than the removed device */
+ }
+ else if (events[i].cdevice.which == device_index) {
+ /* Drop this event entirely */
+ SDL_memmove(&events[i], &events[i + 1], sizeof(*events) * (num_events - (i + 1)));
+ --num_events;
+ --i;
+ }
+ else {
+ /* Fix up the device index if greater than the removed device */
+ --events[i].cdevice.which;
+ }
}
SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);
@@ -1243,17 +1255,21 @@
{
SDL_Joystick *joystick = NULL;
int player_index;
+ int device_index;
#if !SDL_EVENTS_DISABLED
SDL_Event event;
#endif
/* Find this joystick... */
+ device_index = 0;
for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
if (joystick->instance_id == device_instance) {
SDL_PrivateJoystickForceRecentering(joystick);
joystick->attached = SDL_FALSE;
break;
}
+
+ ++device_index;
}
#if !SDL_EVENTS_DISABLED
@@ -1265,7 +1281,7 @@
SDL_PushEvent(&event);
}
- UpdateEventsForDeviceRemoval();
+ UpdateEventsForDeviceRemoval(device_index);
#endif /* !SDL_EVENTS_DISABLED */
SDL_LockJoysticks();