From 73f4aeee6a2affe2777acf513a745142ec81ebf6 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 3 Dec 2022 11:15:50 -0800
Subject: [PATCH] Pass the event timestamp for joystick events
This allows the application to get more fine grained information about controller event timing, and group events that happened together.
---
src/core/linux/SDL_evdev.c | 102 +++---
src/core/linux/SDL_evdev.h | 3 +
src/joystick/SDL_gamecontroller.c | 53 +--
src/joystick/SDL_joystick.c | 35 +-
src/joystick/SDL_joystick_c.h | 12 +-
src/joystick/android/SDL_sysjoystick.c | 17 +-
src/joystick/apple/SDL_mfijoystick.m | 36 ++-
src/joystick/bsd/SDL_bsdjoystick.c | 23 +-
src/joystick/darwin/SDL_iokitjoystick.c | 7 +-
src/joystick/emscripten/SDL_sysjoystick.c | 5 +-
src/joystick/haiku/SDL_haikujoystick.cc | 7 +-
src/joystick/hidapi/SDL_hidapi_gamecube.c | 52 +--
src/joystick/hidapi/SDL_hidapi_luna.c | 92 +++---
src/joystick/hidapi/SDL_hidapi_ps3.c | 135 ++++----
src/joystick/hidapi/SDL_hidapi_ps4.c | 53 +--
src/joystick/hidapi/SDL_hidapi_ps5.c | 106 +++---
src/joystick/hidapi/SDL_hidapi_shield.c | 101 +++---
src/joystick/hidapi/SDL_hidapi_stadia.c | 47 +--
src/joystick/hidapi/SDL_hidapi_steam.c | 50 +--
src/joystick/hidapi/SDL_hidapi_switch.c | 304 +++++++++---------
src/joystick/hidapi/SDL_hidapi_wii.c | 55 ++--
src/joystick/hidapi/SDL_hidapi_xbox360.c | 43 +--
src/joystick/hidapi/SDL_hidapi_xbox360w.c | 43 +--
src/joystick/hidapi/SDL_hidapi_xboxone.c | 159 ++++-----
src/joystick/linux/SDL_sysjoystick.c | 48 +--
src/joystick/n3ds/SDL_sysjoystick.c | 42 ++-
src/joystick/ps2/SDL_sysjoystick.c | 5 +-
src/joystick/psp/SDL_sysjoystick.c | 7 +-
src/joystick/virtual/SDL_virtualjoystick.c | 7 +-
src/joystick/vita/SDL_sysjoystick.c | 15 +-
src/joystick/windows/SDL_dinputjoystick.c | 28 +-
src/joystick/windows/SDL_rawinputjoystick.c | 45 ++-
.../windows/SDL_windows_gaming_input.c | 11 +-
src/joystick/windows/SDL_xinputjoystick.c | 32 +-
src/timer/SDL_timer.c | 10 +
src/timer/SDL_timer_c.h | 1 +
36 files changed, 951 insertions(+), 840 deletions(-)
diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c
index f337999979a1..a8e96cfaef67 100644
--- a/src/core/linux/SDL_evdev.c
+++ b/src/core/linux/SDL_evdev.c
@@ -38,6 +38,7 @@
#include <sys/ioctl.h>
#include <linux/input.h>
+#include "../../timer/SDL_timer_c.h"
#include "../../events/SDL_events_c.h"
#include "../../events/SDL_scancode_tables_c.h"
#include "../../core/linux/SDL_evdev_capabilities.h"
@@ -290,32 +291,34 @@ void SDL_EVDEV_Poll(void)
while ((len = read(item->fd, events, (sizeof events))) > 0) {
len /= sizeof(events[0]);
for (i = 0; i < len; ++i) {
+ struct input_event *event = &events[i];
+
/* special handling for touchscreen, that should eventually be
used for all devices */
if (item->out_of_sync && item->is_touchscreen &&
- events[i].type == EV_SYN && events[i].code != SYN_REPORT) {
+ event->type == EV_SYN && event->code != SYN_REPORT) {
break;
}
- switch (events[i].type) {
+ switch (event->type) {
case EV_KEY:
- if (events[i].code >= BTN_MOUSE && events[i].code < BTN_MOUSE + SDL_arraysize(EVDEV_MouseButtons)) {
- mouse_button = events[i].code - BTN_MOUSE;
- if (events[i].value == 0) {
- SDL_SendMouseButton(0, mouse->focus, (SDL_MouseID)item->fd, SDL_RELEASED, EVDEV_MouseButtons[mouse_button]);
- } else if (events[i].value == 1) {
- SDL_SendMouseButton(0, mouse->focus, (SDL_MouseID)item->fd, SDL_PRESSED, EVDEV_MouseButtons[mouse_button]);
+ if (event->code >= BTN_MOUSE && event->code < BTN_MOUSE + SDL_arraysize(EVDEV_MouseButtons)) {
+ mouse_button = event->code - BTN_MOUSE;
+ if (event->value == 0) {
+ SDL_SendMouseButton(SDL_EVDEV_GetEventTimestamp(event), mouse->focus, (SDL_MouseID)item->fd, SDL_RELEASED, EVDEV_MouseButtons[mouse_button]);
+ } else if (event->value == 1) {
+ SDL_SendMouseButton(SDL_EVDEV_GetEventTimestamp(event), mouse->focus, (SDL_MouseID)item->fd, SDL_PRESSED, EVDEV_MouseButtons[mouse_button]);
}
break;
}
- /* BTH_TOUCH event value 1 indicates there is contact with
+ /* BTN_TOUCH event value 1 indicates there is contact with
a touchscreen or trackpad (earlist finger's current
position is sent in EV_ABS ABS_X/ABS_Y, switching to
next finger after earlist is released) */
- if (item->is_touchscreen && events[i].code == BTN_TOUCH) {
+ if (item->is_touchscreen && event->code == BTN_TOUCH) {
if (item->touchscreen_data->max_slots == 1) {
- if (events[i].value) {
+ if (event->value) {
item->touchscreen_data->slots[0].delta = EVDEV_TOUCH_SLOTDELTA_DOWN;
} else {
item->touchscreen_data->slots[0].delta = EVDEV_TOUCH_SLOTDELTA_UP;
@@ -325,30 +328,30 @@ void SDL_EVDEV_Poll(void)
}
/* Probably keyboard */
- scan_code = SDL_EVDEV_translate_keycode(events[i].code);
+ scan_code = SDL_EVDEV_translate_keycode(event->code);
if (scan_code != SDL_SCANCODE_UNKNOWN) {
- if (events[i].value == 0) {
- SDL_SendKeyboardKey(0, SDL_RELEASED, scan_code);
- } else if (events[i].value == 1 || events[i].value == 2 /* key repeated */) {
- SDL_SendKeyboardKey(0, SDL_PRESSED, scan_code);
+ if (event->value == 0) {
+ SDL_SendKeyboardKey(SDL_EVDEV_GetEventTimestamp(event), SDL_RELEASED, scan_code);
+ } else if (event->value == 1 || event->value == 2 /* key repeated */) {
+ SDL_SendKeyboardKey(SDL_EVDEV_GetEventTimestamp(event), SDL_PRESSED, scan_code);
}
}
- SDL_EVDEV_kbd_keycode(_this->kbd, events[i].code, events[i].value);
+ SDL_EVDEV_kbd_keycode(_this->kbd, event->code, event->value);
break;
case EV_ABS:
- switch (events[i].code) {
+ switch (event->code) {
case ABS_MT_SLOT:
if (!item->is_touchscreen) { /* FIXME: temp hack */
break;
}
- item->touchscreen_data->current_slot = events[i].value;
+ item->touchscreen_data->current_slot = event->value;
break;
case ABS_MT_TRACKING_ID:
if (!item->is_touchscreen) { /* FIXME: temp hack */
break;
}
- if (events[i].value >= 0) {
- item->touchscreen_data->slots[item->touchscreen_data->current_slot].tracking_id = events[i].value;
+ if (event->value >= 0) {
+ item->touchscreen_data->slots[item->touchscreen_data->current_slot].tracking_id = event->value;
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_DOWN;
} else {
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_UP;
@@ -358,7 +361,7 @@ void SDL_EVDEV_Poll(void)
if (!item->is_touchscreen) { /* FIXME: temp hack */
break;
}
- item->touchscreen_data->slots[item->touchscreen_data->current_slot].x = events[i].value;
+ item->touchscreen_data->slots[item->touchscreen_data->current_slot].x = event->value;
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
}
@@ -367,7 +370,7 @@ void SDL_EVDEV_Poll(void)
if (!item->is_touchscreen) { /* FIXME: temp hack */
break;
}
- item->touchscreen_data->slots[item->touchscreen_data->current_slot].y = events[i].value;
+ item->touchscreen_data->slots[item->touchscreen_data->current_slot].y = event->value;
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
}
@@ -376,7 +379,7 @@ void SDL_EVDEV_Poll(void)
if (!item->is_touchscreen) { /* FIXME: temp hack */
break;
}
- item->touchscreen_data->slots[item->touchscreen_data->current_slot].pressure = events[i].value;
+ item->touchscreen_data->slots[item->touchscreen_data->current_slot].pressure = event->value;
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
}
@@ -386,10 +389,10 @@ void SDL_EVDEV_Poll(void)
if (item->touchscreen_data->max_slots != 1) {
break;
}
- item->touchscreen_data->slots[0].x = events[i].value;
+ item->touchscreen_data->slots[0].x = event->value;
} else if (!item->relative_mouse) {
/* FIXME: Normalize to input device's reported input range (EVIOCGABS) */
- item->mouse_x = events[i].value;
+ item->mouse_x = event->value;
}
break;
case ABS_Y:
@@ -397,10 +400,10 @@ void SDL_EVDEV_Poll(void)
if (item->touchscreen_data->max_slots != 1) {
break;
}
- item->touchscreen_data->slots[0].y = events[i].value;
+ item->touchscreen_data->slots[0].y = event->value;
} else if (!item->relative_mouse) {
/* FIXME: Normalize to input device's reported input range (EVIOCGABS) */
- item->mouse_y = events[i].value;
+ item->mouse_y = event->value;
}
break;
default:
@@ -408,49 +411,50 @@ void SDL_EVDEV_Poll(void)
}
break;
case EV_REL:
- switch (events[i].code) {
+ switch (event->code) {
case REL_X:
if (item->relative_mouse) {
- item->mouse_x += events[i].value;
+ item->mouse_x += event->value;
}
break;
case REL_Y:
if (item->relative_mouse) {
- item->mouse_y += events[i].value;
+ item->mouse_y += event->value;
}
break;
case REL_WHEEL:
if (!item->high_res_wheel) {
- item->mouse_wheel += events[i].value;
+ item->mouse_wheel += event->value;
}
break;
case REL_WHEEL_HI_RES:
SDL_assert(item->high_res_wheel);
- item->mouse_wheel += events[i].value;
+ item->mouse_wheel += event->value;
break;
case REL_HWHEEL:
if (!item->high_res_hwheel) {
- item->mouse_hwheel += events[i].value;
+ item->mouse_hwheel += event->value;
}
break;
case REL_HWHEEL_HI_RES:
SDL_assert(item->high_res_hwheel);
- item->mouse_hwheel += events[i].value;
+ item->mouse_hwheel += event->value;
break;
default:
break;
}
break;
case EV_SYN:
- switch (events[i].code) {
+ switch (event->code) {
case SYN_REPORT:
/* Send mouse axis changes together to ensure consistency and reduce event processing overhead */
if (item->mouse_x != 0 || item->mouse_y != 0) {
- SDL_SendMouseMotion(0, mouse->focus, (SDL_MouseID)item->fd, item->relative_mouse, item->mouse_x, item->mouse_y);
+ SDL_SendMouseMotion(SDL_EVDEV_GetEventTimestamp(event), mouse->focus, (SDL_MouseID)item->fd, item->relative_mouse, item->mouse_x, item->mouse_y);
item->mouse_x = item->mouse_y = 0;
}
if (item->mouse_wheel != 0 || item->mouse_hwheel != 0) {
- SDL_SendMouseWheel(0, mouse->focus, (SDL_MouseID)item->fd,
+ SDL_SendMouseWheel(SDL_EVDEV_GetEventTimestamp(event),
+ mouse->focus, (SDL_MouseID)item->fd,
item->mouse_hwheel / (item->high_res_hwheel ? 120.0f : 1.0f),
item->mouse_wheel / (item->high_res_wheel ? 120.0f : 1.0f),
SDL_MOUSEWHEEL_NORMAL);
@@ -480,16 +484,16 @@ void SDL_EVDEV_Poll(void)
* be window-relative in that case. */
switch (item->touchscreen_data->slots[j].delta) {
case EVDEV_TOUCH_SLOTDELTA_DOWN:
- SDL_SendTouch(0, item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, SDL_TRUE, norm_x, norm_y, norm_pressure);
+ SDL_SendTouch(SDL_EVDEV_GetEventTimestamp(event), item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, SDL_TRUE, norm_x, norm_y, norm_pressure);
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
break;
case EVDEV_TOUCH_SLOTDELTA_UP:
- SDL_SendTouch(0, item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, SDL_FALSE, norm_x, norm_y, norm_pressure);
+ SDL_SendTouch(SDL_EVDEV_GetEventTimestamp(event), item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, SDL_FALSE, norm_x, norm_y, norm_pressure);
item->touchscreen_data->slots[j].tracking_id = -1;
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
break;
case EVDEV_TOUCH_SLOTDELTA_MOVE:
- SDL_SendTouchMotion(0, item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, norm_x, norm_y, norm_pressure);
+ SDL_SendTouchMotion(SDL_EVDEV_GetEventTimestamp(event), item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, norm_x, norm_y, norm_pressure);
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
break;
default:
@@ -870,6 +874,22 @@ static int SDL_EVDEV_device_removed(const char *dev_path)
return -1;
}
+Uint64 SDL_EVDEV_GetEventTimestamp(struct input_event *event)
+{
+ Uint64 timestamp;
+
+ /* The kernel internally has nanosecond timestamps, but converts it
+ to microseconds when delivering the events */
+ timestamp = event->time.tv_sec;
+ timestamp *= SDL_NS_PER_SECOND;
+ timestamp += SDL_US_TO_NS(event->time.tv_usec);
+
+ /* Let's assume for now that we're using the same time base */
+ timestamp -= SDL_GetTickStartNS();
+
+ return timestamp;
+}
+
#endif /* SDL_INPUT_LINUXEV */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/core/linux/SDL_evdev.h b/src/core/linux/SDL_evdev.h
index 005ec0ee3a0a..6c0abe17f818 100644
--- a/src/core/linux/SDL_evdev.h
+++ b/src/core/linux/SDL_evdev.h
@@ -26,9 +26,12 @@
#ifdef SDL_INPUT_LINUXEV
+struct input_event;
+
extern int SDL_EVDEV_Init(void);
extern void SDL_EVDEV_Quit(void);
extern void SDL_EVDEV_Poll(void);
+extern Uint64 SDL_EVDEV_GetEventTimestamp(struct input_event *event);
#endif /* SDL_INPUT_LINUXEV */
diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c
index f027186306b6..0d62e24c90f2 100644
--- a/src/joystick/SDL_gamecontroller.c
+++ b/src/joystick/SDL_gamecontroller.c
@@ -206,8 +206,8 @@ static void SDLCALL SDL_GameControllerIgnoreDevicesExceptChanged(void *userdata,
}
static ControllerMapping_t *SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, const char *mappingString, SDL_bool *existing, SDL_ControllerMappingPriority priority);
-static int SDL_PrivateGameControllerAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis, Sint16 value);
-static int SDL_PrivateGameControllerButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button, Uint8 state);
+static int SDL_PrivateGameControllerAxis(Uint64 timestamp, SDL_GameController *gamecontroller, SDL_GameControllerAxis axis, Sint16 value);
+static int SDL_PrivateGameControllerButton(Uint64 timestamp, SDL_GameController *gamecontroller, SDL_GameControllerButton button, Uint8 state);
static SDL_bool HasSameOutput(SDL_ExtendedGameControllerBind *a, SDL_ExtendedGameControllerBind *b)
{
@@ -222,16 +222,16 @@ static SDL_bool HasSameOutput(SDL_ExtendedGameControllerBind *a, SDL_ExtendedGam
}
}
-static void ResetOutput(SDL_GameController *gamecontroller, SDL_ExtendedGameControllerBind *bind)
+static void ResetOutput(Uint64 timestamp, SDL_GameController *gamecontroller, SDL_ExtendedGameControllerBind *bind)
{
if (bind->outputType == SDL_CONTROLLER_BINDTYPE_AXIS) {
- SDL_PrivateGameControllerAxis(gamecontroller, bind->output.axis.axis, 0);
+ SDL_PrivateGameControllerAxis(timestamp, gamecontroller, bind->output.axis.axis, 0);
} else {
- SDL_PrivateGameControllerButton(gamecontroller, bind->output.button, SDL_RELEASED);
+ SDL_PrivateGameControllerButton(timestamp, gamecontroller, bind->output.button, SDL_RELEASED);
}
}
-static void HandleJoystickAxis(SDL_GameController *gamecontroller, int axis, int value)
+static void HandleJoystickAxis(Uint64 timestamp, SDL_GameController *gamecontroller, int axis, int value)
{
int i;
SDL_ExtendedGameControllerBind *last_match;
@@ -262,7 +262,7 @@ static void HandleJoystickAxis(SDL_GameController *gamecontroller, int axis, int
if (last_match && (match == NULL || !HasSameOutput(last_match, match))) {
/* Clear the last input that this axis generated */
- ResetOutput(gamecontroller, last_match);
+ ResetOutput(timestamp, gamecontroller, last_match);
}
if (match) {
@@ -271,7 +271,7 @@ static void HandleJoystickAxis(SDL_GameController *gamecontroller, int axis, int
float normalized_value = (float)(value - match->input.axis.axis_min) / (match->input.axis.axis_max - match->input.axis.axis_min);
value = match->output.axis.axis_min + (int)(normalized_value * (match->output.axis.axis_max - match->output.axis.axis_min));
}
- SDL_PrivateGameControllerAxis(gamecontroller, match->output.axis.axis, (Sint16)value);
+ SDL_PrivateGameControllerAxis(timestamp, gamecontroller, match->output.axis.axis, (Sint16)value);
} else {
Uint8 state;
int threshold = match->input.axis.axis_min + (match->input.axis.axis_max - match->input.axis.axis_min) / 2;
@@ -280,13 +280,13 @@ static void HandleJoystickAxis(SDL_GameController *gamecontroller, int axis, int
} else {
state = (value >= threshold) ? SDL_PRESSED : SDL_RELEASED;
}
- SDL_PrivateGameControllerButton(gamecontroller, match->output.button, state);
+ SDL_PrivateGameControllerButton(timestamp, gamecontroller, match->output.button, state);
}
}
gamecontroller->last_match_axis[axis] = match;
}
-static void HandleJoystickButton(SDL_GameController *gamecontroller, int button, Uint8 state)
+static void HandleJoystickButton(Uint64 timestamp, SDL_GameController *gamecontroller, int button, Uint8 state)
{
int i;
@@ -298,16 +298,16 @@ static void HandleJoystickButton(SDL_GameController *gamecontroller, int button,
button == binding->input.button) {
if (binding->outputType == SDL_CONTROLLER_BINDTYPE_AXIS) {
int value = state ? binding->output.axis.axis_max : binding->output.axis.axis_min;
- SDL_PrivateGameControllerAxis(gamecontroller, binding->output.axis.axis, (Sint16)value);
+ SDL_PrivateGameControllerAxis(timestamp, gamecontroller, binding->output.axis.axis, (Sint16)value);
} else {
- SDL_PrivateGameControllerButton(gamecontroller, binding->output.button, state);
+ SDL_PrivateGameControllerButton(timestamp, gamecontroller, binding->output.button, state);
}
break;
}
}
}
-static void HandleJoystickHat(SDL_GameController *gamecontroller, int hat, Uint8 value)
+static void HandleJoystickHat(Uint64 timestamp, SDL_GameController *gamecontroller, int hat, Uint8 value)
{
int i;
Uint8 last_mask, changed_mask;
@@ -322,12 +322,12 @@ static void HandleJoystickHat(SDL_GameController *gamecontroller, int hat, Uint8
if ((changed_mask & binding->input.hat.hat_mask) != 0) {
if (value & binding->input.hat.hat_mask) {
if (binding->outputType == SDL_CONTROLLER_BINDTYPE_AXIS) {
- SDL_PrivateGameControllerAxis(gamecontroller, binding->output.axis.axis, (Sint16)binding->output.axis.axis_max);
+ SDL_PrivateGameControllerAxis(timestamp, gamecontroller, binding->output.axis.axis, (Sint16)binding->output.axis.axis_max);
} else {
- SDL_PrivateGameControllerButton(gamecontroller, binding->output.button, SDL_PRESSED);
+ SDL_PrivateGameControllerButton(timestamp, gamecontroller, binding->output.button, SDL_PRESSED);
}
} else {
- ResetOutput(gamecontroller, binding);
+ ResetOutput(timestamp, gamecontroller, binding);
}
}
}
@@ -345,18 +345,19 @@ static void RecenterGameController(SDL_GameController *gamecontroller)
{
SDL_GameControllerButton button;
SDL_GameControllerAxis axis;
+ Uint64 timestamp = SDL_GetTicksNS();
CHECK_GAMECONTROLLER_MAGIC(gamecontroller, );
for (button = (SDL_GameControllerButton)0; button < SDL_CONTROLLER_BUTTON_MAX; button++) {
if (SDL_GameControllerGetButton(gamecontroller, button)) {
- SDL_PrivateGameControllerButton(gamecontroller, button, SDL_RELEASED);
+ SDL_PrivateGameControllerButton(timestamp, gamecontroller, button, SDL_RELEASED);
}
}
for (axis = (SDL_GameControllerAxis)0; axis < SDL_CONTROLLER_AXIS_MAX; axis++) {
if (SDL_GameControllerGetAxis(gamecontroller, axis) != 0) {
- SDL_PrivateGameControllerAxis(gamecontroller, axis, 0);
+ SDL_PrivateGameControllerAxis(timestamp, gamecontroller, axis, 0);
}
}
}
@@ -372,7 +373,7 @@ static int SDLCALL SDL_GameControllerEventWatcher(void *userdata, SDL_Event *eve
SDL_GameController *controllerlist = SDL_gamecontrollers;
while (controllerlist) {
if (controllerlist->joystick->instance_id == event->jaxis.which) {
- HandleJoystickAxis(controllerlist, event->jaxis.axis, event->jaxis.value);
+ HandleJoystickAxis(event->common.timestamp, controllerlist, event->jaxis.axis, event->jaxis.value);
break;
}
controllerlist = controllerlist->next;
@@ -384,7 +385,7 @@ static int SDLCALL SDL_GameControllerEventWatcher(void *userdata, SDL_Event *eve
SDL_GameController *controllerlist = SDL_gamecontrollers;
while (controllerlist) {
if (controllerlist->joystick->instance_id == event->jbutton.which) {
- HandleJoystickButton(controllerlist, event->jbutton.button, event->jbutton.state);
+ HandleJoystickButton(event->common.timestamp, controllerlist, event->jbutton.button, event->jbutton.state);
break;
}
controllerlist = controllerlist->next;
@@ -395,7 +396,7 @@ static int SDLCALL SDL_GameControllerEventWatcher(void *userdata, SDL_Event *eve
SDL_GameController *controllerlist = SDL_gamecontrollers;
while (controllerlist) {
if (controllerlist->joystick->instance_id == event->jhat.which) {
- HandleJoystickHat(controllerlist, event->jhat.hat, event->jhat.value);
+ HandleJoystickHat(event->common.timestamp, controllerlist, event->jhat.hat, event->jhat.value);
break;
}
controllerlist = controllerlist->next;
@@ -2857,7 +2858,7 @@ void SDL_GameControllerQuitMappings(void)
/*
* Event filter to transform joystick events into appropriate game controller ones
*/
-static int SDL_PrivateGameControllerAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis, Sint16 value)
+static int SDL_PrivateGameControllerAxis(Uint64 timestamp, SDL_GameController *gamecontroller, SDL_GameControllerAxis axis, Sint16 value)
{
int posted;
@@ -2869,7 +2870,7 @@ static int SDL_PrivateGameControllerAxis(SDL_GameController *gamecontroller, SDL
if (SDL_GetEventState(SDL_CONTROLLERAXISMOTION) == SDL_ENABLE) {
SDL_Event event;
event.type = SDL_CONTROLLERAXISMOTION;
- event.common.timestamp = 0;
+ event.common.timestamp = timestamp;
event.caxis.which = gamecontroller->joystick->instance_id;
event.caxis.axis = axis;
event.caxis.value = value;
@@ -2882,7 +2883,7 @@ static int SDL_PrivateGameControllerAxis(SDL_GameController *gamecontroller, SDL
/*
* Event filter to transform joystick events into appropriate game controller ones
*/
-static int SDL_PrivateGameControllerButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button, Uint8 state)
+static int SDL_PrivateGameControllerButton(Uint64 timestamp, SDL_GameController *gamecontroller, SDL_GameControllerButton button, Uint8 state)
{
int posted;
#if !SDL_EVENTS_DISABLED
@@ -2905,7 +2906,6 @@ static int SDL_PrivateGameControllerButton(SDL_GameController *gamecontroller, S
/* Invalid state -- bail */
return 0;
}
- event.common.timestamp = 0;
#endif /* !SDL_EVENTS_DISABLED */
if (button == SDL_CONTROLLER_BUTTON_GUIDE) {
@@ -2930,6 +2930,7 @@ static int SDL_PrivateGameControllerButton(SDL_GameController *gamecontroller, S
posted = 0;
#if !SDL_EVENTS_DISABLED
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
+ event.common.timestamp = timestamp;
event.cbutton.which = gamecontroller->joystick->instance_id;
event.cbutton.button = button;
event.cbutton.state = state;
@@ -2986,7 +2987,7 @@ void SDL_GameControllerHandleDelayedGuideButton(SDL_Joystick *joystick)
SDL_GameController *controllerlist = SDL_gamecontrollers;
while (controllerlist) {
if (controllerlist->joystick == joystick) {
- SDL_PrivateGameControllerButton(controllerlist, SDL_CONTROLLER_BUTTON_GUIDE, SDL_RELEASED);
+ SDL_PrivateGameControllerButton(0, controllerlist, SDL_CONTROLLER_BUTTON_GUIDE, SDL_RELEASED);
break;
}
controllerlist = controllerlist->next;
diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index d46f32438cce..25bc84109b76 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -1380,29 +1380,30 @@ static void UpdateEventsForDeviceRemoval(int device_index, Uint32 type)
void SDL_PrivateJoystickForceRecentering(SDL_Joystick *joystick)
{
int i, j;
+ Uint64 timestamp = SDL_GetTicksNS();
CHECK_JOYSTICK_MAGIC(joystick, );
/* Tell the app that everything is centered/unpressed... */
for (i = 0; i < joystick->naxes; i++) {
if (joystick->axes[i].has_initial_value) {
- SDL_PrivateJoystickAxis(joystick, i, joystick->axes[i].zero);
+ SDL_PrivateJoystickAxis(timestamp, joystick, i, joystick->axes[i].zero);
}
}
for (i = 0; i < joystick->nbuttons; i++) {
- SDL_PrivateJoystickButton(joystick, i, SDL_RELEASED);
+ SDL_PrivateJoystickButton(timestamp, joystick, i, SDL_RELEASED);
}
for (i = 0; i < joystick->nhats; i++) {
- SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
+ SDL_PrivateJoystickHat(timestamp, joystick, i, SDL_HAT_CENTERED);
}
for (i = 0; i < joystick->ntouchpads; i++) {
SDL_JoystickTouchpadInfo *touchpad = &joystick->touchpads[i];
for (j = 0; j < touchpad->nfingers; ++j) {
- SDL_PrivateJoystickTouchpad(joystick, i, j, SDL_RELEASED, 0.0f, 0.0f, 0.0f);
+ SDL_PrivateJoystickTouchpad(timestamp, joystick, i, j, SDL_RELEASED, 0.0f, 0.0f, 0.0f);
}
}
}
@@ -1449,7 +1450,7 @@ void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
}
}
-int SDL_PrivateJoystickAxis(S
(Patch may be truncated, please check the link at the top of this post.)