SDL: Removed SDL_HasGamepads(), SDL_HasJoysticks(), and SDL_HasSensors()

From 324c0b76a0111f0955063ac657617708208963ea Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 29 Dec 2022 23:07:30 -0800
Subject: [PATCH] Removed SDL_HasGamepads(), SDL_HasJoysticks(), and
 SDL_HasSensors()

Also cleaned up logic for whether we need to poll for events:
- We need to periodically poll for joysticks to handle hotplug.
- We need to frequently poll for joysticks and sensors when they're open so their state can be updated
---
 WhatsNew.txt                      |  6 ++--
 docs/README-migration.md          |  8 +++---
 include/SDL3/SDL_gamepad.h        | 11 --------
 include/SDL3/SDL_joystick.h       | 11 --------
 include/SDL3/SDL_sensor.h         | 11 --------
 src/dynapi/SDL_dynapi.sym         |  3 --
 src/dynapi/SDL_dynapi_overrides.h |  3 --
 src/dynapi/SDL_dynapi_procs.h     |  3 --
 src/events/SDL_events.c           | 46 ++++++------------------------
 src/joystick/SDL_gamepad.c        | 17 -----------
 src/joystick/SDL_joystick.c       | 18 ++++++------
 src/joystick/SDL_joystick_c.h     |  3 ++
 src/sensor/SDL_sensor.c           | 47 ++++++++-----------------------
 src/sensor/SDL_sensor_c.h         |  3 ++
 test/gamepadmap.c                 | 27 ++++++++++++++----
 15 files changed, 64 insertions(+), 153 deletions(-)

diff --git a/WhatsNew.txt b/WhatsNew.txt
index 6733ad8d99a0..e6befaaa4005 100644
--- a/WhatsNew.txt
+++ b/WhatsNew.txt
@@ -12,9 +12,9 @@ General:
 * The preprocessor symbol __IPHONEOS__ has been renamed __IOS__
 * SDL_stdinc.h no longer includes stdio.h, stdlib.h, etc., it only provides the SDL C runtime functionality
 * Added SDL_CreateSurface() and SDL_CreateSurfaceFrom() which replace SDL_CreateRGBSurface*(), and can also be used to create YUV surfaces
-* Added SDL_HasJoysticks(), SDL_GetJoysticks(), SDL_GetJoystickInstanceName(), SDL_GetJoystickInstancePath(), SDL_GetJoystickInstancePlayerIndex(), SDL_GetJoystickInstanceGUID(), SDL_GetJoystickInstanceVendor(), SDL_GetJoystickInstanceProduct(), SDL_GetJoystickInstanceProductVersion(), and SDL_GetJoystickInstanceType() to directly query the list of available joysticks
-* Added SDL_HasGamepads(), SDL_GetGamepads(), SDL_GetGamepadInstanceName(), SDL_GetGamepadInstancePath(), SDL_GetGamepadInstancePlayerIndex(), SDL_GetGamepadInstanceGUID(), SDL_GetGamepadInstanceVendor(), SDL_GetGamepadInstanceProduct(), SDL_GetGamepadInstanceProductVersion(), and SDL_GetGamepadInstanceType() to directly query the list of available gamepads
-* Added SDL_HasSensors(), SDL_GetSensors(), SDL_GetSensorInstanceName(), SDL_GetSensorInstanceType(), and SDL_GetSensorInstanceNonPortableType() to directly query the list of available sensors
+* Added SDL_GetJoysticks(), SDL_GetJoystickInstanceName(), SDL_GetJoystickInstancePath(), SDL_GetJoystickInstancePlayerIndex(), SDL_GetJoystickInstanceGUID(), SDL_GetJoystickInstanceVendor(), SDL_GetJoystickInstanceProduct(), SDL_GetJoystickInstanceProductVersion(), and SDL_GetJoystickInstanceType() to directly query the list of available joysticks
+* Added SDL_GetGamepads(), SDL_GetGamepadInstanceName(), SDL_GetGamepadInstancePath(), SDL_GetGamepadInstancePlayerIndex(), SDL_GetGamepadInstanceGUID(), SDL_GetGamepadInstanceVendor(), SDL_GetGamepadInstanceProduct(), SDL_GetGamepadInstanceProductVersion(), and SDL_GetGamepadInstanceType() to directly query the list of available gamepads
+* Added SDL_GetSensors(), SDL_GetSensorInstanceName(), SDL_GetSensorInstanceType(), and SDL_GetSensorInstanceNonPortableType() to directly query the list of available sensors
 * SDL_GetTicks() now returns a 64-bit value and the tick values should be directly compared instead of using the SDL_TICKS_PASSED macro
 * Added SDL_GetTicksNS() to return the number of nanoseconds since the SDL library initialized
 * Added SDL_DelayNS() to specify a delay in nanoseconds, to the highest precision the system will support
diff --git a/docs/README-migration.md b/docs/README-migration.md
index 56417441b6b4..655e5b79fc5c 100644
--- a/docs/README-migration.md
+++ b/docs/README-migration.md
@@ -119,7 +119,7 @@ SDL_gamecontroller.h has been renamed SDL_gamepad.h, and all APIs have been rena
 
 The SDL_GAMEPADADDED event now provides the joystick instance ID in the which member of the cdevice event structure.
 
-The functions SDL_HasGamepads(), SDL_GetGamepads(), SDL_GetGamepadInstanceName(), SDL_GetGamepadInstancePath(), SDL_GetGamepadInstancePlayerIndex(), SDL_GetGamepadInstanceGUID(), SDL_GetGamepadInstanceVendor(), SDL_GetGamepadInstanceProduct(), SDL_GetGamepadInstanceProductVersion(), and SDL_GetGamepadInstanceType() have been added to directly query the list of available gamepads.
+The functions SDL_GetGamepads(), SDL_GetGamepadInstanceName(), SDL_GetGamepadInstancePath(), SDL_GetGamepadInstancePlayerIndex(), SDL_GetGamepadInstanceGUID(), SDL_GetGamepadInstanceVendor(), SDL_GetGamepadInstanceProduct(), SDL_GetGamepadInstanceProductVersion(), and SDL_GetGamepadInstanceType() have been added to directly query the list of available gamepads.
 
 SDL_GameControllerGetSensorDataWithTimestamp() has been removed. If you want timestamps for the sensor data, you should use the sensor_timestamp member of SDL_GAMEPADSENSORUPDATE events.
 
@@ -297,7 +297,7 @@ Rather than iterating over joysticks using device index, there is a new function
 
 The SDL_JOYDEVICEADDED event now provides the joystick instance ID in the `which` member of the jdevice event structure.
 
-The functions SDL_HasJoysticks(), SDL_GetJoysticks(), SDL_GetJoystickInstanceName(), SDL_GetJoystickInstancePath(), SDL_GetJoystickInstancePlayerIndex(), SDL_GetJoystickInstanceGUID(), SDL_GetJoystickInstanceVendor(), SDL_GetJoystickInstanceProduct(), SDL_GetJoystickInstanceProductVersion(), and SDL_GetJoystickInstanceType() have been added to directly query the list of available joysticks.
+The functions SDL_GetJoysticks(), SDL_GetJoystickInstanceName(), SDL_GetJoystickInstancePath(), SDL_GetJoystickInstancePlayerIndex(), SDL_GetJoystickInstanceGUID(), SDL_GetJoystickInstanceVendor(), SDL_GetJoystickInstanceProduct(), SDL_GetJoystickInstanceProductVersion(), and SDL_GetJoystickInstanceType() have been added to directly query the list of available joysticks.
 
 SDL_AttachVirtualJoystick() and SDL_AttachVirtualJoystickEx() now return the joystick instance ID instead of a device index, and return 0 if there was an error.
 
@@ -356,7 +356,7 @@ The following functions have been removed:
 * SDL_JoystickGetDeviceVendor() - replaced with SDL_GetJoystickInstanceVendor()
 * SDL_JoystickNameForIndex() - replaced with SDL_GetJoystickInstanceName()
 * SDL_JoystickPathForIndex() - replaced with SDL_GetJoystickInstancePath()
-* SDL_NumJoysticks - replaced with SDL_HasJoysticks() and SDL_GetJoysticks()
+* SDL_NumJoysticks - replaced with SDL_GetJoysticks()
  
 ## SDL_keycode.h
 
@@ -704,7 +704,7 @@ The following functions have been renamed:
 
 The following functions have been removed:
 * SDL_LockSensors()
-* SDL_NumSensors() - replaced with SDL_HasSensors() and SDL_GetSensors()
+* SDL_NumSensors() - replaced with SDL_GetSensors()
 * SDL_SensorGetDeviceInstanceID()
 * SDL_SensorGetDeviceName() - replaced with SDL_GetSensorInstanceName()
 * SDL_SensorGetDeviceNonPortableType() - replaced with SDL_GetSensorInstanceNonPortableType()
diff --git a/include/SDL3/SDL_gamepad.h b/include/SDL3/SDL_gamepad.h
index 0861a664f6a6..3e2b059b98a9 100644
--- a/include/SDL3/SDL_gamepad.h
+++ b/include/SDL3/SDL_gamepad.h
@@ -274,17 +274,6 @@ extern DECLSPEC char * SDLCALL SDL_GetGamepadMappingForGUID(SDL_JoystickGUID gui
  */
 extern DECLSPEC char * SDLCALL SDL_GetGamepadMapping(SDL_Gamepad *gamepad);
 
-/**
- * Return whether there are gamepads connected
- *
- * \returns SDL_TRUE if there are gamepads connected, SDL_FALSE otherwise.
- *
- * \since This function is available since SDL 3.0.0.
- *
- * \sa SDL_GetGamepads
- */
-extern DECLSPEC SDL_bool SDLCALL SDL_HasGamepads(void);
-
 /**
  * Get a list of currently connected gamepads.
  *
diff --git a/include/SDL3/SDL_joystick.h b/include/SDL3/SDL_joystick.h
index c3ac436949bf..5e75df8874a1 100644
--- a/include/SDL3/SDL_joystick.h
+++ b/include/SDL3/SDL_joystick.h
@@ -136,17 +136,6 @@ extern DECLSPEC void SDLCALL SDL_LockJoysticks(void) SDL_ACQUIRE(SDL_joystick_lo
  */
 extern DECLSPEC void SDLCALL SDL_UnlockJoysticks(void) SDL_RELEASE(SDL_joystick_lock);
 
-/**
- * Return whether there are joysticks connected
- *
- * \returns SDL_TRUE if there are joysticks connected, SDL_FALSE otherwise.
- *
- * \since This function is available since SDL 3.0.0.
- *
- * \sa SDL_GetJoysticks
- */
-extern DECLSPEC SDL_bool SDLCALL SDL_HasJoysticks(void);
-
 /**
  * Get a list of currently connected joysticks.
  *
diff --git a/include/SDL3/SDL_sensor.h b/include/SDL3/SDL_sensor.h
index c5e341e903c7..7431660f9ee1 100644
--- a/include/SDL3/SDL_sensor.h
+++ b/include/SDL3/SDL_sensor.h
@@ -128,17 +128,6 @@ typedef enum
 
 /* Function prototypes */
 
-/**
- * Return whether there are sensors connected
- *
- * \returns SDL_TRUE if there are sensors connected, SDL_FALSE otherwise.
- *
- * \since This function is available since SDL 3.0.0.
- *
- * \sa SDL_GetSensors
- */
-extern DECLSPEC SDL_bool SDLCALL SDL_HasSensors(void);
-
 /**
  * Get a list of currently connected sensors.
  *
diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym
index 540c00ebf001..3c32b62b77d1 100644
--- a/src/dynapi/SDL_dynapi.sym
+++ b/src/dynapi/SDL_dynapi.sym
@@ -409,8 +409,6 @@ SDL3_0.0.0 {
     SDL_HasClipboardText;
     SDL_HasEvent;
     SDL_HasEvents;
-    SDL_HasGamepads;
-    SDL_HasJoysticks;
     SDL_HasLASX;
     SDL_HasLSX;
     SDL_HasMMX;
@@ -425,7 +423,6 @@ SDL3_0.0.0 {
     SDL_HasSSE42;
     SDL_HasSSE;
     SDL_HasScreenKeyboardSupport;
-    SDL_HasSensors;
     SDL_HideCursor;
     SDL_HideWindow;
     SDL_Init;
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index 2bc07ba4fff5..5c9f68d10439 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -435,8 +435,6 @@
 #define SDL_HasClipboardText SDL_HasClipboardText_REAL
 #define SDL_HasEvent SDL_HasEvent_REAL
 #define SDL_HasEvents SDL_HasEvents_REAL
-#define SDL_HasGamepads SDL_HasGamepads_REAL
-#define SDL_HasJoysticks SDL_HasJoysticks_REAL
 #define SDL_HasLASX SDL_HasLASX_REAL
 #define SDL_HasLSX SDL_HasLSX_REAL
 #define SDL_HasMMX SDL_HasMMX_REAL
@@ -451,7 +449,6 @@
 #define SDL_HasSSE41 SDL_HasSSE41_REAL
 #define SDL_HasSSE42 SDL_HasSSE42_REAL
 #define SDL_HasScreenKeyboardSupport SDL_HasScreenKeyboardSupport_REAL
-#define SDL_HasSensors SDL_HasSensors_REAL
 #define SDL_HideCursor SDL_HideCursor_REAL
 #define SDL_HideWindow SDL_HideWindow_REAL
 #define SDL_Init SDL_Init_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index 62bf7dd3992f..fa0eba740d78 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -507,8 +507,6 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_HasAltiVec,(void),(),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_HasClipboardText,(void),(),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_HasEvent,(Uint32 a),(a),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_HasEvents,(Uint32 a, Uint32 b),(a,b),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_HasGamepads,(void),(),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_HasJoysticks,(void),(),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_HasLASX,(void),(),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_HasLSX,(void),(),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_HasMMX,(void),(),return)
@@ -523,7 +521,6 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_HasSSE3,(void),(),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_HasSSE41,(void),(),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_HasSSE42,(void),(),return)
 SDL_DYNAPI_PROC(SDL_bool,SDL_HasScreenKeyboardSupport,(void),(),return)
-SDL_DYNAPI_PROC(SDL_bool,SDL_HasSensors,(void),(),return)
 SDL_DYNAPI_PROC(int,SDL_HideCursor,(void),(),return)
 SDL_DYNAPI_PROC(void,SDL_HideWindow,(SDL_Window *a),(a),)
 SDL_DYNAPI_PROC(int,SDL_Init,(Uint32 a),(a),return)
diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c
index 7090168171b0..756604affb55 100644
--- a/src/events/SDL_events.c
+++ b/src/events/SDL_events.c
@@ -28,6 +28,9 @@
 #if !SDL_JOYSTICK_DISABLED
 #include "../joystick/SDL_joystick_c.h"
 #endif
+#if !SDL_SENSOR_DISABLED
+#include "../sensor/SDL_sensor_c.h"
+#endif
 #include "../video/SDL_sysvideo.h"
 #include <SDL3/SDL_syswm.h>
 
@@ -99,19 +102,9 @@ static struct
 
 static SDL_bool SDL_update_joysticks = SDL_TRUE;
 
-static void SDL_CalculateShouldUpdateJoysticks(SDL_bool hint_value)
-{
-    if (hint_value &&
-        (!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] || SDL_JoystickEventsEnabled())) {
-        SDL_update_joysticks = SDL_TRUE;
-    } else {
-        SDL_update_joysticks = SDL_FALSE;
-    }
-}
-
 static void SDLCALL SDL_AutoUpdateJoysticksChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
 {
-    SDL_CalculateShouldUpdateJoysticks(SDL_GetStringBoolean(hint, SDL_TRUE));
+    SDL_update_joysticks = SDL_GetStringBoolean(hint, SDL_TRUE);
 }
 
 #endif /* !SDL_JOYSTICK_DISABLED */
@@ -120,19 +113,9 @@ static void SDLCALL SDL_AutoUpdateJoysticksChanged(void *userdata, const char *n
 
 static SDL_bool SDL_update_sensors = SDL_TRUE;
 
-static void SDL_CalculateShouldUpdateSensors(SDL_bool hint_value)
-{
-    if (hint_value &&
-        !SDL_disabled_events[SDL_SENSORUPDATE >> 8]) {
-        SDL_update_sensors = SDL_TRUE;
-    } else {
-        SDL_update_sensors = SDL_FALSE;
-    }
-}
-
 static void SDLCALL SDL_AutoUpdateSensorsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
 {
-    SDL_CalculateShouldUpdateSensors(SDL_GetStringBoolean(hint, SDL_TRUE));
+    SDL_update_sensors = SDL_GetStringBoolean(hint, SDL_TRUE);
 }
 
 #endif /* !SDL_SENSOR_DISABLED */
@@ -908,13 +891,7 @@ static SDL_bool SDL_events_need_periodic_poll()
     SDL_bool need_periodic_poll = SDL_FALSE;
 
 #if !SDL_JOYSTICK_DISABLED
-    need_periodic_poll =
-        SDL_WasInit(SDL_INIT_JOYSTICK) && SDL_update_joysticks;
-#endif
-
-#if !SDL_SENSOR_DISABLED
-    need_periodic_poll = need_periodic_poll ||
-                         (SDL_WasInit(SDL_INIT_SENSOR) && SDL_update_sensors);
+    need_periodic_poll = SDL_WasInit(SDL_INIT_JOYSTICK) && SDL_update_joysticks;
 #endif
 
     return need_periodic_poll;
@@ -997,12 +974,12 @@ static SDL_bool SDL_events_need_polling()
     SDL_bool need_polling = SDL_FALSE;
 
 #if !SDL_JOYSTICK_DISABLED
-    need_polling = SDL_WasInit(SDL_INIT_JOYSTICK) && SDL_update_joysticks && SDL_HasJoysticks();
+    need_polling = SDL_WasInit(SDL_INIT_JOYSTICK) && SDL_update_joysticks && SDL_JoysticksOpened();
 #endif
 
 #if !SDL_SENSOR_DISABLED
     need_polling = need_polling ||
-                   (SDL_WasInit(SDL_INIT_SENSOR) && SDL_update_sensors && SDL_HasSensors());
+                   (SDL_WasInit(SDL_INIT_SENSOR) && SDL_update_sensors && SDL_SensorsOpened());
 #endif
 
     return need_polling;
@@ -1293,13 +1270,6 @@ void SDL_SetEventEnabled(Uint32 type, SDL_bool enabled)
             }
         }
 
-#if !SDL_JOYSTICK_DISABLED
-        SDL_CalculateShouldUpdateJoysticks(SDL_GetHintBoolean(SDL_HINT_AUTO_UPDATE_JOYSTICKS, SDL_TRUE));
-#endif
-#if !SDL_SENSOR_DISABLED
-        SDL_CalculateShouldUpdateSensors(SDL_GetHintBoolean(SDL_HINT_AUTO_UPDATE_SENSORS, SDL_TRUE));
-#endif
-
         /* turn off drag'n'drop support if we've disabled the events.
            This might change some UI details at the OS level. */
         if (type == SDL_DROPFILE || type == SDL_DROPTEXT) {
diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c
index e82b420c10f3..c519b29c0c1d 100644
--- a/src/joystick/SDL_gamepad.c
+++ b/src/joystick/SDL_gamepad.c
@@ -1914,23 +1914,6 @@ int SDL_InitGamepads(void)
     return 0;
 }
 
-SDL_bool SDL_HasGamepads(void)
-{
-    SDL_bool retval = SDL_FALSE;
-    SDL_JoystickID *joysticks = SDL_GetJoysticks(NULL);
-    if (joysticks) {
-        int i;
-        for (i = 0; joysticks[i]; ++i) {
-            if (SDL_IsGamepad(joysticks[i])) {
-                retval = SDL_TRUE;
-                break;
-            }
-        }
-        SDL_free(joysticks);
-    }
-    return retval;
-}
-
 SDL_JoystickID *SDL_GetGamepads(int *count)
 {
     int num_joysticks = 0;
diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index 45589bc5ca96..14861824db39 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -332,19 +332,21 @@ int SDL_InitJoysticks(void)
     return status;
 }
 
-SDL_bool SDL_HasJoysticks(void)
+SDL_bool SDL_JoysticksOpened(void)
 {
-    int i;
-    SDL_bool retval = SDL_FALSE;
+    SDL_bool opened;
+
     SDL_LockJoysticks();
-    for (i = 0; i < SDL_arraysize(SDL_joystick_drivers); ++i) {
-        if (SDL_joystick_drivers[i]->GetCount() > 0) {
-            retval = SDL_TRUE;
-            break;
+    {
+        if (SDL_joysticks != NULL) {
+            opened = SDL_TRUE;
+        } else {
+            opened = SDL_FALSE;
         }
     }
     SDL_UnlockJoysticks();
-    return retval;
+
+    return opened;
 }
 
 SDL_JoystickID *SDL_GetJoysticks(int *count)
diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h
index 45a681e3019e..976b1a0daff0 100644
--- a/src/joystick/SDL_joystick_c.h
+++ b/src/joystick/SDL_joystick_c.h
@@ -49,6 +49,9 @@ extern SDL_bool SDL_JoysticksLocked(void);
 /* Make sure we currently have the joysticks locked */
 extern void SDL_AssertJoysticksLocked(void) SDL_ASSERT_CAPABILITY(SDL_joystick_lock);
 
+/* Function to return whether there are any joysticks opened by the application */
+extern SDL_bool SDL_JoysticksOpened(void);
+
 /* Function to get the next available joystick instance ID */
 extern SDL_JoystickID SDL_GetNextJoystickInstanceID(void);
 
diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c
index c2874ccf8f03..f1972f533b74 100644
--- a/src/sensor/SDL_sensor.c
+++ b/src/sensor/SDL_sensor.c
@@ -51,7 +51,6 @@ static SDL_SensorDriver *SDL_sensor_drivers[] = {
 static SDL_mutex *SDL_sensor_lock = NULL; /* This needs to support recursive locks */
 static SDL_Sensor *SDL_sensors SDL_GUARDED_BY(SDL_sensor_lock) = NULL;
 static SDL_atomic_t SDL_last_sensor_instance_id SDL_GUARDED_BY(SDL_sensor_lock);
-static SDL_bool SDL_updating_sensor SDL_GUARDED_BY(SDL_sensor_lock) = SDL_FALSE;
 
 void SDL_LockSensors(void) SDL_ACQUIRE(SDL_sensor_lock)
 {
@@ -87,19 +86,21 @@ int SDL_InitSensors(void)
     return status;
 }
 
-SDL_bool SDL_HasSensors(void)
+SDL_bool SDL_SensorsOpened(void)
 {
-    int i;
-    SDL_bool retval = SDL_FALSE;
+    SDL_bool opened;
+
     SDL_LockSensors();
-    for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) {
-        if (SDL_sensor_drivers[i]->GetCount() > 0) {
-            retval = SDL_TRUE;
-            break;
+    {
+        if (SDL_sensors != NULL) {
+            opened = SDL_TRUE;
+        } else {
+            opened = SDL_FALSE;
         }
     }
     SDL_UnlockSensors();
-    return retval;
+
+    return opened;
 }
 
 SDL_SensorID *SDL_GetSensors(int *count)
@@ -413,11 +414,6 @@ void SDL_CloseSensor(SDL_Sensor *sensor)
         return;
     }
 
-    if (SDL_updating_sensor) {
-        SDL_UnlockSensors();
-        return;
-    }
-
     sensor->driver->Close(sensor);
     sensor->hwdata = NULL;
 
@@ -451,9 +447,6 @@ void SDL_QuitSensors(void)
 
     SDL_LockSensors();
 
-    /* Make sure we're not getting called in the middle of updating sensors */
-    SDL_assert(!SDL_updating_sensor);
-
     /* Stop the event polling */
     while (SDL_sensors) {
         SDL_sensors->ref_count = 1;
@@ -510,7 +503,7 @@ int SDL_SendSensorUpdate(Uint64 timestamp, SDL_Sensor *sensor, Uint64 sensor_tim
 void SDL_UpdateSensors(void)
 {
     int i;
-    SDL_Sensor *sensor, *next;
+    SDL_Sensor *sensor;
 
     if (!SDL_WasInit(SDL_INIT_SENSOR)) {
         return;
@@ -518,28 +511,10 @@ void SDL_UpdateSensors(void)
 
     SDL_LockSensors();
 
-    if (SDL_updating_sensor) {
-        /* The sensors are already being updated */
-        SDL_UnlockSensors();
-        return;
-    }
-
-    SDL_updating_sensor = SDL_TRUE;
-
     for (sensor = SDL_sensors; sensor; sensor = sensor->next) {
         sensor->driver->Update(sensor);
     }
 
-    SDL_updating_sensor = SDL_FALSE;
-
-    /* If any sensors were closed while updating, free them here */
-    for (sensor = SDL_sensors; sensor; sensor = next) {
-        next = sensor->next;
-        if (sensor->ref_count <= 0) {
-            SDL_CloseSensor(sensor);
-        }
-    }
-
     /* this needs to happen AFTER walking the sensor list above, so that any
        dangling hardware data from removed devices can be free'd
      */
diff --git a/src/sensor/SDL_sensor_c.h b/src/sensor/SDL_sensor_c.h
index d6cb5118030e..326f911562e4 100644
--- a/src/sensor/SDL_sensor_c.h
+++ b/src/sensor/SDL_sensor_c.h
@@ -37,6 +37,9 @@ extern void SDL_QuitSensors(void);
 extern void SDL_LockSensors(void);
 extern void SDL_UnlockSensors(void);
 
+/* Function to return whether there are any sensors opened by the application */
+extern SDL_bool SDL_SensorsOpened(void);
+
 /* Internal event queueing functions */
 extern int SDL_SendSensorUpdate(Uint64 timestamp, SDL_Sensor *sensor, Uint64 sensor_timestamp, float *data, int num_values);
 
diff --git a/test/gamepadmap.c b/test/gamepadmap.c
index 9c8e173991a4..3807e217ee01 100644
--- a/test/gamepadmap.c
+++ b/test/gamepadmap.c
@@ -700,12 +700,28 @@ WatchJoystick(SDL_Joystick *joystick)
     SDL_DestroyRenderer(screen);
 }
 
+static SDL_bool HasJoysticks()
+{
+    int num_joysticks = 0;
+    SDL_JoystickID *joysticks;
+
+    joysticks = SDL_GetJoysticks(&num_joysticks);
+    if (joysticks) {
+        SDL_free(joysticks);
+    }
+    if (num_joysticks > 0) {
+        return SDL_TRUE;
+    } else {
+        return SDL_FALSE;
+    }
+}
+
 int main(int argc, char *argv[])
 {
     const char *name;
     int i;
-    SDL_JoystickID *joysticks;
     int num_joysticks = 0;
+    SDL_JoystickID *joysticks;
     int joystick_index;
     SDL_Joystick *joystick = NULL;
 
@@ -739,7 +755,7 @@ int main(int argc, char *argv[])
         return 2;
     }
 
-    while (!done && !SDL_HasJoysticks()) {
+    while (!done && !HasJoysticks()) {
         SDL_Event event;
 
         while (SDL_PollEvent(&event) > 0) {
@@ -796,10 +812,11 @@ int main(int argc, char *argv[])
     }
     if (joysticks && joystick_index < num_joysticks) {
         joystick = SDL_OpenJoystick(joysticks[joystick_index]);
+        if (joystick == NULL) {
+            SDL_Log("Couldn't open joystick %d: %s\n", joystick_index, SDL_GetError());
+        }
     }
-    if (joystick == NULL) {
-        SDL_Log("Couldn't open joystick %d: %s\n", joystick_index, SDL_GetError());
-    } else {
+    if (joystick != NULL) {
         WatchJoystick(joystick);
         SDL_CloseJoystick(joystick);
     }