Fix HID mouse support with SDL precise input

Over HID, only integral scroll values can be sent. When SDL precise
scrolling is active, scroll events may include fractional values (e.g.,
0.05), which are truncated to 0 in the HID event.

To fix the problem, use the integral scroll value reported by SDL, which
internally accumulates fractional deltas.

Fixes #6156 <https://github.com/Genymobile/scrcpy/issues/6156>
PR #6172 <https://github.com/Genymobile/scrcpy/pull/6172>
This commit is contained in:
Romain Vimont 2025-06-18 18:26:13 +02:00
commit be40ee5dd9
7 changed files with 26 additions and 7 deletions

View file

@ -175,19 +175,23 @@ sc_hid_mouse_generate_input_from_click(struct sc_hid_input *hid_input,
data[3] = 0; // wheel coordinates only used for scrolling data[3] = 0; // wheel coordinates only used for scrolling
} }
void bool
sc_hid_mouse_generate_input_from_scroll(struct sc_hid_input *hid_input, sc_hid_mouse_generate_input_from_scroll(struct sc_hid_input *hid_input,
const struct sc_mouse_scroll_event *event) { const struct sc_mouse_scroll_event *event) {
if (!event->vscroll_int) {
// Need a full integral value for HID
return false;
}
sc_hid_mouse_input_init(hid_input); sc_hid_mouse_input_init(hid_input);
uint8_t *data = hid_input->data; uint8_t *data = hid_input->data;
data[0] = 0; // buttons state irrelevant (and unknown) data[0] = 0; // buttons state irrelevant (and unknown)
data[1] = 0; // no x motion data[1] = 0; // no x motion
data[2] = 0; // no y motion data[2] = 0; // no y motion
// In practice, vscroll is always -1, 0 or 1, but in theory other values data[3] = CLAMP(event->vscroll_int, -127, 127);
// are possible
data[3] = CLAMP(event->vscroll, -127, 127);
// Horizontal scrolling ignored // Horizontal scrolling ignored
return true;
} }
void sc_hid_mouse_generate_open(struct sc_hid_open *hid_open) { void sc_hid_mouse_generate_open(struct sc_hid_open *hid_open) {

View file

@ -22,7 +22,7 @@ void
sc_hid_mouse_generate_input_from_click(struct sc_hid_input *hid_input, sc_hid_mouse_generate_input_from_click(struct sc_hid_input *hid_input,
const struct sc_mouse_click_event *event); const struct sc_mouse_click_event *event);
void bool
sc_hid_mouse_generate_input_from_scroll(struct sc_hid_input *hid_input, sc_hid_mouse_generate_input_from_scroll(struct sc_hid_input *hid_input,
const struct sc_mouse_scroll_event *event); const struct sc_mouse_scroll_event *event);

View file

@ -393,6 +393,8 @@ struct sc_mouse_scroll_event {
struct sc_position position; struct sc_position position;
float hscroll; float hscroll;
float vscroll; float vscroll;
int32_t hscroll_int;
int32_t vscroll_int;
uint8_t buttons_state; // bitwise-OR of sc_mouse_button values uint8_t buttons_state; // bitwise-OR of sc_mouse_button values
}; };

View file

@ -903,6 +903,8 @@ sc_input_manager_process_mouse_wheel(struct sc_input_manager *im,
.hscroll = event->x, .hscroll = event->x,
.vscroll = event->y, .vscroll = event->y,
#endif #endif
.hscroll_int = event->x,
.vscroll_int = event->y,
.buttons_state = im->mouse_buttons_state, .buttons_state = im->mouse_buttons_state,
}; };

View file

@ -55,7 +55,9 @@ sc_mouse_processor_process_mouse_scroll(struct sc_mouse_processor *mp,
struct sc_mouse_uhid *mouse = DOWNCAST(mp); struct sc_mouse_uhid *mouse = DOWNCAST(mp);
struct sc_hid_input hid_input; struct sc_hid_input hid_input;
sc_hid_mouse_generate_input_from_scroll(&hid_input, event); if (!sc_hid_mouse_generate_input_from_scroll(&hid_input, event)) {
return;
}
sc_mouse_uhid_send_input(mouse, &hid_input, "mouse scroll"); sc_mouse_uhid_send_input(mouse, &hid_input, "mouse scroll");
} }

View file

@ -42,7 +42,9 @@ sc_mouse_processor_process_mouse_scroll(struct sc_mouse_processor *mp,
struct sc_mouse_aoa *mouse = DOWNCAST(mp); struct sc_mouse_aoa *mouse = DOWNCAST(mp);
struct sc_hid_input hid_input; struct sc_hid_input hid_input;
sc_hid_mouse_generate_input_from_scroll(&hid_input, event); if (!sc_hid_mouse_generate_input_from_scroll(&hid_input, event)) {
return;
}
if (!sc_aoa_push_input(mouse->aoa, &hid_input)) { if (!sc_aoa_push_input(mouse->aoa, &hid_input)) {
LOGW("Could not push AOA HID input (mouse scroll)"); LOGW("Could not push AOA HID input (mouse scroll)");

View file

@ -164,8 +164,15 @@ sc_screen_otg_process_mouse_wheel(struct sc_screen_otg *screen,
struct sc_mouse_scroll_event evt = { struct sc_mouse_scroll_event evt = {
// .position not used for HID events // .position not used for HID events
#if SDL_VERSION_ATLEAST(2, 0, 18)
.hscroll = event->preciseX,
.vscroll = event->preciseY,
#else
.hscroll = event->x, .hscroll = event->x,
.vscroll = event->y, .vscroll = event->y,
#endif
.hscroll_int = event->x,
.vscroll_int = event->y,
.buttons_state = sc_mouse_buttons_state_from_sdl(sdl_buttons_state), .buttons_state = sc_mouse_buttons_state_from_sdl(sdl_buttons_state),
}; };