scrcpy icon indicating copy to clipboard operation
scrcpy copied to clipboard

Handle high-precision scrolling when using notebook touchpads

Open yume-chan opened this issue 1 year ago • 3 comments

  • [x] I have checked that a similar feature request does not already exist.

Is your feature request related to a problem? Please describe. I'm investigating yume-chan/ya-webadb#396, a user reported that the scrolling speed of my client implementation, when using notebook touchpads, is super fast.

It turns out that Scrcpy is using the integer scrolling distances (x, y) from SDL, but mouse wheel events from browsers only contains high-resolution distances (and the event is firing very frequently). It's pretty hard to emulate integer scrolling distances from fractional ones,

In my testing using the native Scrcpy client with a notebook touchpad, the two-fingering scrolling works, but feels clunky.

https://user-images.githubusercontent.com/1330321/177030433-d060a577-0930-4788-a40a-ced0bfb37e9a.mp4

Describe the solution you'd like Since SDL also provides high-resolution scrolling distances (preciseX and preciseY in SDL_MouseWheelEvent), and Android accepts float values in MotionEvent.PointerCoords.setAxisValue, switch Scrcpy to use the high-precision ones. This will make scrolling on notebook touchpad super smooth.

Additional context

I tested the idea on https://github.com/Genymobile/scrcpy/compare/master...yume-chan:scrcpy:float-scroll. The result on Windows laptops is good.

https://user-images.githubusercontent.com/1330321/177030443-51cd73d8-c80d-4984-98ff-c63213d3d33a.mp4

Logged SDL mouse wheel events:

scroll x=0, y=-1, preciseX=0, preciseY=-1.38333
scroll x=0, y=0, preciseX=0, preciseY=-0.566667
scroll x=0, y=-1, preciseX=0, preciseY=-0.775
scroll x=0, y=-1, preciseX=0, preciseY=-0.541667
scroll x=0, y=-1, preciseX=0, preciseY=-0.808333
scroll x=0, y=0, preciseX=0, preciseY=-0.708333
scroll x=0, y=-1, preciseX=0, preciseY=-0.641667
scroll x=0, y=-1, preciseX=0, preciseY=-0.791667
scroll x=0, y=0, preciseX=0, preciseY=-0.458333
scroll x=0, y=-1, preciseX=0, preciseY=-0.7
scroll x=0, y=0, preciseX=0, preciseY=-0.233333
scroll x=0, y=0, preciseX=0, preciseY=-0.316667
scroll x=0, y=-1, preciseX=0, preciseY=-0.25
scroll x=0, y=0, preciseX=0, preciseY=-0.0916667
scroll x=0, y=0, preciseX=0, preciseY=-0.05
scroll x=0, y=0, preciseX=0, preciseY=-0.0416667
scroll x=0, y=0, preciseX=0, preciseY=-0.025
scroll x=0, y=0, preciseX=0, preciseY=-0.00833333
scroll x=0, y=0, preciseX=0, preciseY=-0.00833333
scroll x=0, y=0, preciseX=0, preciseY=-0.00833333
scroll x=0, y=0, preciseX=0, preciseY=0.00833333
scroll x=0, y=0, preciseX=0, preciseY=0.00833333
scroll x=0, y=0, preciseX=0, preciseY=0.0166667
scroll x=0, y=0, preciseX=0, preciseY=0.0666667
scroll x=0, y=0, preciseX=0, preciseY=0.191667
scroll x=0, y=0, preciseX=0, preciseY=0.2
scroll x=0, y=0, preciseX=0, preciseY=0.391667
scroll x=0, y=1, preciseX=0, preciseY=0.325
scroll x=0, y=0, preciseX=0, preciseY=0.625
scroll x=0, y=1, preciseX=0, preciseY=0.7
scroll x=0, y=1, preciseX=0, preciseY=0.841667
scroll x=0, y=1, preciseX=0, preciseY=0.666667
scroll x=0, y=0, preciseX=0, preciseY=0.808333
scroll x=0, y=1, preciseX=0, preciseY=0.75
scroll x=0, y=1, preciseX=0, preciseY=0.516667
scroll x=0, y=0, preciseX=0, preciseY=0.783333
scroll x=0, y=1, preciseX=0, preciseY=0.433333
scroll x=0, y=0, preciseX=0, preciseY=0.6
scroll x=0, y=1, preciseX=0, preciseY=0.308333
scroll x=0, y=0, preciseX=0, preciseY=0.15
scroll x=0, y=0, preciseX=0, preciseY=0.6
scroll x=0, y=1, preciseX=0, preciseY=0.0833333
scroll x=0, y=0, preciseX=0, preciseY=0.0916667
scroll x=0, y=0, preciseX=0, preciseY=0.05
scroll x=0, y=0, preciseX=0, preciseY=0.0333333
scroll x=0, y=0, preciseX=0, preciseY=0.00833333
scroll x=0, y=0, preciseX=0, preciseY=0.00833333
scroll x=0, y=0, preciseX=0, preciseY=0.00833333

The value can exceed 1/-1 when scrolling fast, but looks like Android only accepts value between -1 and 1

yume-chan avatar Jul 03 '22 07:07 yume-chan

Thank you for the report :+1: A PR is welcome :wink:

Some first remarks on your branch.

The preciseX/preciseY fields have been added in SDL 2.0.18, so a fallback method using x and y must be kept (using SDL_VERSION_ATLEAST(2, 0, 18)).

The vscroll and hscroll in struct sc_mouse_scroll_event should be floats, and serialized as fixed point values (cf how pressure is handled).

rom1v avatar Jul 03 '22 17:07 rom1v

OK. Should I also clamp the value to -1~1 and/or shorten the fields to 16 bits (short) each like pressure? The documentation of MotionEvent.AXIS_HSCROLL(https://developer.android.com/reference/android/view/MotionEvent#AXIS_HSCROLL) says the range is -1 to 1.

yume-chan avatar Jul 04 '22 05:07 yume-chan

Should I also clamp the value to -1~1

I think so.

and/or shorten the fields to 16 bits (short) each like pressure?

I would say yes, I guess 16 bits is sufficient (and for consistency with pressure).

rom1v avatar Jul 04 '22 13:07 rom1v

Fixed by #3369.

rom1v avatar Aug 28 '22 13:08 rom1v