Skip to content

Commit

Permalink
Updated raw input events to match SDL style
Browse files Browse the repository at this point in the history
Also added raw keyboard events, and implemented raw input events on iOS, OpenBSD console, Linux console, and X11
  • Loading branch information
slouken committed Dec 21, 2024
1 parent 3ce68f8 commit 5d05caa
Show file tree
Hide file tree
Showing 25 changed files with 516 additions and 313 deletions.
92 changes: 65 additions & 27 deletions include/SDL3/SDL_events.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ typedef enum SDL_EventType
SDL_EVENT_KEYBOARD_ADDED, /**< A new keyboard has been inserted into the system */
SDL_EVENT_KEYBOARD_REMOVED, /**< A keyboard has been removed */
SDL_EVENT_TEXT_EDITING_CANDIDATES, /**< Keyboard text editing candidates */
SDL_EVENT_RAW_KEY_DOWN, /**< Key pressed (raw key press) */
SDL_EVENT_RAW_KEY_UP, /**< Key released (raw key release) */

/* Mouse events */
SDL_EVENT_MOUSE_MOTION = 0x400, /**< Mouse moved */
Expand All @@ -182,9 +184,10 @@ typedef enum SDL_EventType
SDL_EVENT_MOUSE_WHEEL, /**< Mouse wheel motion */
SDL_EVENT_MOUSE_ADDED, /**< A new mouse has been inserted into the system */
SDL_EVENT_MOUSE_REMOVED, /**< A mouse has been removed */
SDL_EVENT_MOUSE_RAW_MOTION, /**< Mouse moved (raw motion deltas) */
SDL_EVENT_MOUSE_RAW_BUTTON, /**< Mouse click (raw button delta) */
SDL_EVENT_MOUSE_RAW_SCROLL, /**< Mouse wheel (raw scroll deltas) */
SDL_EVENT_RAW_MOUSE_MOTION, /**< Mouse moved (raw motion deltas) */
SDL_EVENT_RAW_MOUSE_BUTTON_DOWN, /**< Mouse button pressed (raw button press) */
SDL_EVENT_RAW_MOUSE_BUTTON_UP, /**< Mouse button released (raw button release) */
SDL_EVENT_RAW_MOUSE_WHEEL, /**< Mouse wheel motion (raw wheel deltas) */

/* Joystick events */
SDL_EVENT_JOYSTICK_AXIS_MOTION = 0x600, /**< Joystick axis motion */
Expand Down Expand Up @@ -361,10 +364,26 @@ typedef struct SDL_KeyboardEvent
SDL_Keycode key; /**< SDL virtual key code */
SDL_Keymod mod; /**< current key modifiers */
Uint16 raw; /**< The platform dependent scancode for this event */
bool down; /**< true if the key is pressed */
bool repeat; /**< true if this is a key repeat */
bool down; /**< true if the key is pressed */
bool repeat; /**< true if this is a key repeat */
} SDL_KeyboardEvent;

/**
* Raw keyboard button event structure (event.raw_key.*)
*
* \since This struct is available since SDL 3.1.8.
*/
typedef struct SDL_RawKeyboardEvent
{
SDL_EventType type; /**< SDL_EVENT_RAW_KEY_DOWN or SDL_EVENT_RAW_KEY_UP */
Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_KeyboardID which; /**< The keyboard instance id */
SDL_Scancode scancode; /**< SDL physical key code */
Uint16 raw; /**< The platform dependent scancode for this event */
bool down; /**< true if the key is pressed */
} SDL_RawKeyboardEvent;

/**
* Keyboard text editing event structure (event.edit.*)
*
Expand Down Expand Up @@ -458,21 +477,21 @@ typedef struct SDL_MouseMotionEvent
} SDL_MouseMotionEvent;

/**
* Mouse raw motion and wheel event structure (event.maxis.*)
* Raw mouse motion event structure (event.raw_motion.*)
*
* \since This struct is available since SDL 3.0.0.
* \since This struct is available since SDL 3.1.8.
*/
typedef struct SDL_MouseRawAxisEvent
typedef struct SDL_RawMouseMotionEvent
{
SDL_EventType type; /**< SDL_EVENT_MOUSE_RAW_MOTION or SDL_EVENT_MOUSE_RAW_SCROLL */
SDL_EventType type; /**< SDL_EVENT_RAW_MOUSE_MOTION */
Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */
int dx; /**< The axis delta value in the X direction */
int dy; /**< The axis delta value in the Y direction */
float ux; /**< The denominator unit in the X direction */
float uy; /**< The denominator unit in the Y direction */
} SDL_MouseRawAxisEvent;
SDL_MouseID which; /**< The mouse instance id */
Sint32 dx; /**< X axis delta */
Sint32 dy; /**< Y axis delta */
float scale_x; /**< X value scale to approximate desktop acceleration */
float scale_y; /**< Y value scale to approximate desktop acceleration */
} SDL_RawMouseMotionEvent;

/**
* Mouse button event structure (event.button.*)
Expand All @@ -485,29 +504,29 @@ typedef struct SDL_MouseButtonEvent
Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_WindowID windowID; /**< The window with mouse focus, if any */
SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID */
SDL_MouseID which; /**< The mouse instance id or SDL_TOUCH_MOUSEID */
Uint8 button; /**< The mouse button index */
bool down; /**< true if the button is pressed */
bool down; /**< true if the button is pressed */
Uint8 clicks; /**< 1 for single-click, 2 for double-click, etc. */
Uint8 padding;
float x; /**< X coordinate, relative to window */
float y; /**< Y coordinate, relative to window */
} SDL_MouseButtonEvent;

/**
* Mouse raw button event structure (event.mbutton.*)
* Raw mouse button event structure (event.raw_button.*)
*
* \since This struct is available since SDL 3.0.0.
* \since This struct is available since SDL 3.1.8.
*/
typedef struct SDL_MouseRawButtonEvent
typedef struct SDL_RawMouseButtonEvent
{
SDL_EventType type; /**< SDL_EVENT_MOUSE_RAW_BUTTON */
SDL_EventType type; /**< SDL_EVENT_RAW_MOUSE_BUTTON_DOWN or SDL_EVENT_RAW_MOUSE_BUTTON_UP */
Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */
SDL_MouseID which; /**< The mouse instance id */
Uint8 button; /**< The mouse button index */
Uint8 state; /**< SDL_PRESSED or SDL_RELEASED */
} SDL_MouseRawButtonEvent;
bool down; /**< true if the button is pressed */
} SDL_RawMouseButtonEvent;

/**
* Mouse wheel event structure (event.wheel.*)
Expand All @@ -520,14 +539,31 @@ typedef struct SDL_MouseWheelEvent
Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_WindowID windowID; /**< The window with mouse focus, if any */
SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID */
SDL_MouseID which; /**< The mouse instance id */
float x; /**< The amount scrolled horizontally, positive to the right and negative to the left */
float y; /**< The amount scrolled vertically, positive away from the user and negative toward the user */
SDL_MouseWheelDirection direction; /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */
float mouse_x; /**< X coordinate, relative to window */
float mouse_y; /**< Y coordinate, relative to window */
} SDL_MouseWheelEvent;

/**
* Raw mouse wheel event structure (event.raw_wheel.*)
*
* \since This struct is available since SDL 3.1.3.
*/
typedef struct SDL_RawMouseWheelEvent
{
SDL_EventType type; /**< SDL_EVENT_RAW_MOUSE_WHEEL */
Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_MouseID which; /**< The mouse instance id */
Sint32 dx; /**< X axis delta, positive to the right and negative to the left */
Sint32 dy; /**< Y axis delta, positive away from the user and negative toward the user */
float scale_x; /**< X value scale to convert to logical scroll units */
float scale_y; /**< Y value scale to convert to logical scroll units */
} SDL_RawMouseWheelEvent;

/**
* Joystick axis motion event structure (event.jaxis.*)
*
Expand Down Expand Up @@ -1025,15 +1061,17 @@ typedef union SDL_Event
SDL_WindowEvent window; /**< Window event data */
SDL_KeyboardDeviceEvent kdevice; /**< Keyboard device change event data */
SDL_KeyboardEvent key; /**< Keyboard event data */
SDL_RawKeyboardEvent raw_key; /**< Raw keyboard event data */
SDL_TextEditingEvent edit; /**< Text editing event data */
SDL_TextEditingCandidatesEvent edit_candidates; /**< Text editing candidates event data */
SDL_TextInputEvent text; /**< Text input event data */
SDL_MouseDeviceEvent mdevice; /**< Mouse device change event data */
SDL_MouseMotionEvent motion; /**< Mouse motion event data */
SDL_RawMouseMotionEvent raw_motion; /**< Raw mouse motion event data */
SDL_MouseButtonEvent button; /**< Mouse button event data */
SDL_RawMouseButtonEvent raw_button; /**< Raw mouse button event data */
SDL_MouseWheelEvent wheel; /**< Mouse wheel event data */
SDL_MouseRawAxisEvent maxis; /**< Mouse raw axis event data (motion or wheel deltas) */
SDL_MouseRawButtonEvent mbutton; /**< Mouse raw button event data */
SDL_RawMouseWheelEvent raw_wheel; /**< Raw mouse wheel event data */
SDL_JoyDeviceEvent jdevice; /**< Joystick device change event data */
SDL_JoyAxisEvent jaxis; /**< Joystick axis event data */
SDL_JoyBallEvent jball; /**< Joystick ball event data */
Expand Down
36 changes: 25 additions & 11 deletions src/core/linux/SDL_evdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,10 @@ void SDL_EVDEV_Poll(void)
switch (event->type) {
case EV_KEY:
if (event->code >= BTN_MOUSE && event->code < BTN_MOUSE + SDL_arraysize(EVDEV_MouseButtons)) {
Uint64 timestamp = SDL_EVDEV_GetEventTimestamp(event);
mouse_button = event->code - BTN_MOUSE;
SDL_SendMouseButton(SDL_EVDEV_GetEventTimestamp(event), mouse->focus, (SDL_MouseID)item->fd, EVDEV_MouseButtons[mouse_button], (event->value != 0));
SDL_SendRawMouseButton(timestamp, (SDL_MouseID)item->fd, EVDEV_MouseButtons[mouse_button], (event->value != 0));
SDL_SendMouseButton(timestamp, mouse->focus, (SDL_MouseID)item->fd, EVDEV_MouseButtons[mouse_button], (event->value != 0));
break;
}

Expand All @@ -367,13 +369,18 @@ void SDL_EVDEV_Poll(void)
}

// Probably keyboard
scancode = SDL_EVDEV_translate_keycode(event->code);
if (event->value == 0) {
SDL_SendKeyboardKey(SDL_EVDEV_GetEventTimestamp(event), (SDL_KeyboardID)item->fd, event->code, scancode, false);
} else if (event->value == 1 || event->value == 2 /* key repeated */) {
SDL_SendKeyboardKey(SDL_EVDEV_GetEventTimestamp(event), (SDL_KeyboardID)item->fd, event->code, scancode, true);
{
Uint64 timestamp = SDL_EVDEV_GetEventTimestamp(event);
scancode = SDL_EVDEV_translate_keycode(event->code);
if (event->value == 0) {
SDL_SendRawKeyboardKey(timestamp, (SDL_KeyboardID)item->fd, event->code, scancode, false);
SDL_SendKeyboardKey(timestamp, (SDL_KeyboardID)item->fd, event->code, scancode, false);
} else if (event->value == 1 || event->value == 2 /* key repeated */) {
SDL_SendRawKeyboardKey(timestamp, (SDL_KeyboardID)item->fd, event->code, scancode, true);
SDL_SendKeyboardKey(timestamp, (SDL_KeyboardID)item->fd, event->code, scancode, true);
}
SDL_EVDEV_kbd_keycode(_this->kbd, event->code, event->value);
}
SDL_EVDEV_kbd_keycode(_this->kbd, event->code, event->value);
break;
case EV_ABS:
switch (event->code) {
Expand Down Expand Up @@ -485,7 +492,9 @@ void SDL_EVDEV_Poll(void)
// Send mouse axis changes together to ensure consistency and reduce event processing overhead
if (item->relative_mouse) {
if (item->mouse_x != 0 || item->mouse_y != 0) {
SDL_SendMouseMotion(SDL_EVDEV_GetEventTimestamp(event), mouse->focus, (SDL_MouseID)item->fd, item->relative_mouse, (float)item->mouse_x, (float)item->mouse_y);
Uint64 timestamp = SDL_EVDEV_GetEventTimestamp(event);
SDL_SendRawMouseMotion(timestamp, (SDL_MouseID)item->fd, item->mouse_x, item->mouse_y, 1.0f, 1.0f);
SDL_SendMouseMotion(timestamp, mouse->focus, (SDL_MouseID)item->fd, item->relative_mouse, (float)item->mouse_x, (float)item->mouse_y);
item->mouse_x = item->mouse_y = 0;
}
} else if (item->range_x > 0 && item->range_y > 0) {
Expand All @@ -508,10 +517,15 @@ void SDL_EVDEV_Poll(void)
}

if (item->mouse_wheel != 0 || item->mouse_hwheel != 0) {
SDL_SendMouseWheel(SDL_EVDEV_GetEventTimestamp(event),
Uint64 timestamp = SDL_EVDEV_GetEventTimestamp(event);
const float scale = (item->high_res_hwheel ? 1.0f / 120.0f : 1.0f);
SDL_SendRawMouseWheel(timestamp,
(SDL_MouseID)item->fd,
item->mouse_hwheel, item->mouse_wheel, scale, scale);
SDL_SendMouseWheel(timestamp,
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),
item->mouse_hwheel * scale,
item->mouse_wheel * scale,
SDL_MOUSEWHEEL_NORMAL);
item->mouse_wheel = item->mouse_hwheel = 0;
}
Expand Down
40 changes: 28 additions & 12 deletions src/core/openbsd/SDL_wscons_kbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ static void Translate_to_text(SDL_WSCONS_input_data *input, keysym_t ksym)
}
}

static void Translate_to_keycode(SDL_WSCONS_input_data *input, int type, keysym_t ksym)
static void Translate_to_keycode(SDL_WSCONS_input_data *input, int type, keysym_t ksym, Uint64 timestamp)
{
struct wscons_keymap keyDesc = input->keymap.map[ksym];
keysym_t *group = &keyDesc.group1[KS_GROUP(keyDesc.group1[0]) == KS_GROUP_Keypad && IS_NUMLOCK_ON ? !IS_SHIFT_HELD : 0];
Expand All @@ -560,22 +560,32 @@ static void Translate_to_keycode(SDL_WSCONS_input_data *input, int type, keysym_
switch (keyDesc.command) {
case KS_Cmd_ScrollBack:
{
SDL_SendKeyboardKey(0, input->keyboardID, 0, SDL_SCANCODE_PAGEUP, (type == WSCONS_EVENT_KEY_DOWN));
SDL_SendKeyboardKey(timestamp, input->keyboardID, 0, SDL_SCANCODE_PAGEUP, (type == WSCONS_EVENT_KEY_DOWN));
return;
}
case KS_Cmd_ScrollFwd:
{
SDL_SendKeyboardKey(0, input->keyboardID, 0, SDL_SCANCODE_PAGEDOWN, (type == WSCONS_EVENT_KEY_DOWN));
SDL_SendKeyboardKey(timestamp, input->keyboardID, 0, SDL_SCANCODE_PAGEDOWN, (type == WSCONS_EVENT_KEY_DOWN));
return;
}
default:
break;
}
for (i = 0; i < sizeof(conversion_table) / sizeof(struct wscons_keycode_to_SDL); i++) {
for (i = 0; i < SDL_arraysize(conversion_table); i++) {
if (conversion_table[i].sourcekey == group[0]) {
SDL_SendKeyboardKey(0, input->keyboardID, group[0], conversion_table[i].targetKey, (type == WSCONS_EVENT_KEY_DOWN));
SDL_SendRawKeyboardKey(timestamp, input->keyboardID, group[0], conversion_table[i].targetKey, (type == WSCONS_EVENT_KEY_DOWN));
SDL_SendKeyboardKey(timestamp, input->keyboardID, group[0], conversion_table[i].targetKey, (type == WSCONS_EVENT_KEY_DOWN));
return;
}
}
SDL_SendKeyboardKey(0, input->keyboardID, group[0], SDL_SCANCODE_UNKNOWN, (type == WSCONS_EVENT_KEY_DOWN));
SDL_SendRawKeyboardKey(timestamp, input->keyboardID, group[0], SDL_SCANCODE_UNKNOWN, (type == WSCONS_EVENT_KEY_DOWN));
SDL_SendKeyboardKey(timestamp, input->keyboardID, group[0], SDL_SCANCODE_UNKNOWN, (type == WSCONS_EVENT_KEY_DOWN));
}

static Uint64 GetEventTimestamp(struct timespec *time)
{
// FIXME: Get the event time in the SDL tick time base
return SDL_GetTicksNS();
}

static void updateKeyboard(SDL_WSCONS_input_data *input)
Expand All @@ -592,6 +602,7 @@ static void updateKeyboard(SDL_WSCONS_input_data *input)
if ((n = read(input->fd, events, sizeof(events))) > 0) {
n /= sizeof(struct wscons_event);
for (i = 0; i < n; i++) {
Uint64 timestamp = GetEventTimestamp(&events[i].time);
type = events[i].type;
switch (type) {
case WSCONS_EVENT_KEY_DOWN:
Expand Down Expand Up @@ -809,15 +820,20 @@ static void updateKeyboard(SDL_WSCONS_input_data *input)
} break;
case WSCONS_EVENT_ALL_KEYS_UP:
for (i = 0; i < SDL_SCANCODE_COUNT; i++) {
SDL_SendKeyboardKey(0, input->keyboardID, 0, (SDL_Scancode)i, false);
SDL_SendRawKeyboardKey(timestamp, input->keyboardID, 0, (SDL_Scancode)i, false);
SDL_SendKeyboardKey(timestamp, input->keyboardID, 0, (SDL_Scancode)i, false);
}
break;
default:
break;
}

if (input->type == WSKBD_TYPE_USB && events[i].value <= 0xE7)
SDL_SendKeyboardKey(0, input->keyboardID, 0, (SDL_Scancode)events[i].value, (type == WSCONS_EVENT_KEY_DOWN));
else
Translate_to_keycode(input, type, events[i].value);
if (input->type == WSKBD_TYPE_USB && events[i].value <= 0xE7) {
SDL_SendRawKeyboardKey(timestamp, input->keyboardID, 0, (SDL_Scancode)events[i].value, (type == WSCONS_EVENT_KEY_DOWN));
SDL_SendKeyboardKey(timestamp, input->keyboardID, 0, (SDL_Scancode)events[i].value, (type == WSCONS_EVENT_KEY_DOWN));
} else {
Translate_to_keycode(input, type, events[i].value, timestamp);
}

if (type == WSCONS_EVENT_KEY_UP) {
continue;
Expand Down Expand Up @@ -910,7 +926,7 @@ static void updateKeyboard(SDL_WSCONS_input_data *input)
}
if (IS_ALT_HELD) {
if (input->encoding & KB_METAESC) {
Translate_to_keycode(input, WSCONS_EVENT_KEY_DOWN, KS_Escape);
Translate_to_keycode(input, WSCONS_EVENT_KEY_DOWN, KS_Escape, 0);
Translate_to_text(input, result);
continue;
} else {
Expand Down
Loading

0 comments on commit 5d05caa

Please sign in to comment.