mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-07 20:08:13 +00:00
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:
@@ -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: */
|
||||
|
Reference in New Issue
Block a user