Accumulate VALUE120 high-res discrete scrolling events - #9128
Conversation
|
The correct fix for this would be to pass the fact that these are 120th of line units in the flags parameter of GLFWscrollfun() and then change the code in mouse.c that handles them to use that information to actually scroll by 120th of a line. IIRC only the first four bits of flags is currently used so you can use bit 5 for it. |
5d25a94 to
65cdd9e
Compare
Thanks, done. I didn't look at first and I assumed the GLFWscrollfun was some library code. I realized that we currently do not handle the case when the two scroll axes are different types, e.g. one is continuous and another is discrete. But that would only be a problem with some very small minority of pointing devices. |
|
I dont quite follow the logic. In mouse.c you are treating a VALUE120 s = offset * cell_height / 120 rather than s = offset / cell_height In other words a value of 120 should cause a scroll by one line. |
65cdd9e to
80a9bdb
Compare
|
You're right, my bad. How's that? |
On a high resolution wheel one physical detent is delivered as several VALUE120 fragments, and those fragments do not reliably total 120 units. Measured on a Logitech MX Master 3 under GNOME/Wayland, single detents ranged from 96 to 152 units, with 96% of them falling between 0.80 and 1.40 lines. scale_scroll() carries pending_scroll_pixels across events and never resets it, so residual left over from a previous detent, possibly in the opposite direction, has to be cancelled before any line can be emitted. A detent is therefore often consumed entirely and does not scroll at all. Measured over 96 detents, against a terminal program that had requested mouse events, 47% of detents that reversed direction scrolled nothing, as did 14% of detents continuing in the same direction. Treat an idle gap or a direction reversal as the start of a new detent, discard the stale residual, and emit a line as soon as the detent is unambiguous rather than waiting for a full line to accumulate. Both decisions are taken on an incoming fragment rather than on a timer, so no latency is added. This preserves the accumulating behaviour added in kovidgoyal#9128 for devices that stream many small VALUE120 events: within a continuous same-direction stream nothing changes, and fragments too small to be a detent still scroll nothing. Measured after the change, over 118 detents, no detent failed to scroll, in either direction.
On a high resolution wheel one physical detent is delivered as several VALUE120 fragments, and those fragments do not reliably total 120 units. Measured on a Logitech MX Master 3 under GNOME/Wayland, single detents ranged from 96 to 152 units, with 96% of them falling between 0.80 and 1.40 lines. scale_scroll() carries pending_scroll_pixels across events and never resets it, so residual left over from a previous detent, possibly in the opposite direction, has to be cancelled before any line can be emitted. A detent is therefore often consumed entirely and does not scroll at all. Measured over 96 detents, against a terminal program that had requested mouse events, 47% of detents that reversed direction scrolled nothing, as did 14% of detents continuing in the same direction. Treat an idle gap or a direction reversal as the start of a new detent, discard the stale residual, and emit a line as soon as the detent is unambiguous rather than waiting for a full line to accumulate. Both decisions are taken on an incoming fragment rather than on a timer, so no latency is added. This preserves the accumulating behaviour added in kovidgoyal#9128 for devices that stream many small VALUE120 events: within a continuous same-direction stream nothing changes, and fragments too small to be a detent still scroll nothing. Measured after the change, over 118 detents, no detent failed to scroll, in either direction.
Fixes a bug where VALUE120 scroll events with value < 1 line would always scroll a full line, leading to strange-feeling scrolling behavior on smooth-scrolling input devices.
Explanation: