On Thu, Jul 12, 2018 at 12:50 AM Harry Cutts <hcutts@xxxxxxxxxxxx> 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. Hi Harry, FYI, there was also a discussion regarding High res events last year, lead by Mauro: https://www.spinics.net/lists/linux-doc/msg44752.html The outcome was not clear and this is why we never merged the series. IIRC, the discussion ended up on how are we going to forward the REL_WHEEL resolution, and there is no simple answer to that. > > 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. Generally speaking, forwarding twice the same event with different resolution is a bad idea. This may introduce errors with the blind evdev xorg driver. Cheers, Benjamin > > 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.) > > 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). > > 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. > > 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. > > [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