Skip to content

High-res scrolling support for trackball#794

Merged
mondalaci merged 6 commits intoUltimateHackingKeyboard:masterfrom
rightaditya:hires-scroll
Nov 1, 2024
Merged

High-res scrolling support for trackball#794
mondalaci merged 6 commits intoUltimateHackingKeyboard:masterfrom
rightaditya:hires-scroll

Conversation

@rightaditya
Copy link
Contributor

@rightaditya rightaditya commented Jul 25, 2024

This PR is for HID-compliant high-resolution scrolling support for the trackball. Closes #741. See this comment for notes on testing this on Linux.

TODO

  • Actually handle values in SetReport request (will require separating X and Y high-res modes)
  • Add exception(s) for Linux's broken (?) SetReport requests
  • Test on Windows
  • Use a single multiplier for both axes (try just making the multiplier global in the report, but if that doesn't work, the logical collections will have to be removed)
  • Fix mouse scroll keys not working in high res mode

@cla-sign-bot
Copy link

cla-sign-bot bot commented Jul 25, 2024

Thank you for your contribution!
Please sign the CLA.

1 similar comment
@cla-sign-bot
Copy link

cla-sign-bot bot commented Aug 1, 2024

Thank you for your contribution!
Please sign the CLA.

@rightaditya
Copy link
Contributor Author

I've added support for the high-res mode to be selectively disabled per-axis via a USB SetReport feature request, which enables support for this kind of setting via registry values in Windows. It doesn't play too well with axis locking, though. I can't think of a use case for having high-res scrolling enabled on one axis and not another, and there's really just one physical scroll device here, so IMO it'd make more sense to just have a single multiplier that applies to both wheels. This may require changing the structure of the USB descriptor.

@rightaditya
Copy link
Contributor Author

@mondalaci I figured there was no need to sign the CLA until this PR is considered ready for merging, but I can do so sooner if you need it for the CI (or just to silence the bot, lol).

@mondalaci
Copy link
Member

@rightaditya Yes, it'd make sense to sign the CLA now. A single multiplier for both axes is sufficient.

@rightaditya
Copy link
Contributor Author

Just made the change and tested it. Now on Windows, disabling high-res scrolling for a single axis via the relevant registry key only disables the OS's handling for high-res values on that axis, so scrolling on that axis becomes very sensitive (but moves in larger chunks). Disabling both axes works as expected. I can't figure who would possibly be fiddling with the registry keys to disable high-res scrolling on a single axis only, so this seems a reasonable compromise. (The two-multiplier case worked better for that case, though was still a bit janky and unnecessarily complicated the axis-locking code.)

This behaviour suggests that the firmware is handling the SetReport and GetReport requests as it should, but unfortunately I can't be 100% sure without inspecting USB packet capture logs and I can't get these on Windows since I only have it installed on a USB drive and packet capture with USBPcap doesn't work when this is the case.

Otherwise I think that the minimal stuff needed for this is all done. I could take a look at USB packet capture logs for macOS if desired to see if perhaps the OS is trying to activate high-res mode in some other way than expected.

@mondalaci
Copy link
Member

@rightaditya Thanks for the excellent work! We'll test this thoroughly, and @kareltucek may fine-tune the firmware in this respect. We'll follow up.

@rightaditya rightaditya changed the title [WIP] High-res scrolling support for trackball High-res scrolling support for trackball Aug 2, 2024
rightaditya and others added 4 commits August 13, 2024 12:39
* High-resolution mode is only enabled if a request is received to set
  the feature report. This seems to be how Linux instructs a device to
  use high-resolution mode (Windows needs testing still).
  * Currently the actual values in the SetReport request are ignored.
    This *should* be fine since this request should only be sent if the
    host supports resolution multipliers. But Windows does allow
    disabling high-resolution scrolling for individual axes, so the
    values in the request should actually get processed. (Linux doesn't
    have this functionality and, AFAICT, uses this request during
    initial setup.)
    * Linux's implementation is (I think) somewhat broken, so if the
      values are processed, there should be an exception for the Linux
      case.
* The resolution multiplier is set to 120, the maximum sensible value
  (thus providing the most overall flexibility). Summands to the wheel
  values are scaled by 120 to compensate. This is so that scroll events
  induce the same amount of scrolling in the OS regardless of whether
  high-resolution mode is used.
  * Without any configuration changes this is already noticeably
    smoother, but the minimum scroll value with the default
    configuration for the trackball (base speed 0.5, speed 0.5, and
    acceleration 1, and scroll speed divisor 8) is 7. Setting base speed
    to 0.2, speed to 0.8, acceleration to 0.9, and scroll speed divisor
    to 12 is reasonably similar in terms of mouse and scroll speed feel
    but scrolling is smoother still (especially noticeable when
    scrolling slowly). With these settings, the minimum scroll value
    sent is 2. Getting it down to 1 is the smoothest possible, but it'd
    be harder to get a similar mouse and scroll speed feel. Separate
    speed curves for scroll vs. cursor would be useful for this (but
    probably more trouble than they're worth).
Allow high-res scrolling to be selectively enabled for the two axes, as
specified by the values given in the SetReport feature request. AFAIK
only Windows supports this (via registry keys[^1]).

Beware that disabling high-res scrolling for only one axis doesn't play
too well with axis locking. I've adjusted as best as I could, but
there's ultimately no getting around it: a movement with equal physical
x and y displacement will have much larger values on the scaled axis. To
try to adjust for this, there could be some kind of extra buffer that
must be filled before scroll values are sent, but this would induce a
delay before movement is seen on the high-res axis, disrupting the
smooth, 1:1 (or nearly 1:1) feel provided by the higher resolution,
defeating its purpose (to an extent).

I think the right way to deal with this would be to change the USB
descriptor for the mouse so that there's only one resolution multiplier.
Because of the way resolution multipliers are scoped, I think the
logical groups for the wheels would have to be removed so that a single
resolution multiplier in the descriptor can apply to both wheels. At
least, this is the case from my recollection of the USB HID spec. It's
possible that OS drivers would take a global resolution multiplier to
apply to any contained logical collections that don't themselves have a
resolution multiplier specified.

[^1]: [Enhanced Wheel Support in
Windows](https://learn.microsoft.com/en-us/previous-versions/windows/hardware/design/dn613912(v=vs.85))
Merge the two wheels into a single logical collection in the HID mouse
report descriptor so that a single resolution multiplier is used for
both wheel axes together. On Windows, disabling high-resolution
scrolling for a single axis via the relevant registry key will now only
disable the OS's high-resolution handling, while the mouse will continue
to send high-res values. This means the disabled axis will scroll very
quickly but in larger chunks. Disabling high-res scrolling for both axes
in the registry works as expected.

It's unlikely anyone will ever want the single-axis case. For reference,
handling it "properly" would require going back to separate resolution
multipliers per axis (previous commit) or else adding support for
different scroll speed divisors per axis.
Plus a mild refactor.

On my Linux setup, this makes scrolling with the mouse scroll keys
noticeably smoother in high-res scroll mode than in regular (low-res)
scroll mode.
@mondalaci mondalaci merged commit 173a828 into UltimateHackingKeyboard:master Nov 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

High-resolution scrolling

2 participants