Re: Reporting high-resolution scroll events

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Jul 11, 2018 at 03:50:32PM -0700, Harry Cutts wrote:
> Hi all,
> 
> I'm currently working on supporting high-resolution scrolling, such as is found
> on a growing number of mice from Logitech and Microsoft. Below you'll find my
> proposal for reporting these events through evdev in a backwards-compatible way.
> I'd appreciate any input you might have. For a quick summary, just read the
> "Proposed solution" section.
> 
> Thanks,
> 
> Harry Cutts
> Chromium OS Touch/Input Team
> 
> 
> Background
> ==========
> 
> A lot of modern mice (mostly from Logitech but also from Microsoft) support
> high-resolution (sometimes called high-precision) scrolling, which is normally
> eight times as precise as standard scroll events. The Linux kernel does not
> currently support this feature, so the mice remain in low-resolution mode.
> 
> Objective
> =========
> 
> Report high-resolution scrolling events to user-space libraries and applications
> (e.g. libinput, Chromium OS's Aura, LibSDL...).
> 
> Requirements:
> 1. Should be backwards-compatible, that is, an application which is unaware of
>    the existence of high-res scrolling should still behave normally (instead of,
>    for example, scrolling 8 times faster on an 8x resolution mouse).
> 2. Should support horizontal scroll wheels (like the one on the Logitech MX
>    Master).
> 3. Should handle higher-resolution scroll wheels that may be produced in future
>    without requiring additional user-space changes.
> 4. Should be vendor-agnostic.
> 
> Proposed solution
> =================
> 
> When in high-resolution mode, evdev would report scroll wheel movements at high
> resolution on new axes (e.g. REL_WHEEL_HI_RES and REL_HWHEEL_HI_RES). For
> backwards compatibility, however, evdev would continue to report events on
> REL_WHEEL and REL_HWHEEL, after adjusting for the mouse's scroll resolution.
> 
> On the high-resolution axes, movement would be reported as the distance moved by
> the user's finger, in 256ths of a millimetre. For a wheel this would be
> calculated using the radius of the wheel and the angle through which it has
> turned. While it might seem more intuitive to report the angle that the wheel
> has rotated, this would require the user-space library to scale the values to
> account for the size of the wheel, as otherwise mice with very small wheels
> would seem to scroll very fast. (See "Alternatives considered" below for more
> discussion of this.)

I really like defining it through mm instead of an angle, I wish I'd have
thought of that for libinput. Having a fixed physical reference defined as
part of the axis is great because it removes the need for EVIOCGABS
equivalents on the REL axis. The question is: where is the resolution stored
and how or whether it is reported. You could get away without exposing it to
userspace at all but you'd then remove the notion of a "wheel click" on that
axis. Userspace would have to match the highres motion with the REL_WHEEL
data to guess how much motion constitutes a click. Or just accept that world
has changed and wheel clicks are out of fashion now :)

That's not bad, but it should be noted somewhere that this changes the
notion of scroll wheel axes away from the traditional clicks. Mostly
pointing this out to make sure that that is the intention here.

> For example, if the mouse scroll resolution is 8x and the user scrolls 16 mouse
> units up (which translates into 8mm of movement), evdev would report a
> REL_WHEEL_HI_RES movement of 2048 (8mm * 256) and a REL_WHEEL movement of 2. The
> resolution of the REL_WHEEL_HI_RES axis would be reported as 128 (0.5mm). An
> input library which supported high-resolution scrolling would ignore REL_WHEEL
> and use REL_WHEEL_HI_RES instead, while one that didn't would ignore
> REL_WHEEL_HI_RES (since it wouldn't know it existed) and just use REL_WHEEL.
> 
> Reporting remainders
> --------------------
> 
> Of course, the movements aren't always going to be exact multiples of
> low-resolution units, in particular when the wheel is in freewheel mode. In the
> example above, what should evdev report on REL_WHEEL if the movement is 11, or
> 15? The mouse that I tested (a Logitech MX Master 2S) reports frequent scroll
> events with small magnitudes, meaning that simply rounding the number on each
> event would stop any scrolling from happening at all (as each event would be
> rounded to 0).
> 
> Instead, we can accumulate the remainder across multiple events until it is
> greater than one (low-res) notch. For example, we get the following scroll
> events in quick succession from an 8x wheel:
> 
> Value |  Remainder | Cumulative | REL_WHEEL units reported
> ------+------------+------------+-------------------------
>    19 | 19 % 8 = 3 |          3 | 2
>    14 |          6 |  9 - 8 = 1 | 2 (1 from this event, plus 1 from the
>       |            |            |    accumulated remainder)
>    11 |          3 |          4 | 1
> 
> After these events we have an accumulated remainder of 4 left. We should
> probably also store the timestamp of the last scroll event, and discard the
> accumulated remainder if it was last added to some time ago (maybe 100ms).

remainders are tricky. Small movements can happen within the treshold
boundaries or across the threshold and produce different results.

Assume the above 8 threshold level and assume a continuous movement up/down
by 5 units. Start with a remainder of 2 and you get 7/2/7/2/7/2 - userspace
gets high res up/down events but no REL_WHEEL.  Start with a remainder of 5
and you get 10/-3/2/-3/2/-3 - userspace gets both high res and REL_WHEEL
events for every transition across the threshold. Since the remainder isn't
visible, it's hard to predict for the user.

This is a general problem with click-less wheels anyway and not a killer,
but do add this to the TODO list of things to sort out in case it's not
already on there.

Resetting the remainder on directional changes is probably the easiest
solution here but the usefulness depends on whether the data can be messy
(i.e. whether wheels can send unintended negative scroll events).

> Alternatives considered
> =======================
> 
> Different high-resolution reporting units
> -----------------------------------------
> 
> Current scroll events (on REL_(H)WHEEL axes) are reported as the number of
> "notches" that the wheel moved. The angle between these notches varies by mouse,
> but is typically assumed to be 15 degrees unless an hwdb entry [0] specifies
> otherwise. High-resolution mice (at least from Logitech) report movements as
> fractions of a notch when in high-resolution mode. Given that we will be adding
> a new pair of scrolling axes for which backwards compatibility need not be
> considered, this is a good opportunity to standardise the unit in which
> scrolling is reported.
> 
> The most obvious unit to use would be an angular one, representing the angle
> through which the wheel has been rotated, and this is indeed how libinput
> reports scroll events. However, there is variation in the size of scroll wheels
> [1], which would cause the scroll speed to vary by mouse unless this was
> accounted for by a similar set of scaling factors in something like hwdb.
> 
> Using distance moved instead removes the need for the user-space library to
> scale for the wheel size. It does require the device driver to know or guess the
> wheel size. For devices which do not expose this in any way (which is all of
> them, as far as I know) the driver can either look the size up in a hard-coded
> table or assume a sensible default.

tbh, my hopes for drivers getting this always right are ... limited, so
we'll end up with a hwdb-like quirk database *somewhere*. Because six months
after you added the driver for the ACME Supermouse, the newly released
Supermouse 2 can use the same driver but has a different resolution.

So - either a kernel update for everyone or a userspace quirk through the
hwdb. The latter is a lot easier to handle but it requires an ioctl.
 
> Using existing event codes but specifying the resolution
> --------------------------------------------------------
> 
> libinput already takes into account the angle represented by one notch of the
> scroll wheel by reading the MOUSE_WHEEL_CLICK_COUNT or MOUSE_WHEEL_CLICK_ANGLE
> properties (or their _HORIZONTAL variants) from udev/hwdb. These are currently
> only set for relatively minor adjustments, like for a mouse with 20 degree
> clicks instead of the default 15 degree, but we could set
> MOUSE_WHEEL_CLICK_COUNT as high as 65535. Ideally, of course, systemd et al
> wouldn't have to maintain lists of mice and their scroll resolutions, so we
> could report the resolution using the resolution field of the REL_(H)WHEEL event
> codes for newer user-space libraries to use.
> 
> I don't think we should use this approach, because it fails requirement 1. I had
> thought that would be OK if all major input libraries respected the hwdb
> properties, but LibSDL, a cross-platform library used by a lot of games
> (including Valve’s Source engine [3]) does not. If we changed the resolution
> being reported by evdev scrolling in these games would break, and updating
> LibSDL would not fix the problem because games generally compile libraries into
> the binary.

I agree. fwiw, the click count wasn't about adding a new axis but more
about retro-fitting existing hardware so the data makes more sense.
Adding a new axis for high-res scrolling is going to be more useful than
hoping the existing axis can be made to work.

So summary:
* mm instead of angle is good
* having 1/256mm as fixed base resolution is good
* we need an ioctl to fix/correct some devices
* we need "implementation-defined" remainder handling

Cheers,
   Peter

> [0]: https://github.com/systemd/systemd/blob/master/hwdb/70-mouse.hwdb
> [1]: For example, the Apple Mighty Mouse has a very small scroll ball.
> [2]: Citation: "Porting Source to Linux: Valve’s Lessons Learned", NVIDIA,
> retrieved on 2018-07-11 from
> https://developer.nvidia.com/sites/default/files/akamai/gamedev/docs/Porting%20Source%20to%20Linux.pdf
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux