From 78c4674d97eb96452bc1b1ead0f94b7bc68e5269 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 29 Jun 2025 18:22:46 +0200 Subject: [PATCH] Handle mouse integer scrolling locally Do not rely on SDL to expose integer scroll values, as they are not available in all versions. It was reimplemented in SDL 3.2.12 by this commit: Refs #6156 --- app/src/hid/hid_mouse.c | 35 ++++++++++++++++++++++++++++------- app/src/hid/hid_mouse.h | 10 +++++++++- app/src/input_events.h | 2 -- app/src/input_manager.c | 2 -- app/src/uhid/mouse_uhid.c | 5 ++++- app/src/uhid/mouse_uhid.h | 2 ++ app/src/usb/mouse_aoa.c | 5 ++++- app/src/usb/mouse_aoa.h | 2 ++ app/src/usb/screen_otg.c | 2 -- 9 files changed, 49 insertions(+), 16 deletions(-) diff --git a/app/src/hid/hid_mouse.c b/app/src/hid/hid_mouse.c index 33f0807e..54105a17 100644 --- a/app/src/hid/hid_mouse.c +++ b/app/src/hid/hid_mouse.c @@ -166,6 +166,12 @@ sc_hid_buttons_from_buttons_state(uint8_t buttons_state) { return c; } +void +sc_hid_mouse_init(struct sc_hid_mouse *hid) { + hid->residual_hscroll = 0; + hid->residual_vscroll = 0; +} + void sc_hid_mouse_generate_input_from_motion(struct sc_hid_input *hid_input, const struct sc_mouse_motion_event *event) { @@ -192,22 +198,37 @@ sc_hid_mouse_generate_input_from_click(struct sc_hid_input *hid_input, data[4] = 0; // no horizontal scrolling } +static int8_t +consume_scroll_integer(float *scroll) { + float value = CLAMP(*scroll, -127, 127); + int8_t consume = value; // truncate towards 0 + float residual = value - consume; + *scroll = residual; + return consume; +} + bool -sc_hid_mouse_generate_input_from_scroll(struct sc_hid_input *hid_input, +sc_hid_mouse_generate_input_from_scroll(struct sc_hid_mouse *hid, + struct sc_hid_input *hid_input, const struct sc_mouse_scroll_event *event) { - if (!event->vscroll_int && !event->hscroll_int) { - // Need a full integral value for HID + sc_hid_mouse_input_init(hid_input); + + hid->residual_hscroll += event->hscroll; + hid->residual_vscroll += event->vscroll; + int8_t hscroll = consume_scroll_integer(&hid->residual_hscroll); + int8_t vscroll = consume_scroll_integer(&hid->residual_vscroll); + + if (!hscroll && !vscroll) { + // Not enough scrolling to inject a scroll event return false; } - sc_hid_mouse_input_init(hid_input); - uint8_t *data = hid_input->data; data[0] = 0; // buttons state irrelevant (and unknown) data[1] = 0; // no x motion data[2] = 0; // no y motion - data[3] = CLAMP(event->vscroll_int, -127, 127); - data[4] = CLAMP(event->hscroll_int, -127, 127); + data[3] = vscroll; + data[4] = hscroll; return true; } diff --git a/app/src/hid/hid_mouse.h b/app/src/hid/hid_mouse.h index 4ae4bfd4..6d590267 100644 --- a/app/src/hid/hid_mouse.h +++ b/app/src/hid/hid_mouse.h @@ -8,6 +8,13 @@ #define SC_HID_ID_MOUSE 2 +struct sc_hid_mouse { + float residual_hscroll; + float residual_vscroll; +}; + +void sc_hid_mouse_init(struct sc_hid_mouse *hid); + void sc_hid_mouse_generate_open(struct sc_hid_open *hid_open); @@ -23,7 +30,8 @@ sc_hid_mouse_generate_input_from_click(struct sc_hid_input *hid_input, const struct sc_mouse_click_event *event); bool -sc_hid_mouse_generate_input_from_scroll(struct sc_hid_input *hid_input, +sc_hid_mouse_generate_input_from_scroll(struct sc_hid_mouse *hid, + struct sc_hid_input *hid_input, const struct sc_mouse_scroll_event *event); #endif diff --git a/app/src/input_events.h b/app/src/input_events.h index 1e34b50e..0c022acc 100644 --- a/app/src/input_events.h +++ b/app/src/input_events.h @@ -393,8 +393,6 @@ struct sc_mouse_scroll_event { struct sc_position position; float hscroll; float vscroll; - int32_t hscroll_int; - int32_t vscroll_int; uint8_t buttons_state; // bitwise-OR of sc_mouse_button values }; diff --git a/app/src/input_manager.c b/app/src/input_manager.c index 3e4dd0f3..f7a787d1 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -903,8 +903,6 @@ sc_input_manager_process_mouse_wheel(struct sc_input_manager *im, .hscroll = event->x, .vscroll = event->y, #endif - .hscroll_int = event->x, - .vscroll_int = event->y, .buttons_state = im->mouse_buttons_state, }; diff --git a/app/src/uhid/mouse_uhid.c b/app/src/uhid/mouse_uhid.c index 869e48a4..1277ed84 100644 --- a/app/src/uhid/mouse_uhid.c +++ b/app/src/uhid/mouse_uhid.c @@ -55,7 +55,8 @@ sc_mouse_processor_process_mouse_scroll(struct sc_mouse_processor *mp, struct sc_mouse_uhid *mouse = DOWNCAST(mp); struct sc_hid_input hid_input; - if (!sc_hid_mouse_generate_input_from_scroll(&hid_input, event)) { + if (!sc_hid_mouse_generate_input_from_scroll(&mouse->hid, &hid_input, + event)) { return; } @@ -65,6 +66,8 @@ sc_mouse_processor_process_mouse_scroll(struct sc_mouse_processor *mp, bool sc_mouse_uhid_init(struct sc_mouse_uhid *mouse, struct sc_controller *controller) { + sc_hid_mouse_init(&mouse->hid); + mouse->controller = controller; static const struct sc_mouse_processor_ops ops = { diff --git a/app/src/uhid/mouse_uhid.h b/app/src/uhid/mouse_uhid.h index f117ba97..998bf21a 100644 --- a/app/src/uhid/mouse_uhid.h +++ b/app/src/uhid/mouse_uhid.h @@ -4,11 +4,13 @@ #include #include "controller.h" +#include "hid/hid_mouse.h" #include "trait/mouse_processor.h" struct sc_mouse_uhid { struct sc_mouse_processor mouse_processor; // mouse processor trait + struct sc_hid_mouse hid; struct sc_controller *controller; }; diff --git a/app/src/usb/mouse_aoa.c b/app/src/usb/mouse_aoa.c index fd5fa5e0..4bc76c54 100644 --- a/app/src/usb/mouse_aoa.c +++ b/app/src/usb/mouse_aoa.c @@ -42,7 +42,8 @@ sc_mouse_processor_process_mouse_scroll(struct sc_mouse_processor *mp, struct sc_mouse_aoa *mouse = DOWNCAST(mp); struct sc_hid_input hid_input; - if (!sc_hid_mouse_generate_input_from_scroll(&hid_input, event)) { + if (!sc_hid_mouse_generate_input_from_scroll(&mouse->hid, &hid_input, + event)) { return; } @@ -64,6 +65,8 @@ sc_mouse_aoa_init(struct sc_mouse_aoa *mouse, struct sc_aoa *aoa) { return false; } + sc_hid_mouse_init(&mouse->hid); + static const struct sc_mouse_processor_ops ops = { .process_mouse_motion = sc_mouse_processor_process_mouse_motion, .process_mouse_click = sc_mouse_processor_process_mouse_click, diff --git a/app/src/usb/mouse_aoa.h b/app/src/usb/mouse_aoa.h index 506286ba..1a25d986 100644 --- a/app/src/usb/mouse_aoa.h +++ b/app/src/usb/mouse_aoa.h @@ -6,11 +6,13 @@ #include #include "usb/aoa_hid.h" +#include "hid/hid_mouse.h" #include "trait/mouse_processor.h" struct sc_mouse_aoa { struct sc_mouse_processor mouse_processor; // mouse processor trait + struct sc_hid_mouse hid; struct sc_aoa *aoa; }; diff --git a/app/src/usb/screen_otg.c b/app/src/usb/screen_otg.c index 5c580df9..bed48eb6 100644 --- a/app/src/usb/screen_otg.c +++ b/app/src/usb/screen_otg.c @@ -171,8 +171,6 @@ sc_screen_otg_process_mouse_wheel(struct sc_screen_otg *screen, .hscroll = event->x, .vscroll = event->y, #endif - .hscroll_int = event->x, - .vscroll_int = event->y, .buttons_state = sc_mouse_buttons_state_from_sdl(sdl_buttons_state), };