Extend value range for SDK mouse scrolling

SDL precise scrolling can sometimes produce values greater than 1 or
less than -1.

On the wire, the value is encoded as a 16-bit fixed-point number.

Previously, the range was interpreted as [-1, 1], using 1 bit for the
integral part (the sign) and 15 bits for the fractional part.

To support larger values, interpret the range as [-16, 16] instead,
using 5 bits for the integral part and 11 bits for the fractional part
(which is more than enough).

PR #6172 <https://github.com/Genymobile/scrcpy/pull/6172>
This commit is contained in:
Romain Vimont 2025-06-20 09:06:10 +02:00
commit 0498459c1f
3 changed files with 13 additions and 8 deletions

View file

@ -127,10 +127,14 @@ sc_control_msg_serialize(const struct sc_control_msg *msg, uint8_t *buf) {
return 32; return 32;
case SC_CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT: case SC_CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT:
write_position(&buf[1], &msg->inject_scroll_event.position); write_position(&buf[1], &msg->inject_scroll_event.position);
int16_t hscroll = // Accept values in the range [-16, 16].
sc_float_to_i16fp(msg->inject_scroll_event.hscroll); // Normalize to [-1, 1] in order to use sc_float_to_i16fp().
int16_t vscroll = float hscroll_norm = msg->inject_scroll_event.hscroll / 16;
sc_float_to_i16fp(msg->inject_scroll_event.vscroll); hscroll_norm = CLAMP(hscroll_norm, -1, 1);
float vscroll_norm = msg->inject_scroll_event.vscroll / 16;
vscroll_norm = CLAMP(vscroll_norm, -1, 1);
int16_t hscroll = sc_float_to_i16fp(hscroll_norm);
int16_t vscroll = sc_float_to_i16fp(vscroll_norm);
sc_write16be(&buf[13], (uint16_t) hscroll); sc_write16be(&buf[13], (uint16_t) hscroll);
sc_write16be(&buf[15], (uint16_t) vscroll); sc_write16be(&buf[15], (uint16_t) vscroll);
sc_write32be(&buf[17], msg->inject_scroll_event.buttons); sc_write32be(&buf[17], msg->inject_scroll_event.buttons);

View file

@ -113,8 +113,8 @@ sc_mouse_processor_process_mouse_scroll(struct sc_mouse_processor *mp,
.type = SC_CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT, .type = SC_CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT,
.inject_scroll_event = { .inject_scroll_event = {
.position = event->position, .position = event->position,
.hscroll = CLAMP(event->hscroll, -1, 1), .hscroll = event->hscroll,
.vscroll = CLAMP(event->vscroll, -1, 1), .vscroll = event->vscroll,
.buttons = convert_mouse_buttons(event->buttons_state), .buttons = convert_mouse_buttons(event->buttons_state),
}, },
}; };

View file

@ -112,8 +112,9 @@ public class ControlMessageReader {
private ControlMessage parseInjectScrollEvent() throws IOException { private ControlMessage parseInjectScrollEvent() throws IOException {
Position position = parsePosition(); Position position = parsePosition();
float hScroll = Binary.i16FixedPointToFloat(dis.readShort()); // Binary.i16FixedPointToFloat() decodes values assuming the full range is [-1, 1], but the actual range is [-16, 16].
float vScroll = Binary.i16FixedPointToFloat(dis.readShort()); float hScroll = Binary.i16FixedPointToFloat(dis.readShort()) * 16;
float vScroll = Binary.i16FixedPointToFloat(dis.readShort()) * 16;
int buttons = dis.readInt(); int buttons = dis.readInt();
return ControlMessage.createInjectScrollEvent(position, hScroll, vScroll, buttons); return ControlMessage.createInjectScrollEvent(position, hScroll, vScroll, buttons);
} }