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), };