diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 4cc18cd641ea67..27da4b4eaf9c7e 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -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 */ @@ -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 */ @@ -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.*) * @@ -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.*) @@ -485,9 +504,9 @@ 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 */ @@ -495,19 +514,19 @@ typedef struct SDL_MouseButtonEvent } 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.*) @@ -520,7 +539,7 @@ 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 */ @@ -528,6 +547,23 @@ typedef struct SDL_MouseWheelEvent 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.*) * @@ -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 */ diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c index e655eea6ef0f15..bdeadec9773da1 100644 --- a/src/core/linux/SDL_evdev.c +++ b/src/core/linux/SDL_evdev.c @@ -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; } @@ -367,11 +369,14 @@ void SDL_EVDEV_Poll(void) } // Probably keyboard + Uint64 timestamp = SDL_EVDEV_GetEventTimestamp(event); 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); + 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_SendKeyboardKey(SDL_EVDEV_GetEventTimestamp(event), (SDL_KeyboardID)item->fd, event->code, scancode, true); + 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); break; @@ -485,7 +490,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) { @@ -508,10 +515,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; } diff --git a/src/core/openbsd/SDL_wscons_kbd.c b/src/core/openbsd/SDL_wscons_kbd.c index 79566ef5b0bd74..b8d9ef6e964fc0 100644 --- a/src/core/openbsd/SDL_wscons_kbd.c +++ b/src/core/openbsd/SDL_wscons_kbd.c @@ -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]; @@ -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) @@ -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: @@ -809,15 +820,19 @@ 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)); + 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); + Translate_to_keycode(input, type, events[i].value, timestamp); if (type == WSCONS_EVENT_KEY_UP) { continue; diff --git a/src/core/openbsd/SDL_wscons_mouse.c b/src/core/openbsd/SDL_wscons_mouse.c index 5ba7a5007bb128..de0faca1f9118e 100644 --- a/src/core/openbsd/SDL_wscons_mouse.c +++ b/src/core/openbsd/SDL_wscons_mouse.c @@ -63,6 +63,12 @@ SDL_WSCONS_mouse_input_data *SDL_WSCONS_Init_Mouse(void) return input; } +static Uint64 GetEventTimestamp(struct timespec *time) +{ + // FIXME: Get the event time in the SDL tick time base + return SDL_GetTicksNS(); +} + void updateMouse(SDL_WSCONS_mouse_input_data *input) { struct wscons_event events[64]; @@ -73,56 +79,44 @@ void updateMouse(SDL_WSCONS_mouse_input_data *input) int i; n /= sizeof(struct wscons_event); for (i = 0; i < n; i++) { + Uint64 timestamp = GetEventTimestamp(&events[i].time); int type = events[i].type; switch (type) { case WSCONS_EVENT_MOUSE_DOWN: - { - switch (events[i].value) { - case 0: // Left Mouse Button. - SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_BUTTON_LEFT, true); - break; - case 1: // Middle Mouse Button. - SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_BUTTON_MIDDLE, true); - break; - case 2: // Right Mouse Button. - SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_BUTTON_RIGHT, true); - break; - } - } break; case WSCONS_EVENT_MOUSE_UP: { - switch (events[i].value) { - case 0: // Left Mouse Button. - SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_BUTTON_LEFT, false); - break; - case 1: // Middle Mouse Button. - SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_BUTTON_MIDDLE, false); - break; - case 2: // Right Mouse Button. - SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_BUTTON_RIGHT, false); - break; - } - } break; + Uint8 button = SDL_BUTTON_LEFT + events[i].value; + bool down = (type == WSCONS_EVENT_MOUSE_DOWN); + SDL_SendRawMouseButton(timestamp, input->mouseID, button, down); + SDL_SendMouseButton(timestamp, mouse->focus, input->mouseID, button, down); + break; + } case WSCONS_EVENT_MOUSE_DELTA_X: { - SDL_SendMouseMotion(0, mouse->focus, input->mouseID, 1, (float)events[i].value, 0.0f); + SDL_SendRawMouseMotion(timestamp, input->mouseID, events[i].value, 0, 1.0f, 1.0f); + SDL_SendMouseMotion(timestamp, mouse->focus, input->mouseID, true, (float)events[i].value, 0.0f); break; } case WSCONS_EVENT_MOUSE_DELTA_Y: { - SDL_SendMouseMotion(0, mouse->focus, input->mouseID, 1, 0.0f, -(float)events[i].value); + SDL_SendRawMouseMotion(timestamp, input->mouseID, 0, -events[i].value, 1.0f, 1.0f); + SDL_SendMouseMotion(timestamp, mouse->focus, input->mouseID, true, 0.0f, -(float)events[i].value); break; } case WSCONS_EVENT_MOUSE_DELTA_W: { - SDL_SendMouseWheel(0, mouse->focus, input->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL); + SDL_SendRawMouseWheel(timestamp, input->mouseID, events[i].value, 0, 1.0f, 1.0f); + SDL_SendMouseWheel(timestamp, mouse->focus, input->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL); break; } case WSCONS_EVENT_MOUSE_DELTA_Z: { - SDL_SendMouseWheel(0, mouse->focus, input->mouseID, 0, -events[i].value, SDL_MOUSEWHEEL_NORMAL); + SDL_SendRawMouseWheel(timestamp, input->mouseID, 0, -events[i].value, 1.0f, 1.0f); + SDL_SendMouseWheel(timestamp, mouse->focus, input->mouseID, 0, -events[i].value, SDL_MOUSEWHEEL_NORMAL); break; } + default: + break; } } } diff --git a/src/events/SDL_categories.c b/src/events/SDL_categories.c index 5f0853476f3aca..283c5e0680e9b3 100644 --- a/src/events/SDL_categories.c +++ b/src/events/SDL_categories.c @@ -62,6 +62,8 @@ SDL_EventCategory SDL_GetEventCategory(Uint32 type) case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_UP: + case SDL_EVENT_RAW_KEY_DOWN: + case SDL_EVENT_RAW_KEY_UP: return SDL_EVENTCATEGORY_KEY; case SDL_EVENT_TEXT_EDITING: @@ -78,13 +80,17 @@ SDL_EventCategory SDL_GetEventCategory(Uint32 type) return SDL_EVENTCATEGORY_EDIT_CANDIDATES; case SDL_EVENT_MOUSE_MOTION: + case SDL_EVENT_RAW_MOUSE_MOTION: return SDL_EVENTCATEGORY_MOTION; case SDL_EVENT_MOUSE_BUTTON_DOWN: case SDL_EVENT_MOUSE_BUTTON_UP: + case SDL_EVENT_RAW_MOUSE_BUTTON_DOWN: + case SDL_EVENT_RAW_MOUSE_BUTTON_UP: return SDL_EVENTCATEGORY_BUTTON; case SDL_EVENT_MOUSE_WHEEL: + case SDL_EVENT_RAW_MOUSE_WHEEL: return SDL_EVENTCATEGORY_WHEEL; case SDL_EVENT_MOUSE_ADDED: diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index c68dbc126cbd7e..33d7999e3255cf 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -390,7 +390,7 @@ static void SDL_LogEvent(const SDL_Event *event) // sensor/mouse/pen/finger motion are spammy, ignore these if they aren't demanded. if ((SDL_EventLoggingVerbosity < 2) && ((event->type == SDL_EVENT_MOUSE_MOTION) || - (event->type == SDL_EVENT_MOUSE_RAW_MOTION) || + (event->type == SDL_EVENT_RAW_MOUSE_MOTION) || (event->type == SDL_EVENT_FINGER_MOTION) || (event->type == SDL_EVENT_PEN_AXIS) || (event->type == SDL_EVENT_PEN_MOTION) || @@ -535,6 +535,19 @@ static void SDL_LogEvent(const SDL_Event *event) break; #undef PRINT_KEY_EVENT +#define PRINT_RAW_KEY_EVENT(event) \ + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u state=%s scancode=%u)", \ + (uint)event->raw_key.timestamp, (uint)event->raw_key.which, \ + event->raw_key.down ? "pressed" : "released", \ + (uint)event->raw_key.scancode); + SDL_EVENT_CASE(SDL_EVENT_RAW_KEY_DOWN) + PRINT_RAW_KEY_EVENT(event); + break; + SDL_EVENT_CASE(SDL_EVENT_RAW_KEY_UP) + PRINT_RAW_KEY_EVENT(event); + break; +#undef PRINT_RAW_KEY_EVENT + SDL_EVENT_CASE(SDL_EVENT_TEXT_EDITING) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u text='%s' start=%d length=%d)", (uint)event->edit.timestamp, (uint)event->edit.windowID, @@ -568,11 +581,18 @@ static void SDL_LogEvent(const SDL_Event *event) event->motion.xrel, event->motion.yrel); break; + SDL_EVENT_CASE(SDL_EVENT_RAW_MOUSE_MOTION) + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u dx=%d dy=%d)", + (uint)event->raw_motion.timestamp, + (uint)event->raw_motion.which, + (int)event->raw_motion.dx, (int)event->raw_motion.dy); + break; + #define PRINT_MBUTTON_EVENT(event) \ (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u button=%u state=%s clicks=%u x=%g y=%g)", \ (uint)event->button.timestamp, (uint)event->button.windowID, \ (uint)event->button.which, (uint)event->button.button, \ - event->button.down ? "pressed" : "released", \ + event->button.down ? "pressed" : "released", \ (uint)event->button.clicks, event->button.x, event->button.y) SDL_EVENT_CASE(SDL_EVENT_MOUSE_BUTTON_DOWN) PRINT_MBUTTON_EVENT(event); @@ -582,6 +602,19 @@ static void SDL_LogEvent(const SDL_Event *event) break; #undef PRINT_MBUTTON_EVENT +#define PRINT_RAW_MBUTTON_EVENT(event) \ + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u button=%u state=%s)", \ + (uint)event->raw_button.timestamp, \ + (uint)event->raw_button.which, (uint)event->raw_button.button, \ + event->raw_button.down ? "pressed" : "released"); + SDL_EVENT_CASE(SDL_EVENT_RAW_MOUSE_BUTTON_DOWN) + PRINT_RAW_MBUTTON_EVENT(event); + break; + SDL_EVENT_CASE(SDL_EVENT_RAW_MOUSE_BUTTON_UP) + PRINT_RAW_MBUTTON_EVENT(event); + break; +#undef PRINT_RAW_MBUTTON_EVENT + SDL_EVENT_CASE(SDL_EVENT_MOUSE_WHEEL) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u x=%g y=%g direction=%s)", (uint)event->wheel.timestamp, (uint)event->wheel.windowID, @@ -589,6 +622,13 @@ static void SDL_LogEvent(const SDL_Event *event) event->wheel.direction == SDL_MOUSEWHEEL_NORMAL ? "normal" : "flipped"); break; + SDL_EVENT_CASE(SDL_EVENT_RAW_MOUSE_WHEEL) + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u dx=%d dy=%d)", + (uint)event->raw_wheel.timestamp, + (uint)event->raw_wheel.which, + (int)event->raw_wheel.dx, (int)event->raw_wheel.dy); + break; + SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_AXIS_MOTION) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d axis=%u value=%d)", (uint)event->jaxis.timestamp, (int)event->jaxis.which, @@ -1890,12 +1930,6 @@ void SDL_SetEventEnabled(Uint32 type, bool enabled) if (type == SDL_EVENT_DROP_FILE || type == SDL_EVENT_DROP_TEXT) { SDL_ToggleDragAndDropSupport(); } - - if (type == SDL_EVENT_MOUSE_RAW_MOTION || - type == SDL_EVENT_MOUSE_RAW_SCROLL || - type == SDL_EVENT_MOUSE_RAW_BUTTON) { - SDL_UpdateRawMouseDataEnabled(); - } } } @@ -1984,9 +2018,6 @@ bool SDL_InitEvents(void) return false; } - SDL_SetEventEnabled(SDL_EVENT_MOUSE_RAW_MOTION, false); - SDL_SetEventEnabled(SDL_EVENT_MOUSE_RAW_SCROLL, false); - SDL_SetEventEnabled(SDL_EVENT_MOUSE_RAW_BUTTON, false); SDL_InitQuit(); return true; diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index 3a96d5ab21af42..ea2c9e6fdeb4f0 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -690,6 +690,22 @@ bool SDL_SendKeyboardKeyAutoRelease(Uint64 timestamp, SDL_Scancode scancode) return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_AUTORELEASE, SDL_GLOBAL_KEYBOARD_ID, 0, scancode, true); } +void SDL_SendRawKeyboardKey(Uint64 timestamp, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, bool down) +{ + const SDL_EventType type = down ? SDL_EVENT_RAW_KEY_DOWN : SDL_EVENT_RAW_KEY_UP; + + if (SDL_EventEnabled(type)) { + SDL_Event event; + event.type = type; + event.common.timestamp = timestamp; + event.raw_key.which = keyboardID; + event.raw_key.scancode = scancode; + event.raw_key.raw = rawcode; + event.raw_key.down = down; + SDL_PushEvent(&event); + } +} + void SDL_ReleaseAutoReleaseKeys(void) { SDL_Keyboard *keyboard = &SDL_keyboard; diff --git a/src/events/SDL_keyboard_c.h b/src/events/SDL_keyboard_c.h index 4023822facbb12..5bfc825fb845e5 100644 --- a/src/events/SDL_keyboard_c.h +++ b/src/events/SDL_keyboard_c.h @@ -63,6 +63,9 @@ extern bool SDL_SendKeyboardKeyAutoRelease(Uint64 timestamp, SDL_Scancode scanco Most platforms should prefer to optionally call SDL_SetKeymap and then use SDL_SendKeyboardKey. */ extern bool SDL_SendKeyboardKeyAndKeycode(Uint64 timestamp, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, SDL_Keycode keycode, bool down); +// Send a raw keyboard key event +extern void SDL_SendRawKeyboardKey(Uint64 timestamp, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, bool down); + // Release all the autorelease keys extern void SDL_ReleaseAutoReleaseKeys(void); diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 638f6d4e543dde..88d990397fd6e5 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -597,34 +597,6 @@ void SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouse SDL_PrivateSendMouseMotion(timestamp, window, mouseID, relative, x, y); } -void SDL_SendRawMouseAxis(Uint64 timestamp, SDL_MouseID mouseID, int dx, int dy, float ux, float uy, SDL_EventType type) -{ - if (SDL_EventEnabled(type)) { - SDL_Event event; - event.type = type; - event.common.timestamp = timestamp; - event.maxis.which = mouseID; - event.maxis.dx = dx; - event.maxis.dy = dy; - event.maxis.ux = ux; - event.maxis.uy = uy; - SDL_PushEvent(&event); - } -} - -void SDL_SendRawMouseButton(Uint64 timestamp, SDL_MouseID mouseID, Uint8 state, Uint8 button) -{ - if (SDL_EventEnabled(SDL_EVENT_MOUSE_RAW_BUTTON)) { - SDL_Event event; - event.type = SDL_EVENT_MOUSE_RAW_BUTTON; - event.common.timestamp = timestamp; - event.mbutton.which = mouseID; - event.mbutton.button = button; - event.mbutton.state = state; - SDL_PushEvent(&event); - } -} - static void ConstrainMousePosition(SDL_Mouse *mouse, SDL_Window *window, float *x, float *y) { /* make sure that the pointers find themselves inside the windows, @@ -998,6 +970,51 @@ void SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseI } } +void SDL_SendRawMouseMotion(Uint64 timestamp, SDL_MouseID mouseID, int dx, int dy, float scale_x, float scale_y) +{ + if (SDL_EventEnabled(SDL_EVENT_RAW_MOUSE_MOTION)) { + SDL_Event event; + event.type = SDL_EVENT_RAW_MOUSE_MOTION; + event.common.timestamp = timestamp; + event.raw_motion.which = mouseID; + event.raw_motion.dx = dx; + event.raw_motion.dy = dy; + event.raw_motion.scale_x = scale_x; + event.raw_motion.scale_y = scale_y; + SDL_PushEvent(&event); + } +} + +void SDL_SendRawMouseButton(Uint64 timestamp, SDL_MouseID mouseID, Uint8 button, bool down) +{ + const SDL_EventType type = down ? SDL_EVENT_RAW_MOUSE_BUTTON_DOWN : SDL_EVENT_RAW_MOUSE_BUTTON_UP; + + if (SDL_EventEnabled(type)) { + SDL_Event event; + event.type = type; + event.common.timestamp = timestamp; + event.raw_button.which = mouseID; + event.raw_button.button = button; + event.raw_button.down = down; + SDL_PushEvent(&event); + } +} + +void SDL_SendRawMouseWheel(Uint64 timestamp, SDL_MouseID mouseID, int dx, int dy, float scale_x, float scale_y) +{ + if (SDL_EventEnabled(SDL_EVENT_RAW_MOUSE_WHEEL)) { + SDL_Event event; + event.type = SDL_EVENT_RAW_MOUSE_WHEEL; + event.common.timestamp = timestamp; + event.raw_wheel.which = mouseID; + event.raw_wheel.dx = dx; + event.raw_wheel.dy = dy; + event.raw_wheel.scale_x = scale_x; + event.raw_wheel.scale_y = scale_y; + SDL_PushEvent(&event); + } +} + void SDL_QuitMouse(void) { SDL_Cursor *cursor, *next; diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index 558cb4944e4a9e..ffd0260134bff1 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -169,12 +169,6 @@ extern bool SDL_UpdateMouseCapture(bool force_release); // Send a mouse motion event extern void SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, bool relative, float x, float y); -/* Send a raw mouse motion or scroll event */ -extern void SDL_SendRawMouseAxis(Uint64 timestamp, SDL_MouseID mouseID, int dx, int dy, float ux, float uy, SDL_EventType type); - -/* Send a raw mouse button event */ -extern void SDL_SendRawMouseButton(Uint64 timestamp, SDL_MouseID mouseID, Uint8 state, Uint8 button); - // Send a mouse button event extern void SDL_SendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 button, bool down); @@ -184,6 +178,15 @@ extern void SDL_SendMouseButtonClicks(Uint64 timestamp, SDL_Window *window, SDL_ // Send a mouse wheel event extern void SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction); +// Send raw mouse motion +extern void SDL_SendRawMouseMotion(Uint64 timestamp, SDL_MouseID mouseID, int dx, int dy, float scale_x, float scale_y); + +// Send a raw mouse button event +extern void SDL_SendRawMouseButton(Uint64 timestamp, SDL_MouseID mouseID, Uint8 button, bool down); + +// Send a raw mouse wheel event +extern void SDL_SendRawMouseWheel(Uint64 timestamp, SDL_MouseID mouseID, int dx, int dy, float scale_x, float scale_y); + // Warp the mouse within the window, potentially overriding relative mode extern void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, bool ignore_relative_mode); diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index eb28b0563c8c67..54eec3b75603b8 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -1784,6 +1784,11 @@ void SDLTest_PrintEvent(const SDL_Event *event) event->motion.xrel, event->motion.yrel, event->motion.windowID); break; + case SDL_EVENT_RAW_MOUSE_MOTION: + SDL_Log("SDL EVENT: Raw Mouse: mouse %" SDL_PRIu32 " moved %" SDL_PRIs32 ",%" SDL_PRIs32, + event->raw_motion.which, + event->raw_motion.dx, event->raw_motion.dy); + break; case SDL_EVENT_MOUSE_BUTTON_DOWN: SDL_Log("SDL EVENT: Mouse: button %d pressed at %g,%g with click count %d in window %" SDL_PRIu32, event->button.button, event->button.x, event->button.y, event->button.clicks, @@ -1794,10 +1799,22 @@ void SDLTest_PrintEvent(const SDL_Event *event) event->button.button, event->button.x, event->button.y, event->button.clicks, event->button.windowID); break; + case SDL_EVENT_RAW_MOUSE_BUTTON_DOWN: + SDL_Log("SDL EVENT: Raw Mouse: mouse %" SDL_PRIu32 " button %d pressed", + event->raw_button.which, event->raw_button.button); + break; + case SDL_EVENT_RAW_MOUSE_BUTTON_UP: + SDL_Log("SDL EVENT: Raw Mouse: mouse %" SDL_PRIu32 " button %d released", + event->raw_button.which, event->raw_button.button); + break; case SDL_EVENT_MOUSE_WHEEL: SDL_Log("SDL EVENT: Mouse: wheel scrolled %g in x and %g in y (reversed: %d) in window %" SDL_PRIu32, event->wheel.x, event->wheel.y, event->wheel.direction, event->wheel.windowID); break; + case SDL_EVENT_RAW_MOUSE_WHEEL: + SDL_Log("SDL EVENT: Raw Mouse: mouse %" SDL_PRIu32 " wheel scrolled %" SDL_PRIs32 " in x and %" SDL_PRIs32 " in y", + event->raw_wheel.which, event->raw_wheel.dx, event->raw_wheel.dy); + break; case SDL_EVENT_JOYSTICK_ADDED: SDL_Log("SDL EVENT: Joystick %" SDL_PRIu32 " attached", event->jdevice.which); @@ -2221,6 +2238,7 @@ SDL_AppResult SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const if (state->verbose & VERBOSE_EVENT) { if ((event->type != SDL_EVENT_MOUSE_MOTION && + event->type != SDL_EVENT_RAW_MOUSE_MOTION && event->type != SDL_EVENT_FINGER_MOTION && event->type != SDL_EVENT_PEN_MOTION && event->type != SDL_EVENT_PEN_AXIS && diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index e323c8971eb211..15bfb7229f4856 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -385,9 +385,6 @@ struct SDL_VideoDevice // Display the system-level window menu void (*ShowWindowSystemMenu)(SDL_Window *window, int x, int y); - /* Re-synchronize platform raw input subscription */ - bool (*RefreshRawInput)(SDL_VideoDevice *_this); - /* * * */ // Data common to all drivers SDL_ThreadID thread; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 3b0f576f447485..75b2a8df9e698c 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2109,13 +2109,6 @@ void SDL_ToggleDragAndDropSupport(void) } } -void SDL_UpdateRawMouseDataEnabled(void) -{ - if (_this && _this->RefreshRawInput) { - _this->RefreshRawInput(_this); - } -} - SDL_Window **SDLCALL SDL_GetWindows(int *count) { if (count) { diff --git a/src/video/openvr/SDL_openvrvideo.c b/src/video/openvr/SDL_openvrvideo.c index 51c10dfbafbea7..271ce93ca1b648 100644 --- a/src/video/openvr/SDL_openvrvideo.c +++ b/src/video/openvr/SDL_openvrvideo.c @@ -1210,9 +1210,11 @@ static bool OPENVR_GL_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window) static void OPENVR_HandleMouse(float x, float y, int btn, int evt) { if (evt == 2) { - SDL_SendMouseMotion(0, 0, 0, false, (int)x, (int)y); + SDL_SendMouseMotion(0, NULL, SDL_GLOBAL_MOUSE_ID, false, x, y); } else { - SDL_SendMouseButton(0, 0, 0, btn + 1, (evt != 0)); + const Uint8 button = SDL_BUTTON_LEFT + btn; + const bool down = (evt != 0); + SDL_SendMouseButton(0, NULL, SDL_GLOBAL_MOUSE_ID, button, down); } } diff --git a/src/video/uikit/SDL_uikitevents.m b/src/video/uikit/SDL_uikitevents.m index e3f9450d8b01c3..5d6252e1d77dbf 100644 --- a/src/video/uikit/SDL_uikitevents.m +++ b/src/video/uikit/SDL_uikitevents.m @@ -187,7 +187,9 @@ static void OnGCKeyboardConnected(GCKeyboard *keyboard) API_AVAILABLE(macos(11.0 SDL_AddKeyboard(keyboardID, NULL, true); keyboard.keyboardInput.keyChangedHandler = ^(GCKeyboardInput *kbrd, GCControllerButtonInput *key, GCKeyCode keyCode, BOOL pressed) { - SDL_SendKeyboardKey(0, keyboardID, 0, (SDL_Scancode)keyCode, pressed); + Uint64 timestamp = SDL_GetTicksNS(); + SDL_SendRawKeyboardKey(timestamp, keyboardID, 0, (SDL_Scancode)keyCode, pressed); + SDL_SendKeyboardKey(timestamp, keyboardID, 0, (SDL_Scancode)keyCode, pressed); }; dispatch_queue_t queue = dispatch_queue_create("org.libsdl.input.keyboard", DISPATCH_QUEUE_SERIAL); @@ -318,7 +320,9 @@ static bool SetGCMouseRelativeMode(bool enabled) static void OnGCMouseButtonChanged(SDL_MouseID mouseID, Uint8 button, BOOL pressed) { - SDL_SendMouseButton(0, SDL_GetMouseFocus(), mouseID, button, pressed); + Uint64 timestamp = SDL_GetTicksNS(); + SDL_SendRawMouseButton(timestamp, mouseID, button, pressed); + SDL_SendMouseButton(timestamp, SDL_GetMouseFocus(), mouseID, button, pressed); } static void OnGCMouseConnected(GCMouse *mouse) API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) @@ -346,12 +350,19 @@ static void OnGCMouseConnected(GCMouse *mouse) API_AVAILABLE(macos(11.0), ios(14 } mouse.mouseInput.mouseMovedHandler = ^(GCMouseInput *mouseInput, float deltaX, float deltaY) { - if (SDL_GCMouseRelativeMode()) { - SDL_SendMouseMotion(0, SDL_GetMouseFocus(), mouseID, 1, deltaX, -deltaY); - } + Uint64 timestamp = SDL_GetTicksNS(); + + // FIXME: Do we get non-integer deltas here? + SDL_SendRawMouseMotion(timestamp, mouseID, (int)deltaX, (int)-deltaY, 1.0f, 1.0f); + + if (SDL_GCMouseRelativeMode()) { + SDL_SendMouseMotion(timestamp, SDL_GetMouseFocus(), mouseID, true, deltaX, -deltaY); + } }; mouse.mouseInput.scroll.valueChangedHandler = ^(GCControllerDirectionPad *dpad, float xValue, float yValue) { + Uint64 timestamp = SDL_GetTicksNS(); + /* Raw scroll values come in here, vertical values in the first axis, horizontal values in the second axis. * The vertical values are negative moving the mouse wheel up and positive moving it down. * The horizontal values are negative moving the mouse wheel left and positive moving it right. @@ -359,12 +370,16 @@ static void OnGCMouseConnected(GCMouse *mouse) API_AVAILABLE(macos(11.0), ios(14 */ float vertical = -xValue; float horizontal = yValue; + + // FIXME: Do we get non-integer deltas here? + SDL_SendRawMouseWheel(timestamp, mouseID, (int)horizontal, (int)vertical, 1.0f, 1.0f); + if (mouse_scroll_direction == SDL_MOUSEWHEEL_FLIPPED) { // Since these are raw values, we need to flip them ourselves vertical = -vertical; horizontal = -horizontal; } - SDL_SendMouseWheel(0, SDL_GetMouseFocus(), mouseID, horizontal, vertical, mouse_scroll_direction); + SDL_SendMouseWheel(timestamp, SDL_GetMouseFocus(), mouseID, horizontal, vertical, mouse_scroll_direction); }; UpdateScrollDirection(); diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 6cd7501aad0431..e79453b8b46d1a 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -697,37 +697,37 @@ static void pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_ SDL_WindowData *window = input->pointer_focus; enum wl_pointer_button_state state = state_w; Uint64 timestamp = Wayland_GetPointerTimestamp(input, time); + Uint8 sdl_button; + const bool down = (state != 0); - if (SDL_EventEnabled(SDL_EVENT_MOUSE_RAW_BUTTON)) { - SDL_SendRawMouseButton(timestamp, input->pointer_id, !!state, button); + switch (button) { + case BTN_LEFT: + sdl_button = SDL_BUTTON_LEFT; + break; + case BTN_MIDDLE: + sdl_button = SDL_BUTTON_MIDDLE; + break; + case BTN_RIGHT: + sdl_button = SDL_BUTTON_RIGHT; + break; + case BTN_SIDE: + sdl_button = SDL_BUTTON_X1; + break; + case BTN_EXTRA: + sdl_button = SDL_BUTTON_X2; + break; + default: + return; } + SDL_SendRawMouseButton(timestamp, input->pointer_id, sdl_button, down); if (window) { SDL_VideoData *viddata = window->waylandData; - Uint32 sdl_button; bool ignore_click = false; - switch (button) { - case BTN_LEFT: - sdl_button = SDL_BUTTON_LEFT; - if (ProcessHitTest(input->pointer_focus, input->seat, input->sx_w, input->sy_w, serial)) { - return; // don't pass this event on to app. - } - break; - case BTN_MIDDLE: - sdl_button = SDL_BUTTON_MIDDLE; - break; - case BTN_RIGHT: - sdl_button = SDL_BUTTON_RIGHT; - break; - case BTN_SIDE: - sdl_button = SDL_BUTTON_X1; - break; - case BTN_EXTRA: - sdl_button = SDL_BUTTON_X2; - break; - default: - return; + if (sdl_button == SDL_BUTTON_LEFT && + ProcessHitTest(input->pointer_focus, input->seat, input->sx_w, input->sy_w, serial)) { + return; // don't pass this event on to app. } // Possibly ignore this click if it was to gain focus. @@ -765,8 +765,7 @@ static void pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_ } if (!ignore_click) { - SDL_SendMouseButton(Wayland_GetPointerTimestamp(input, time), window->sdlwindow, input->pointer_id, - sdl_button, !!state); + SDL_SendMouseButton(timestamp, window->sdlwindow, input->pointer_id, sdl_button, down); } } } @@ -786,15 +785,13 @@ static void pointer_handle_axis_common_v1(struct SDL_WaylandInput *input, const Uint64 timestamp = Wayland_GetPointerTimestamp(input, time); const enum wl_pointer_axis a = axis; - if (SDL_EventEnabled(SDL_EVENT_MOUSE_RAW_SCROLL)) { - // wl_fixed_t is a 24.8 signed fixed-point number which needs to be converted by dividing by 256 - const float denom = (float)(WAYLAND_WHEEL_AXIS_UNIT * 256); - - if (a == WL_POINTER_AXIS_VERTICAL_SCROLL) { - SDL_SendRawMouseAxis(timestamp, input->pointer_id, 0, (int)value, 0.f, denom, SDL_EVENT_MOUSE_RAW_SCROLL); - } else { - SDL_SendRawMouseAxis(timestamp, input->pointer_id, (int)value, 0, denom, 0.f, SDL_EVENT_MOUSE_RAW_SCROLL); - } + // wl_fixed_t is a 24.8 signed fixed-point number which needs to be converted by dividing by 256 + const float scale = 1.0f / WAYLAND_WHEEL_AXIS_UNIT; + const int amount = (value * WAYLAND_WHEEL_AXIS_UNIT) >> 8; + if (a == WL_POINTER_AXIS_VERTICAL_SCROLL) { + SDL_SendRawMouseWheel(timestamp, input->pointer_id, 0, amount, scale, scale); + } else { + SDL_SendRawMouseWheel(timestamp, input->pointer_id, amount, 0, scale, scale); } if (input->pointer_focus) { @@ -825,15 +822,13 @@ static void pointer_handle_axis_common(struct SDL_WaylandInput *input, enum SDL_ { const enum wl_pointer_axis a = axis; - if (SDL_EventEnabled(SDL_EVENT_MOUSE_RAW_SCROLL)) { - // wl_fixed_t is a 24.8 signed fixed-point number which needs to be converted by dividing by 256 - const float denom = (float)((type == AXIS_EVENT_VALUE120 ? 120 : WAYLAND_WHEEL_AXIS_UNIT) * 256); - - if (a == WL_POINTER_AXIS_VERTICAL_SCROLL) { - SDL_SendRawMouseAxis(input->pointer_curr_axis_info.timestamp_ns, input->pointer_id, 0, (int)value, 0.f, denom, SDL_EVENT_MOUSE_RAW_SCROLL); - } else { - SDL_SendRawMouseAxis(input->pointer_curr_axis_info.timestamp_ns, input->pointer_id, (int)value, 0, denom, 0.f, SDL_EVENT_MOUSE_RAW_SCROLL); - } + // wl_fixed_t is a 24.8 signed fixed-point number which needs to be converted by dividing by 256 + const float scale = (type == AXIS_EVENT_VALUE120) ? (1.0f / 120.0f) : (1.0f / WAYLAND_WHEEL_AXIS_UNIT); + const int amount = (type == AXIS_EVENT_VALUE120) ? (amount >> 8) : ((value * WAYLAND_WHEEL_AXIS_UNIT) >> 8); + if (a == WL_POINTER_AXIS_VERTICAL_SCROLL) { + SDL_SendRawMouseWheel(timestamp, input->pointer_id, 0, amount, scale, scale); + } else { + SDL_SendRawMouseWheel(timestamp, input->pointer_id, amount, 0, scale, scale); } if (input->pointer_focus) { @@ -1038,10 +1033,10 @@ static void relative_pointer_handle_relative_motion(void *data, // Relative pointer event times are in microsecond granularity. const Uint64 timestamp = Wayland_GetEventTimestamp(SDL_US_TO_NS(((Uint64)time_hi << 32) | (Uint64)time_lo)); - if (SDL_EventEnabled(SDL_EVENT_MOUSE_RAW_MOTION)) { - // wl_fixed_t is a 24.8 signed fixed-point number which needs to be converted by dividing by 256 - SDL_SendRawMouseAxis(timestamp, input->pointer_id, (int)dx_unaccel_w, (int)dy_unaccel_w, 256.0f, 256.0f, SDL_EVENT_MOUSE_RAW_MOTION); - } + // wl_fixed_t is a 24.8 signed fixed-point number which needs to be converted by dividing by 256 + const float scale_x = dx_unaccel_w ? (dx_w / (float)dx_unaccel_w) : 1.0f; + const float scale_y = dx_unaccel_h ? (dx_h / (float)dx_unaccel_h) : 1.0f; + SDL_SendRawMouseMotion(timestamp, input->pointer_id, dx_unaccel_w >> 8, dy_unaccel_w >> 8, scale_x, scale_y); if (input->pointer_focus && d->relative_mouse_mode) { double dx; @@ -1719,7 +1714,8 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, } #endif - window->last_focus_event_time_ns = SDL_GetTicksNS(); + Uint64 timestamp = SDL_GetTicksNS(); + window->last_focus_event_time_ns = timestamp; wl_array_for_each (key, keys) { const SDL_Scancode scancode = Wayland_get_scancode_from_key(input, *key + 8); @@ -1736,7 +1732,8 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, case SDLK_RGUI: case SDLK_MODE: Wayland_HandleModifierKeys(input, scancode, true); - SDL_SendKeyboardKeyIgnoreModifiers(0, input->keyboard_id, *key, scancode, true); + SDL_SendRawKeyboardKey(timestamp, input->keyboard_id, *key, scancode, true); + SDL_SendKeyboardKeyIgnoreModifiers(timestamp, input->keyboard_id, *key, scancode, true); break; default: break; @@ -1872,7 +1869,9 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, scancode = Wayland_get_scancode_from_key(input, key + 8); Wayland_HandleModifierKeys(input, scancode, state == WL_KEYBOARD_KEY_STATE_PRESSED); - SDL_SendKeyboardKeyIgnoreModifiers(Wayland_GetKeyboardTimestamp(input, time), input->keyboard_id, key, scancode, (state == WL_KEYBOARD_KEY_STATE_PRESSED)); + Uint64 timestamp = Wayland_GetKeyboardTimestamp(input, time); + SDL_SendRawKeyboardKey(timestamp, input->keyboard_id, key, scancode, (state == WL_KEYBOARD_KEY_STATE_PRESSED)); + SDL_SendKeyboardKeyIgnoreModifiers(timestamp, input->keyboard_id, key, scancode, (state == WL_KEYBOARD_KEY_STATE_PRESSED)); if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { if (has_text && !(SDL_GetModState() & SDL_KMOD_CTRL)) { diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index ccbf9851668048..ebe987f05a3bf7 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -521,46 +521,66 @@ static bool WIN_SwapButtons(HANDLE hDevice) static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_VideoData *data, HANDLE hDevice, RAWMOUSE *rawmouse) { - int xraw = (int)rawmouse->lLastX; - int yraw = (int)rawmouse->lLastY; - bool haveMotion = (xraw || yraw) ? true : false; - bool haveButton = (rawmouse->usButtonFlags) ? true : false; - bool isAbsolute = (rawmouse->usFlags & MOUSE_MOVE_ABSOLUTE) ? true : false; + static struct { + USHORT usButtonFlags; + Uint8 button; + bool down; + } raw_buttons[] = { + { RI_MOUSE_LEFT_BUTTON_DOWN, SDL_BUTTON_LEFT, true }, + { RI_MOUSE_LEFT_BUTTON_UP, SDL_BUTTON_LEFT, false }, + { RI_MOUSE_RIGHT_BUTTON_DOWN, SDL_BUTTON_RIGHT, true }, + { RI_MOUSE_RIGHT_BUTTON_UP, SDL_BUTTON_RIGHT, false }, + { RI_MOUSE_MIDDLE_BUTTON_DOWN, SDL_BUTTON_MIDDLE, true }, + { RI_MOUSE_MIDDLE_BUTTON_UP, SDL_BUTTON_MIDDLE, false }, + { RI_MOUSE_BUTTON_4_DOWN, SDL_BUTTON_X1, true }, + { RI_MOUSE_BUTTON_4_UP, SDL_BUTTON_X1, false }, + { RI_MOUSE_BUTTON_5_DOWN, SDL_BUTTON_X2, true }, + { RI_MOUSE_BUTTON_5_UP, SDL_BUTTON_X2, false } + }; + + int dx = (int)rawmouse->lLastX; + int dy = (int)rawmouse->lLastY; + bool haveMotion = (dx || dy); + bool haveButton = (rawmouse->usButtonFlags != 0); + bool isAbsolute = ((rawmouse->usFlags & MOUSE_MOVE_ABSOLUTE) != 0); SDL_MouseID mouseID = (SDL_MouseID)(uintptr_t)hDevice; - - if (SDL_EventEnabled(SDL_EVENT_MOUSE_RAW_MOTION)) { - if (haveMotion && !isAbsolute) { - SDL_SendRawMouseAxis(timestamp, mouseID, xraw, yraw, 1.0f, 1.0f, SDL_EVENT_MOUSE_RAW_MOTION); - } - } - - if (SDL_EventEnabled(SDL_EVENT_MOUSE_RAW_BUTTON)) { - if (haveButton) { - USHORT flagBits = rawmouse->usButtonFlags; - for (Uint8 i = 0; i < 10; ++i) { - if (flagBits & 1) { - Uint8 state = (i & 1) ^ 1; - Uint8 button = (i >> 1) + 1; - SDL_SendRawMouseButton(timestamp, mouseID, state, button); + + if (haveMotion && !isAbsolute) { + // FIXME: Apply desktop mouse scale? + const float scale = 1.0f; + SDL_SendRawMouseMotion(timestamp, mouseID, dx, dy, scale, scale); + } + + if (haveButton) { + for (int i = 0; i < SDL_arraysize(raw_buttons); ++i) { + if (rawmouse->usButtonFlags & raw_buttons[i].usButtonFlags) { + Uint8 button = raw_buttons[i].button; + bool down = raw_buttons[i].down; + + if (button == SDL_BUTTON_LEFT) { + if (WIN_SwapButtons(hDevice)) { + button = SDL_BUTTON_RIGHT; + } + } else if (button == SDL_BUTTON_RIGHT) { + if (WIN_SwapButtons(hDevice)) { + button = SDL_BUTTON_LEFT; + } } - flagBits = flagBits >> 1; + + SDL_SendRawMouseButton(timestamp, mouseID, button, down); } } - } - - if (SDL_EventEnabled(SDL_EVENT_MOUSE_RAW_SCROLL)) { - if (haveButton) { - short amount = (short)rawmouse->usButtonData; - if (rawmouse->usButtonFlags & RI_MOUSE_WHEEL) { - SDL_SendRawMouseAxis(timestamp, mouseID, 0, (int)amount, 120.0f, 120.0f, SDL_EVENT_MOUSE_RAW_SCROLL); - } else if (rawmouse->usButtonFlags & RI_MOUSE_HWHEEL) { - SDL_SendRawMouseAxis(timestamp, mouseID, (int)amount, 0, 120.0f, 120.0f, SDL_EVENT_MOUSE_RAW_SCROLL); - } + + const float scale = 1.0f / 120.0f; + SHORT amount = (SHORT)rawmouse->usButtonData; + if (rawmouse->usButtonFlags & RI_MOUSE_WHEEL) { + SDL_SendRawMouseWheel(timestamp, mouseID, 0, amount, scale, scale); + } else if (rawmouse->usButtonFlags & RI_MOUSE_HWHEEL) { + SDL_SendRawMouseWheel(timestamp, mouseID, amount, 0, scale, scale); } } - // this check is for whether relative mode should also receive events from the rawinput stream, - // separate from whether or not the optional rawaxis/rawbutton events should be generated. + // Check whether relative mode should also receive events from the rawinput stream if (!data->raw_mouse_enabled) { return; } @@ -579,27 +599,27 @@ static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_VideoData *data, HANDL if (haveMotion) { if (!isAbsolute) { - SDL_SendMouseMotion(timestamp, window, mouseID, true, (float)xraw, (float)yraw); + SDL_SendMouseMotion(timestamp, window, mouseID, true, (float)dx, (float)dy); } else { /* This is absolute motion, either using a tablet or mouse over RDP - + Notes on how RDP appears to work, as of Windows 10 2004: - SetCursorPos() calls are cached, with multiple calls coalesced into a single call that's sent to the RDP client. If the last call to SetCursorPos() has the same value as the last one that was sent to the client, it appears to be ignored and not sent. This means that we need to jitter the SetCursorPos() position slightly in order for the recentering to work correctly. - User mouse motion is coalesced with SetCursorPos(), so the WM_INPUT positions we see will not necessarily match the position we requested with SetCursorPos(). - SetCursorPos() outside of the bounds of the focus window appears not to do anything. - SetCursorPos() while the cursor is NULL doesn't do anything - + We handle this by creating a safe area within the application window, and when the mouse leaves that safe area, we warp back to the opposite side. Any single motion > 50% of the safe area is assumed to be a warp and ignored. */ - bool remote_desktop = GetSystemMetrics(SM_REMOTESESSION) ? true : false; - bool virtual_desktop = (rawmouse->usFlags & MOUSE_VIRTUAL_DESKTOP) ? true : false; - bool raw_coordinates = (rawmouse->usFlags & 0x40) ? true : false; + bool remote_desktop = (GetSystemMetrics(SM_REMOTESESSION) == TRUE); + bool virtual_desktop = ((rawmouse->usFlags & MOUSE_VIRTUAL_DESKTOP) != 0); + bool raw_coordinates = ((rawmouse->usFlags & 0x40) != 0); int w = GetSystemMetrics(virtual_desktop ? SM_CXVIRTUALSCREEN : SM_CXSCREEN); int h = GetSystemMetrics(virtual_desktop ? SM_CYVIRTUALSCREEN : SM_CYSCREEN); - int x = raw_coordinates ? (int)xraw : (int)(((float)xraw / 65535.0f) * w); - int y = raw_coordinates ? (int)yraw : (int)(((float)yraw / 65535.0f) * h); + int x = raw_coordinates ? dx : (int)(((float)dx / 65535.0f) * w); + int y = raw_coordinates ? dy : (int)(((float)dy / 65535.0f) * h); int relX, relY; - + /* Calculate relative motion */ if (data->last_raw_mouse_position.x == 0 && data->last_raw_mouse_position.y == 0) { data->last_raw_mouse_position.x = x; @@ -607,22 +627,22 @@ static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_VideoData *data, HANDL } relX = x - data->last_raw_mouse_position.x; relY = y - data->last_raw_mouse_position.y; - + if (remote_desktop) { if (!windowdata->in_title_click && !windowdata->focus_click_pending) { static int wobble; float floatX = (float)x / w; float floatY = (float)y / h; - + /* See if the mouse is at the edge of the screen, or in the RDP title bar area */ if (floatX <= 0.01f || floatX >= 0.99f || floatY <= 0.01f || floatY >= 0.99f || y < 32) { /* Wobble the cursor position so it's not ignored if the last warp didn't have any effect */ RECT rect = windowdata->cursor_clipped_rect; int warpX = rect.left + ((rect.right - rect.left) / 2) + wobble; int warpY = rect.top + ((rect.bottom - rect.top) / 2); - + WIN_SetCursorPos(warpX, warpY); - + ++wobble; if (wobble > 1) { wobble = -1; @@ -648,30 +668,13 @@ static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_VideoData *data, HANDL SDL_SendMouseMotion(timestamp, window, mouseID, true, (float)relX, (float)relY); } } - + data->last_raw_mouse_position.x = x; data->last_raw_mouse_position.y = y; } } if (haveButton) { - static struct { - USHORT usButtonFlags; - Uint8 button; - bool down; - } raw_buttons[] = { - { RI_MOUSE_LEFT_BUTTON_DOWN, SDL_BUTTON_LEFT, true }, - { RI_MOUSE_LEFT_BUTTON_UP, SDL_BUTTON_LEFT, false }, - { RI_MOUSE_RIGHT_BUTTON_DOWN, SDL_BUTTON_RIGHT, true }, - { RI_MOUSE_RIGHT_BUTTON_UP, SDL_BUTTON_RIGHT, false }, - { RI_MOUSE_MIDDLE_BUTTON_DOWN, SDL_BUTTON_MIDDLE, true }, - { RI_MOUSE_MIDDLE_BUTTON_UP, SDL_BUTTON_MIDDLE, false }, - { RI_MOUSE_BUTTON_4_DOWN, SDL_BUTTON_X1, true }, - { RI_MOUSE_BUTTON_4_UP, SDL_BUTTON_X1, false }, - { RI_MOUSE_BUTTON_5_DOWN, SDL_BUTTON_X2, true }, - { RI_MOUSE_BUTTON_5_UP, SDL_BUTTON_X2, false } - }; - for (int i = 0; i < SDL_arraysize(raw_buttons); ++i) { if (rawmouse->usButtonFlags & raw_buttons[i].usButtonFlags) { Uint8 button = raw_buttons[i].button; @@ -703,11 +706,11 @@ static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_VideoData *data, HANDL } if (rawmouse->usButtonFlags & RI_MOUSE_WHEEL) { - short amount = (short)rawmouse->usButtonData; + SHORT amount = (SHORT)rawmouse->usButtonData; float fAmount = (float)amount / WHEEL_DELTA; SDL_SendMouseWheel(WIN_GetEventTimestamp(), window, mouseID, 0.0f, fAmount, SDL_MOUSEWHEEL_NORMAL); } else if (rawmouse->usButtonFlags & RI_MOUSE_HWHEEL) { - short amount = (short)rawmouse->usButtonData; + SHORT amount = (SHORT)rawmouse->usButtonData; float fAmount = (float)amount / WHEEL_DELTA; SDL_SendMouseWheel(WIN_GetEventTimestamp(), window, mouseID, fAmount, 0.0f, SDL_MOUSEWHEEL_NORMAL); } @@ -718,10 +721,6 @@ static void WIN_HandleRawKeyboardInput(Uint64 timestamp, SDL_VideoData *data, HA { SDL_KeyboardID keyboardID = (SDL_KeyboardID)(uintptr_t)hDevice; - if (!data->raw_keyboard_enabled) { - return; - } - if (rawkeyboard->Flags & RI_KEY_E1) { // First key in a Ctrl+{key} sequence data->pending_E1_key_sequence = true; @@ -764,6 +763,13 @@ static void WIN_HandleRawKeyboardInput(Uint64 timestamp, SDL_VideoData *data, HA } code = windows_scancode_table[index]; } + + SDL_SendRawKeyboardKey(timestamp, keyboardID, rawcode, code, down); + + if (!data->raw_keyboard_enabled) { + return; + } + if (down) { SDL_Window *focus = SDL_GetKeyboardFocus(); if (!focus || focus->text_input_active) { @@ -1167,7 +1173,7 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara ); if (wish_clip_cursor) { data->skip_update_clipcursor = false; - WIN_UpdateClipCursor(window); + WIN_UpdateClipCursor(window); } } diff --git a/src/video/windows/SDL_windowsgameinput.c b/src/video/windows/SDL_windowsgameinput.c index df6829bb71b428..11dfc2e5a1f09e 100644 --- a/src/video/windows/SDL_windowsgameinput.c +++ b/src/video/windows/SDL_windowsgameinput.c @@ -291,6 +291,7 @@ static void GAMEINPUT_InitialMouseReading(WIN_GameInputData *data, SDL_Window *w for (int i = 0; i < MAX_GAMEINPUT_BUTTONS; ++i) { const GameInputMouseButtons mask = (1 << i); bool down = ((state.buttons & mask) != 0); + SDL_SendRawMouseButton(timestamp, mouseID, GAMEINPUT_button_map[i], down); SDL_SendMouseButton(timestamp, window, mouseID, GAMEINPUT_button_map[i], down); } } @@ -313,6 +314,10 @@ static void GAMEINPUT_HandleMouseDelta(WIN_GameInputData *data, SDL_Window *wind delta.wheelY = (state.wheelY - last.wheelY); if (delta.positionX || delta.positionY) { + // FIXME: Apply desktop mouse scale? + const float scale = 1.0f; + SDL_SendRawMouseMotion(timestamp, mouseID, delta.positionX, delta.positionY, scale, scale); + SDL_SendMouseMotion(timestamp, window, mouseID, true, (float)delta.positionX, (float)delta.positionY); } if (delta.buttons) { @@ -320,11 +325,15 @@ static void GAMEINPUT_HandleMouseDelta(WIN_GameInputData *data, SDL_Window *wind const GameInputMouseButtons mask = (1 << i); if (delta.buttons & mask) { bool down = ((state.buttons & mask) != 0); + SDL_SendRawMouseButton(timestamp, mouseID, GAMEINPUT_button_map[i], down); SDL_SendMouseButton(timestamp, window, mouseID, GAMEINPUT_button_map[i], down); } } } if (delta.wheelX || delta.wheelY) { + const float scale = 1.0f / WHEEL_DELTA; + SDL_SendRawMouseWheel(timestamp, device->instance_id, delta.wheelX, delta.wheelY, scale, scale); + float fAmountX = (float)delta.wheelX / WHEEL_DELTA; float fAmountY = (float)delta.wheelY / WHEEL_DELTA; SDL_SendMouseWheel(timestamp, SDL_GetMouseFocus(), device->instance_id, fAmountX, fAmountY, SDL_MOUSEWHEEL_NORMAL); @@ -374,12 +383,14 @@ static void GAMEINPUT_InitialKeyboardReading(WIN_GameInputData *data, SDL_Window const bool *keyboard_state = SDL_GetKeyboardState(&num_scancodes); for (int i = 0; i < num_scancodes; ++i) { if (keyboard_state[i] && !KeysHaveScancode(keys, num_keys, (SDL_Scancode)i)) { + SDL_SendRawKeyboardKey(timestamp, keyboardID, keys[i].scanCode, (SDL_Scancode)i, false); SDL_SendKeyboardKey(timestamp, keyboardID, keys[i].scanCode, (SDL_Scancode)i, false); } } // Go through and send key down events for any key that's held down for (uint32_t i = 0; i < num_keys; ++i) { + SDL_SendRawKeyboardKey(timestamp, keyboardID, keys[i].scanCode, GetScancodeFromKeyState(&keys[i]), true); SDL_SendKeyboardKey(timestamp, keyboardID, keys[i].scanCode, GetScancodeFromKeyState(&keys[i]), true); } } @@ -425,15 +436,18 @@ static void GAMEINPUT_HandleKeyboardDelta(WIN_GameInputData *data, SDL_Window *w ++index_keys; } else { // This key was released + SDL_SendRawKeyboardKey(timestamp, keyboardID, last[index_last].scanCode, GetScancodeFromKeyState(&last[index_last]), false); SDL_SendKeyboardKey(timestamp, keyboardID, last[index_last].scanCode, GetScancodeFromKeyState(&last[index_last]), false); ++index_last; } } else if (index_last < num_last) { // This key was released + SDL_SendRawKeyboardKey(timestamp, keyboardID, last[index_last].scanCode, GetScancodeFromKeyState(&last[index_last]), false); SDL_SendKeyboardKey(timestamp, keyboardID, last[index_last].scanCode, GetScancodeFromKeyState(&last[index_last]), false); ++index_last; } else { // This key was pressed + SDL_SendRawKeyboardKey(timestamp, keyboardID, keys[index_keys].scanCode, GetScancodeFromKeyState(&keys[index_keys]), true); SDL_SendKeyboardKey(timestamp, keyboardID, keys[index_keys].scanCode, GetScancodeFromKeyState(&keys[index_keys]), true); ++index_keys; } diff --git a/src/video/windows/SDL_windowsrawinput.c b/src/video/windows/SDL_windowsrawinput.c index d44881074b370d..b4937c8044c7a4 100644 --- a/src/video/windows/SDL_windowsrawinput.c +++ b/src/video/windows/SDL_windowsrawinput.c @@ -193,13 +193,11 @@ static bool WIN_UpdateRawInputEnabled(SDL_VideoDevice *_this) { SDL_VideoData *data = _this->internal; Uint32 flags = 0; - if (SDL_EventEnabled(SDL_EVENT_MOUSE_RAW_MOTION) || - SDL_EventEnabled(SDL_EVENT_MOUSE_RAW_SCROLL) || - SDL_EventEnabled(SDL_EVENT_MOUSE_RAW_BUTTON) || - data->raw_mouse_enabled) { + const bool ENABLE_RAW_INPUT_EVENTS = true; + if (data->raw_mouse_enabled || ENABLE_RAW_INPUT_EVENTS) { flags |= ENABLE_RAW_MOUSE_INPUT; } - if (data->raw_keyboard_enabled) { + if (data->raw_keyboard_enabled || ENABLE_RAW_INPUT_EVENTS) { flags |= ENABLE_RAW_KEYBOARD_INPUT; } if (flags != data->raw_input_enabled) { @@ -248,11 +246,6 @@ bool WIN_SetRawKeyboardEnabled(SDL_VideoDevice *_this, bool enabled) return true; } -bool WIN_RefreshRawInputEnabled(SDL_VideoDevice *_this) -{ - return WIN_UpdateRawInputEnabled(_this); -} - #else bool WIN_SetRawMouseEnabled(SDL_VideoDevice *_this, bool enabled) @@ -265,10 +258,6 @@ bool WIN_SetRawKeyboardEnabled(SDL_VideoDevice *_this, bool enabled) return SDL_Unsupported(); } -bool WIN_RefreshRawInputEnabled(SDL_VideoDevice *_this) -{ - return SDL_Unsupported(); -} #endif // !SDL_PLATFORM_XBOXONE && !SDL_PLATFORM_XBOXSERIES #endif // SDL_VIDEO_DRIVER_WINDOWS diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c index 8c74ee6282152b..982c2a77a1ed9b 100644 --- a/src/video/windows/SDL_windowsvideo.c +++ b/src/video/windows/SDL_windowsvideo.c @@ -246,7 +246,6 @@ static SDL_VideoDevice *WIN_CreateDevice(void) device->OnWindowEnter = WIN_OnWindowEnter; device->SetWindowHitTest = WIN_SetWindowHitTest; device->AcceptDragAndDrop = WIN_AcceptDragAndDrop; - device->RefreshRawInput = WIN_RefreshRawInputEnabled; device->FlashWindow = WIN_FlashWindow; device->ShowWindowSystemMenu = WIN_ShowWindowSystemMenu; device->SetWindowFocusable = WIN_SetWindowFocusable; diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 4d7fbf3e2e0c10..9dc514f965bfa9 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -795,6 +795,12 @@ SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window) return NULL; } +Uint64 X11_GetEventTimestamp(unsigned long time) +{ + // FIXME: Get the event time in the SDL tick time base + return SDL_GetTicksNS(); +} + void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_KeyboardID keyboardID, XEvent *xevent) { SDL_VideoData *videodata = (SDL_VideoData *)_this->internal; @@ -805,6 +811,7 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_ char text[64]; Status status = 0; bool handled_by_ime = false; + Uint64 timestamp = X11_GetEventTimestamp(xevent->xkey.time) #ifdef DEBUG_XEVENTS SDL_Log("window 0x%lx %s (X11 keycode = 0x%X)\n", xevent->xany.window, (xevent->type == KeyPress ? "KeyPress" : "KeyRelease"), xevent->xkey.keycode); @@ -820,6 +827,11 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_ } #endif // DEBUG SCANCODES + if (keyboardID != SDL_GLOBAL_KEYBOARD_ID) { + const bool down = (xevent->type == KeyPress); + SDL_SendRawKeyboardKey(timestamp, keyboardID, keycode, videodata->key_layout[keycode], down); + } + text[0] = '\0'; if (SDL_TextInputActive(windowdata->window)) { @@ -846,9 +858,9 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_ videodata->filter_time = xevent->xkey.time; if (orig_event_type == KeyPress) { - SDL_SendKeyboardKey(0, keyboardID, orig_keycode, scancode, true); + SDL_SendKeyboardKey(timestamp, keyboardID, orig_keycode, scancode, true); } else { - SDL_SendKeyboardKey(0, keyboardID, orig_keycode, scancode, false); + SDL_SendKeyboardKey(timestamp, keyboardID, orig_keycode, scancode, false); } #endif return; @@ -874,7 +886,7 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_ if (xevent->type == KeyPress) { // Don't send the key if it looks like a duplicate of a filtered key sent by an IME if (xevent->xkey.keycode != videodata->filter_code || xevent->xkey.time != videodata->filter_time) { - SDL_SendKeyboardKey(0, keyboardID, keycode, videodata->key_layout[keycode], true); + SDL_SendKeyboardKey(timestamp, keyboardID, keycode, videodata->key_layout[keycode], true); } if (*text) { text[text_length] = '\0'; @@ -885,7 +897,7 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_ // We're about to get a repeated key down, ignore the key up return; } - SDL_SendKeyboardKey(0, keyboardID, keycode, videodata->key_layout[keycode], false); + SDL_SendKeyboardKey(timestamp, keyboardID, keycode, videodata->key_layout[keycode], false); } } @@ -894,12 +906,14 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_ } } -void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, const float x, const float y, const unsigned long time) +void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, float x, float y, unsigned long time) { SDL_Window *window = windowdata->window; const SDL_VideoData *videodata = (SDL_VideoData *)_this->internal; Display *display = videodata->display; int xticks = 0, yticks = 0; + Uint64 timestamp = X11_GetEventTimestamp(time); + #ifdef DEBUG_XEVENTS SDL_Log("window 0x%lx: ButtonPress (X11 button = %d)\n", windowdata->xwindow, button); #endif @@ -907,22 +921,29 @@ void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, S SDL_Mouse *mouse = SDL_GetMouse(); if (!mouse->relative_mode && (x != mouse->x || y != mouse->y)) { X11_ProcessHitTest(_this, windowdata, x, y, false); - SDL_SendMouseMotion(0, window, mouseID, false, x, y); + SDL_SendMouseMotion(timestamp, window, mouseID, false, x, y); } if (X11_IsWheelEvent(display, button, &xticks, &yticks)) { - SDL_SendMouseWheel(0, window, mouseID, (float)-xticks, (float)yticks, SDL_MOUSEWHEEL_NORMAL); + if (mouseID != SDL_GLOBAL_MOUSE_ID) { + SDL_SendRawMouseWheel(timestamp, mouseID, -xticks, yticks); + } + SDL_SendMouseWheel(timestamp, window, mouseID, (float)-xticks, (float)yticks, SDL_MOUSEWHEEL_NORMAL); } else { bool ignore_click = false; + if (button > 7) { + /* X button values 4-7 are used for scrolling, so X1 is 8, X2 is 9, ... + => subtract (8-SDL_BUTTON_X1) to get value SDL expects */ + button -= (8 - SDL_BUTTON_X1); + } + if (mouseID != SDL_GLOBAL_MOUSE_ID) { + SDL_SendRawMouseButton(timestamp, mouseID, button, true); + } if (button == Button1) { if (X11_TriggerHitTestAction(_this, windowdata, x, y)) { SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0); return; // don't pass this event on to app. } - } else if (button > 7) { - /* X button values 4-7 are used for scrolling, so X1 is 8, X2 is 9, ... - => subtract (8-SDL_BUTTON_X1) to get value SDL expects */ - button -= (8 - SDL_BUTTON_X1); } if (windowdata->last_focus_event_time) { const int X11_FOCUS_CLICK_TIMEOUT = 10; @@ -932,19 +953,21 @@ void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, S windowdata->last_focus_event_time = 0; } if (!ignore_click) { - SDL_SendMouseButton(0, window, mouseID, button, true); + SDL_SendMouseButton(timestamp, window, mouseID, button, true); } } X11_UpdateUserTime(windowdata, time); } -void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button) +void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, unsigned long time) { SDL_Window *window = windowdata->window; const SDL_VideoData *videodata = (SDL_VideoData *)_this->internal; Display *display = videodata->display; // The X server sends a Release event for each Press for wheels. Ignore them. int xticks = 0, yticks = 0; + Uint64 timestamp = X11_GetEventTimestamp(time); + #ifdef DEBUG_XEVENTS SDL_Log("window 0x%lx: ButtonRelease (X11 button = %d)\n", windowdata->xwindow, button); #endif @@ -953,7 +976,10 @@ void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata, // see explanation at case ButtonPress button -= (8 - SDL_BUTTON_X1); } - SDL_SendMouseButton(0, window, mouseID, button, false); + if (mouseID != SDL_GLOBAL_MOUSE_ID) { + SDL_SendRawMouseButton(timestamp, mouseID, button, false); + } + SDL_SendMouseButton(timestamp, window, mouseID, button, false); } } @@ -1584,7 +1610,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) break; } - X11_HandleButtonRelease(_this, data, SDL_GLOBAL_MOUSE_ID, xevent->xbutton.button); + X11_HandleButtonRelease(_this, data, SDL_GLOBAL_MOUSE_ID, xevent->xbutton.button, xevent->xbutton.time); } break; case PropertyNotify: diff --git a/src/video/x11/SDL_x11events.h b/src/video/x11/SDL_x11events.h index af3fe83f9abdd0..4e00f04e4d6178 100644 --- a/src/video/x11/SDL_x11events.h +++ b/src/video/x11/SDL_x11events.h @@ -29,9 +29,10 @@ extern void X11_SendWakeupEvent(SDL_VideoDevice *_this, SDL_Window *window); extern bool X11_SuspendScreenSaver(SDL_VideoDevice *_this); extern void X11_ReconcileKeyboardState(SDL_VideoDevice *_this); extern void X11_GetBorderValues(SDL_WindowData *data); +extern Uint64 X11_GetEventTimestamp(unsigned long time); extern void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_KeyboardID keyboardID, XEvent *xevent); -extern void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, const float x, const float y, const unsigned long time); -extern void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button); +extern void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, float x, float y, unsigned long time); +extern void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, unsigned long time); extern SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window); extern bool X11_ProcessHitTest(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y, bool force_new_result); extern bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y); diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c index abc5efae48333b..00b1387c414c80 100644 --- a/src/video/x11/SDL_x11xinput2.c +++ b/src/video/x11/SDL_x11xinput2.c @@ -319,21 +319,13 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie) double coords[2]; double processed_coords[2]; int i; + Uint64 timestamp = X11_GetEventTimestamp(rawev->time); videodata->global_mouse_changed = true; if (is_pen) { break; // Pens check for XI_Motion instead } - if (!mouse->relative_mode) { - break; - } - - // Relative mouse motion is delivered to the window with keyboard focus - if (!SDL_GetKeyboardFocus()) { - break; - } - devinfo = xinput2_get_device_info(videodata, rawev->deviceid); if (!devinfo) { break; // oh well. @@ -350,7 +342,15 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie) } } - SDL_SendMouseMotion(0, mouse->focus, (SDL_MouseID)rawev->sourceid, true, (float)processed_coords[0], (float)processed_coords[1]); + // FIXME: Apply desktop mouse scale? + const float scale = 1.0f; + SDL_SendRawMouseMotion(timestamp, (SDL_MouseID)rawev->sourceid, processed_coords[0], processed_coords[1], scale, scale); + + // Relative mouse motion is delivered to the window with keyboard focus + if (mouse->relative_mode && SDL_GetKeyboardFocus()) { + SDL_SendMouseMotion(timestamp, mouse->focus, (SDL_MouseID)rawev->sourceid, true, (float)processed_coords[0], (float)processed_coords[1]); + } + devinfo->prev_coords[0] = coords[0]; devinfo->prev_coords[1] = coords[1]; } break; @@ -430,7 +430,7 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie) X11_HandleButtonPress(_this, windowdata, (SDL_MouseID)xev->sourceid, button, (float)xev->event_x, (float)xev->event_y, xev->time); } else { - X11_HandleButtonRelease(_this, windowdata, (SDL_MouseID)xev->sourceid, button); + X11_HandleButtonRelease(_this, windowdata, (SDL_MouseID)xev->sourceid, button, xev->time); } } } break; diff --git a/test/testrelative.c b/test/testrelative.c index d2d4ea234495d8..4320746164ab22 100644 --- a/test/testrelative.c +++ b/test/testrelative.c @@ -98,10 +98,10 @@ static void loop(void) } } } break; - case SDL_EVENT_MOUSE_RAW_MOTION: + case SDL_EVENT_RAW_MOUSE_MOTION: { - rect.x += event.maxis.dx / event.maxis.ux; - rect.y += event.maxis.dy / event.maxis.uy; + rect.x += event.raw_motion.dx * event.raw_motion.scale_x; + rect.y += event.raw_motion.dy * event.raw_motion.scale_y; } break; default: break; @@ -207,9 +207,7 @@ int main(int argc, char *argv[]) } } - if (raw) { - SDL_SetEventEnabled(SDL_EVENT_MOUSE_RAW_MOTION, true); - } + SDL_SetEventEnabled(SDL_EVENT_RAW_MOUSE_MOTION, raw); rect.x = DEFAULT_WINDOW_WIDTH / 2; rect.y = DEFAULT_WINDOW_HEIGHT / 2;