diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index 8443ba03ab..2df24a6336 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -318,22 +318,6 @@ static void RecenterGamepad(SDL_Gamepad *gamepad) } } -/* SDL defines sensor orientation relative to the device natural - orientation, so when it's changed orientation to be used as a - gamepad, change the sensor orientation to match. - */ -static void AdjustSensorOrientation(SDL_Joystick *joystick, float *src, float *dst) -{ - unsigned int i, j; - - for (i = 0; i < 3; ++i) { - dst[i] = 0.0f; - for (j = 0; j < 3; ++j) { - dst[i] += joystick->sensor_transform[i][j] * src[j]; - } - } -} - /* * Event filter to fire gamepad events from joystick ones */ @@ -408,23 +392,6 @@ static int SDLCALL SDL_GamepadEventWatcher(void *userdata, SDL_Event *event) SDL_PushEvent(&deviceevent); } } break; - case SDL_EVENT_SENSOR_UPDATE: - { - SDL_LockJoysticks(); - for (gamepad = SDL_gamepads; gamepad; gamepad = gamepad->next) { - if (gamepad->joystick->accel && gamepad->joystick->accel_sensor == event->sensor.which) { - float data[3]; - AdjustSensorOrientation(gamepad->joystick, event->sensor.data, data); - SDL_SendJoystickSensor(event->common.timestamp, gamepad->joystick, SDL_SENSOR_ACCEL, event->sensor.sensor_timestamp, data, SDL_arraysize(data)); - } - if (gamepad->joystick->gyro && gamepad->joystick->gyro_sensor == event->sensor.which) { - float data[3]; - AdjustSensorOrientation(gamepad->joystick, event->sensor.data, data); - SDL_SendJoystickSensor(event->common.timestamp, gamepad->joystick, SDL_SENSOR_GYRO, event->sensor.sensor_timestamp, data, SDL_arraysize(data)); - } - } - SDL_UnlockJoysticks(); - } break; default: break; } @@ -432,6 +399,52 @@ static int SDLCALL SDL_GamepadEventWatcher(void *userdata, SDL_Event *event) return 1; } +/* SDL defines sensor orientation relative to the device natural + orientation, so when it's changed orientation to be used as a + gamepad, change the sensor orientation to match. + */ +static void AdjustSensorOrientation(SDL_Joystick *joystick, float *src, float *dst) +{ + unsigned int i, j; + + for (i = 0; i < 3; ++i) { + dst[i] = 0.0f; + for (j = 0; j < 3; ++j) { + dst[i] += joystick->sensor_transform[i][j] * src[j]; + } + } +} + +/* + * Event filter to fire gamepad sensor events from system sensor events + * + * We don't use SDL_GamepadEventWatcher() for this because we want to + * deliver gamepad sensor events when system sensor events are disabled, + * and we also need to avoid a potential deadlock where joystick event + * delivery locks the joysticks and then the event queue, but sensor + * event delivery would lock the event queue and then from within the + * event watcher function lock the joysticks. + */ +void SDL_GamepadSensorWatcher(Uint64 timestamp, SDL_SensorID sensor, Uint64 sensor_timestamp, float *data, int num_values) +{ + SDL_Gamepad *gamepad; + + SDL_LockJoysticks(); + for (gamepad = SDL_gamepads; gamepad; gamepad = gamepad->next) { + if (gamepad->joystick->accel && gamepad->joystick->accel_sensor == sensor) { + float gamepad_data[3]; + AdjustSensorOrientation(gamepad->joystick, data, gamepad_data); + SDL_SendJoystickSensor(timestamp, gamepad->joystick, SDL_SENSOR_ACCEL, sensor_timestamp, gamepad_data, SDL_arraysize(gamepad_data)); + } + if (gamepad->joystick->gyro && gamepad->joystick->gyro_sensor == sensor) { + float gamepad_data[3]; + AdjustSensorOrientation(gamepad->joystick, data, gamepad_data); + SDL_SendJoystickSensor(timestamp, gamepad->joystick, SDL_SENSOR_GYRO, sensor_timestamp, gamepad_data, SDL_arraysize(gamepad_data)); + } + } + SDL_UnlockJoysticks(); +} + #ifdef __ANDROID__ /* * Helper function to guess at a mapping based on the elements reported for this gamepad diff --git a/src/joystick/SDL_gamepad_c.h b/src/joystick/SDL_gamepad_c.h index 16db7f69ee..d7472db508 100644 --- a/src/joystick/SDL_gamepad_c.h +++ b/src/joystick/SDL_gamepad_c.h @@ -42,4 +42,7 @@ extern SDL_bool SDL_ShouldIgnoreGamepad(const char *name, SDL_JoystickGUID guid) /* Handle delayed guide button on a gamepad */ extern void SDL_GamepadHandleDelayedGuideButton(SDL_Joystick *joystick); +/* Handle system sensor data */ +extern void SDL_GamepadSensorWatcher(Uint64 timestamp, SDL_SensorID sensor, Uint64 sensor_timestamp, float *data, int num_values); + #endif /* SDL_gamepad_c_h_ */ diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c index d3eb6beee9..c9a5ab74bf 100644 --- a/src/sensor/SDL_sensor.c +++ b/src/sensor/SDL_sensor.c @@ -27,6 +27,7 @@ #ifndef SDL_EVENTS_DISABLED #include "../events/SDL_events_c.h" #endif +#include "../joystick/SDL_gamepad_c.h" static SDL_SensorDriver *SDL_sensor_drivers[] = { #ifdef SDL_SENSOR_ANDROID @@ -501,6 +502,9 @@ int SDL_SendSensorUpdate(Uint64 timestamp, SDL_Sensor *sensor, Uint64 sensor_tim posted = SDL_PushEvent(&event) == 1; } #endif /* !SDL_EVENTS_DISABLED */ + + SDL_GamepadSensorWatcher(timestamp, sensor->instance_id, sensor_timestamp, data, num_values); + return posted; }