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.
This commit is contained in:
Sam Lantinga
2022-12-03 11:15:50 -08:00
parent f32cdfa096
commit 73f4aeee6a
36 changed files with 950 additions and 839 deletions

View File

@@ -986,6 +986,7 @@ static void UpdateDINPUTJoystickState_Polled(SDL_Joystick *joystick)
DIJOYSTATE2 state;
HRESULT result;
int i;
Uint64 timestamp = SDL_GetTicksNS();
result =
IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice,
@@ -1009,40 +1010,40 @@ static void UpdateDINPUTJoystickState_Polled(SDL_Joystick *joystick)
case AXIS:
switch (in->ofs) {
case DIJOFS_X:
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lX);
SDL_PrivateJoystickAxis(timestamp, joystick, in->num, (Sint16)state.lX);
break;
case DIJOFS_Y:
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lY);
SDL_PrivateJoystickAxis(timestamp, joystick, in->num, (Sint16)state.lY);
break;
case DIJOFS_Z:
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lZ);
SDL_PrivateJoystickAxis(timestamp, joystick, in->num, (Sint16)state.lZ);
break;
case DIJOFS_RX:
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRx);
SDL_PrivateJoystickAxis(timestamp, joystick, in->num, (Sint16)state.lRx);
break;
case DIJOFS_RY:
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRy);
SDL_PrivateJoystickAxis(timestamp, joystick, in->num, (Sint16)state.lRy);
break;
case DIJOFS_RZ:
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRz);
SDL_PrivateJoystickAxis(timestamp, joystick, in->num, (Sint16)state.lRz);
break;
case DIJOFS_SLIDER(0):
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[0]);
SDL_PrivateJoystickAxis(timestamp, joystick, in->num, (Sint16)state.rglSlider[0]);
break;
case DIJOFS_SLIDER(1):
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[1]);
SDL_PrivateJoystickAxis(timestamp, joystick, in->num, (Sint16)state.rglSlider[1]);
break;
}
break;
case BUTTON:
SDL_PrivateJoystickButton(joystick, in->num,
SDL_PrivateJoystickButton(timestamp, joystick, in->num,
(Uint8)(state.rgbButtons[in->ofs - DIJOFS_BUTTON0] ? SDL_PRESSED : SDL_RELEASED));
break;
case HAT:
{
Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]);
SDL_PrivateJoystickHat(joystick, in->num, pos);
SDL_PrivateJoystickHat(timestamp, joystick, in->num, pos);
break;
}
}
@@ -1055,6 +1056,7 @@ static void UpdateDINPUTJoystickState_Buffered(SDL_Joystick *joystick)
HRESULT result;
DWORD numevents;
DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
Uint64 timestamp = SDL_GetTicksNS();
numevents = INPUT_QSIZE;
result =
@@ -1086,16 +1088,16 @@ static void UpdateDINPUTJoystickState_Buffered(SDL_Joystick *joystick)
switch (in->type) {
case AXIS:
SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)evtbuf[i].dwData);
SDL_PrivateJoystickAxis(timestamp, joystick, in->num, (Sint16)evtbuf[i].dwData);
break;
case BUTTON:
SDL_PrivateJoystickButton(joystick, in->num,
SDL_PrivateJoystickButton(timestamp, joystick, in->num,
(Uint8)(evtbuf[i].dwData ? SDL_PRESSED : SDL_RELEASED));
break;
case HAT:
{
Uint8 pos = TranslatePOV(evtbuf[i].dwData);
SDL_PrivateJoystickHat(joystick, in->num, pos);
SDL_PrivateJoystickHat(timestamp, joystick, in->num, pos);
} break;
}
}

View File

@@ -1399,22 +1399,22 @@ static void RAWINPUT_HandleStatePacket(SDL_Joystick *joystick, Uint8 *data, int
};
Uint64 match_state = ctx->match_state;
/* Update match_state with button bit, then fall through */
#define SDL_PrivateJoystickButton(joystick, button, state) \
#define SDL_PrivateJoystickButton(timestamp, joystick, button, state) \
if (button < SDL_arraysize(button_map)) { \
Uint64 button_bit = 1ull << button_map[button]; \
match_state = (match_state & ~button_bit) | (button_bit * (state)); \
} \
SDL_PrivateJoystickButton(joystick, button, state)
SDL_PrivateJoystickButton(timestamp, joystick, button, state)
#ifdef SDL_JOYSTICK_RAWINPUT_MATCH_AXES
/* Grab high 4 bits of value, then fall through */
#define AddAxisToMatchState(axis, value) \
{ \
match_state = (match_state & ~(0xFull << (4 * axis + 16))) | ((value)&0xF000ull) << (4 * axis + 4); \
}
#define SDL_PrivateJoystickAxis(joystick, axis, value) \
#define SDL_PrivateJoystickAxis(timestamp, joystick, axis, value) \
if (axis < 4) \
AddAxisToMatchState(axis, value); \
SDL_PrivateJoystickAxis(joystick, axis, value)
SDL_PrivateJoystickAxis(timestamp, joystick, axis, value)
#endif
#endif /* SDL_JOYSTICK_RAWINPUT_MATCHING */
@@ -1424,6 +1424,7 @@ static void RAWINPUT_HandleStatePacket(SDL_Joystick *joystick, Uint8 *data, int
int naxes = joystick->naxes - (ctx->trigger_hack * 2);
int nhats = joystick->nhats;
Uint32 button_mask = 0;
Uint64 timestamp = SDL_GetTicksNS();
if (SDL_HidP_GetData(HidP_Input, ctx->data, &data_length, ctx->preparsed_data, (PCHAR)data, size) != HIDP_STATUS_SUCCESS) {
return;
@@ -1436,14 +1437,14 @@ static void RAWINPUT_HandleStatePacket(SDL_Joystick *joystick, Uint8 *data, int
}
}
for (i = 0; i < nbuttons; ++i) {
SDL_PrivateJoystickButton(joystick, i, (button_mask & (1 << i)) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(timestamp, joystick, i, (button_mask & (1 << i)) ? SDL_PRESSED : SDL_RELEASED);
}
for (i = 0; i < naxes; ++i) {
HIDP_DATA *item = GetData(ctx->axis_indices[i], ctx->data, data_length);
if (item) {
Sint16 axis = (int)(Uint16)item->RawValue - 0x8000;
SDL_PrivateJoystickAxis(joystick, i, axis);
SDL_PrivateJoystickAxis(timestamp, joystick, i, axis);
}
}
@@ -1467,7 +1468,7 @@ static void RAWINPUT_HandleStatePacket(SDL_Joystick *joystick, Uint8 *data, int
#ifdef SDL_JOYSTICK_RAWINPUT_MATCHING
match_state = (match_state & ~HAT_MASK) | hat_map[state];
#endif
SDL_PrivateJoystickHat(joystick, i, hat_states[state]);
SDL_PrivateJoystickHat(timestamp, joystick, i, hat_states[state]);
}
}
}
@@ -1521,8 +1522,8 @@ static void RAWINPUT_HandleStatePacket(SDL_Joystick *joystick, Uint8 *data, int
if (!has_trigger_data)
#endif /* SDL_JOYSTICK_RAWINPUT_MATCH_TRIGGERS */
{
SDL_PrivateJoystickAxis(joystick, left_trigger, left_value);
SDL_PrivateJoystickAxis(joystick, right_trigger, right_value);
SDL_PrivateJoystickAxis(timestamp, joystick, left_trigger, left_value);
SDL_PrivateJoystickAxis(timestamp, joystick, right_trigger, right_value);
}
}
}
@@ -1590,7 +1591,7 @@ static void RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
/* It gets left down if we were actually correlated incorrectly and it was released on the WindowsGamingInput
device but we didn't get a state packet. */
if (ctx->guide_hack) {
SDL_PrivateJoystickButton(joystick, guide_button, SDL_RELEASED);
SDL_PrivateJoystickButton(0, joystick, guide_button, SDL_RELEASED);
}
}
}
@@ -1686,7 +1687,7 @@ static void RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
/* It gets left down if we were actually correlated incorrectly and it was released on the XInput
device but we didn't get a state packet. */
if (ctx->guide_hack) {
SDL_PrivateJoystickButton(joystick, guide_button, SDL_RELEASED);
SDL_PrivateJoystickButton(0, joystick, guide_button, SDL_RELEASED);
}
}
}
@@ -1749,13 +1750,18 @@ static void RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
RAWINPUT_UpdateXInput();
if (xinput_state[ctx->xinput_slot].connected) {
XINPUT_BATTERY_INFORMATION_EX *battery_info = &xinput_state[ctx->xinput_slot].battery;
Uint64 timestamp;
if (ctx->guide_hack || ctx->trigger_hack) {
timestamp = SDL_GetTicksNS();
}
if (ctx->guide_hack) {
SDL_PrivateJoystickButton(joystick, guide_button, (xinput_state[ctx->xinput_slot].state.Gamepad.wButtons & XINPUT_GAMEPAD_GUIDE) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(timestamp, joystick, guide_button, (xinput_state[ctx->xinput_slot].state.Gamepad.wButtons & XINPUT_GAMEPAD_GUIDE) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->trigger_hack) {
SDL_PrivateJoystickAxis(joystick, left_trigger, ((int)xinput_state[ctx->xinput_slot].state.Gamepad.bLeftTrigger * 257) - 32768);
SDL_PrivateJoystickAxis(joystick, right_trigger, ((int)xinput_state[ctx->xinput_slot].state.Gamepad.bRightTrigger * 257) - 32768);
SDL_PrivateJoystickAxis(timestamp, joystick, left_trigger, ((int)xinput_state[ctx->xinput_slot].state.Gamepad.bLeftTrigger * 257) - 32768);
SDL_PrivateJoystickAxis(timestamp, joystick, right_trigger, ((int)xinput_state[ctx->xinput_slot].state.Gamepad.bRightTrigger * 257) - 32768);
}
has_trigger_data = SDL_TRUE;
@@ -1792,13 +1798,18 @@ static void RAWINPUT_UpdateOtherAPIs(SDL_Joystick *joystick)
RAWINPUT_UpdateWindowsGamingInput(); /* May detect disconnect / cause uncorrelation */
if (ctx->wgi_correlated) { /* Still connected */
struct __x_ABI_CWindows_CGaming_CInput_CGamepadReading *state = &ctx->wgi_slot->state;
Uint64 timestamp;
if (ctx->guide_hack || ctx->trigger_hack) {
timestamp = SDL_GetTicksNS();
}
if (ctx->guide_hack) {
SDL_PrivateJoystickButton(joystick, guide_button, (state->Buttons & GamepadButtons_GUIDE) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(timestamp, joystick, guide_button, (state->Buttons & GamepadButtons_GUIDE) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->trigger_hack) {
SDL_PrivateJoystickAxis(joystick, left_trigger, ((int)(state->LeftTrigger * SDL_MAX_UINT16)) - 32768);
SDL_PrivateJoystickAxis(joystick, right_trigger, ((int)(state->RightTrigger * SDL_MAX_UINT16)) - 32768);
SDL_PrivateJoystickAxis(timestamp, joystick, left_trigger, ((int)(state->LeftTrigger * SDL_MAX_UINT16)) - 32768);
SDL_PrivateJoystickAxis(timestamp, joystick, right_trigger, ((int)(state->RightTrigger * SDL_MAX_UINT16)) - 32768);
}
has_trigger_data = SDL_TRUE;
}

View File

@@ -835,6 +835,8 @@ static void WGI_JoystickUpdate(SDL_Joystick *joystick)
UINT32 i;
SDL_bool all_zero = SDL_TRUE;
hwdata->timestamp = timestamp;
/* The axes are all zero when the application loses focus */
for (i = 0; i < naxes; ++i) {
if (axes[i] != 0.0f) {
@@ -845,17 +847,18 @@ static void WGI_JoystickUpdate(SDL_Joystick *joystick)
if (all_zero) {
SDL_PrivateJoystickForceRecentering(joystick);
} else {
/* FIXME: What units are the timestamp we get from GetCurrentReading()? */
timestamp = SDL_GetTicksNS();
for (i = 0; i < nbuttons; ++i) {
SDL_PrivateJoystickButton(joystick, (Uint8)i, buttons[i]);
SDL_PrivateJoystickButton(timestamp, joystick, (Uint8)i, buttons[i]);
}
for (i = 0; i < nhats; ++i) {
SDL_PrivateJoystickHat(joystick, (Uint8)i, ConvertHatValue(hats[i]));
SDL_PrivateJoystickHat(timestamp, joystick, (Uint8)i, ConvertHatValue(hats[i]));
}
for (i = 0; i < naxes; ++i) {
SDL_PrivateJoystickAxis(joystick, (Uint8)i, (Sint16)((int)(axes[i] * 65535) - 32768));
SDL_PrivateJoystickAxis(timestamp, joystick, (Uint8)i, (Sint16)((int)(axes[i] * 65535) - 32768));
}
}
hwdata->timestamp = timestamp;
}
SDL_stack_free(buttons);

View File

@@ -424,16 +424,17 @@ static void UpdateXInputJoystickState_OLD(SDL_Joystick *joystick, XINPUT_STATE_E
};
WORD wButtons = pXInputState->Gamepad.wButtons;
Uint8 button;
Uint64 timestamp = SDL_GetTicksNS();
SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX);
SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY)));
SDL_PrivateJoystickAxis(joystick, 2, (Sint16)pXInputState->Gamepad.sThumbRX);
SDL_PrivateJoystickAxis(joystick, 3, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY)));
SDL_PrivateJoystickAxis(joystick, 4, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger * 65535 / 255) - 32768));
SDL_PrivateJoystickAxis(joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger * 65535 / 255) - 32768));
SDL_PrivateJoystickAxis(timestamp, joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX);
SDL_PrivateJoystickAxis(timestamp, joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY)));
SDL_PrivateJoystickAxis(timestamp, joystick, 2, (Sint16)pXInputState->Gamepad.sThumbRX);
SDL_PrivateJoystickAxis(timestamp, joystick, 3, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY)));
SDL_PrivateJoystickAxis(timestamp, joystick, 4, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger * 65535 / 255) - 32768));
SDL_PrivateJoystickAxis(timestamp, joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger * 65535 / 255) - 32768));
for (button = 0; button < (Uint8)SDL_arraysize(s_XInputButtons); ++button) {
SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(timestamp, joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
}
UpdateXInputJoystickBatteryInformation(joystick, pBatteryInformation);
@@ -450,16 +451,17 @@ static void UpdateXInputJoystickState(SDL_Joystick *joystick, XINPUT_STATE_EX *p
WORD wButtons = pXInputState->Gamepad.wButtons;
Uint8 button;
Uint8 hat = SDL_HAT_CENTERED;
Uint64 timestamp = SDL_GetTicksNS();
SDL_PrivateJoystickAxis(joystick, 0, pXInputState->Gamepad.sThumbLX);
SDL_PrivateJoystickAxis(joystick, 1, ~pXInputState->Gamepad.sThumbLY);
SDL_PrivateJoystickAxis(joystick, 2, ((int)pXInputState->Gamepad.bLeftTrigger * 257) - 32768);
SDL_PrivateJoystickAxis(joystick, 3, pXInputState->Gamepad.sThumbRX);
SDL_PrivateJoystickAxis(joystick, 4, ~pXInputState->Gamepad.sThumbRY);
SDL_PrivateJoystickAxis(joystick, 5, ((int)pXInputState->Gamepad.bRightTrigger * 257) - 32768);
SDL_PrivateJoystickAxis(timestamp, joystick, 0, pXInputState->Gamepad.sThumbLX);
SDL_PrivateJoystickAxis(timestamp, joystick, 1, ~pXInputState->Gamepad.sThumbLY);
SDL_PrivateJoystickAxis(timestamp, joystick, 2, ((int)pXInputState->Gamepad.bLeftTrigger * 257) - 32768);
SDL_PrivateJoystickAxis(timestamp, joystick, 3, pXInputState->Gamepad.sThumbRX);
SDL_PrivateJoystickAxis(timestamp, joystick, 4, ~pXInputState->Gamepad.sThumbRY);
SDL_PrivateJoystickAxis(timestamp, joystick, 5, ((int)pXInputState->Gamepad.bRightTrigger * 257) - 32768);
for (button = 0; button < (Uint8)SDL_arraysize(s_XInputButtons); ++button) {
SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(timestamp, joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
}
if (wButtons & XINPUT_GAMEPAD_DPAD_UP) {
@@ -474,7 +476,7 @@ static void UpdateXInputJoystickState(SDL_Joystick *joystick, XINPUT_STATE_EX *p
if (wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) {
hat |= SDL_HAT_RIGHT;
}
SDL_PrivateJoystickHat(joystick, 0, hat);
SDL_PrivateJoystickHat(timestamp, joystick, 0, hat);
UpdateXInputJoystickBatteryInformation(joystick, pBatteryInformation);
}