It looks like scrollwheel in the main output uses the wrong math

Posted by Fiendish on Sat 15 Feb 2020 07:02 PM — 5 posts, 20,785 views.

USA Global Moderator #0
For details see: https://devblogs.microsoft.com/oldnewthing/20030807-00/?p=42963

https://github.com/nickgammon/mushclient/blob/e3ac17980c5e63cdd5c56b04d1f5e9add8dd5935/mushview.cpp#L5255-L5256

and

https://github.com/nickgammon/mushclient/blob/e3ac17980c5e63cdd5c56b04d1f5e9add8dd5935/mushview.cpp#L5294-L5295

both just divide the zDelta value by WHEEL_DELTA and then multiply by a line quantity to convert a scroll movement into a set number of lines. On my machine with high precision tracking, that makes scrolling slowly (where zDelta < WHEEL_DELTA) impossible because zDelta always gets zeroed by the division and nothing is ever carried over.

This makes scrolling slowly on my laptop trackpad with small zdelta quite unsatisfying because I have to be aggressive for the display to move at all.

See also this video, which compares MUSHclient's inbuilt scrolling with synthetic scrolling from a splitscreen plugin I made.
https://youtu.be/onlsSs9TCrU

In the video, scroll events when the cursor is above the horizontal split go directly to the client. Scroll events from below the split line go to the plugin where I just don't do anything with WHEEL_DELTA ( https://github.com/fiendish/aardwolfclientpackage/blob/632240d1288d9c63823da9b1b96f0e10f28280f6/MUSHclient/worlds/plugins/aard_splitscreen_scrollback.xml#L298 ).

Notice how scrolling slowly above the split often results in no movement at all, whereas scrolling below the split actually results in the desired amount of movement (though not line-by-line in this video).
Amended on Sun 16 Feb 2020 08:19 PM by Fiendish
Australia Forum Administrator #1
What do you suggest? Multiply before the divide?
USA Global Moderator #2
The Best Practices Guidlines from Microsoft says:
Quote:
It is preferable for the application to scroll the view a fractional number of lines if possible. If this is not possible, the view should be scrolled a whole number of lines, and any remainder should be accumulated and added to the next lines-to-scroll result. The remainder must be zeroed when the wheel rotation switches directions or when window focus changes.

https://docs.microsoft.com/en-us/previous-versions/ms997498(v=msdn.10)#vertical-scrolling

So the ideal scenario would be to not try to snap to whole lines at all, but the alternative solution should be to accumulate the non-integer part of the division like shown in the devblogs.microsoft.com link.

Old mouse wheels only registered movement on whole clicks and they all generated zDeltas of 120 per click, but modern devices can register movement at much smaller intervals and generate zDeltas much smaller than or much greater than 120 based on the actual velocity of movement. My trackpad goes all the way down to 6. My mouse goes from 26 to over 32000 (possibly even higher). Obviously the high end doesn't matter as much, but the low end matters a lot because small movements currently get clipped to 0 instead of accumulating.
Amended on Sun 16 Feb 2020 07:43 PM by Fiendish
USA Global Moderator #3
This is a plugin miniwindow equivalent of what I'm pretty sure should be happening inside MUSHclient to have correct line-snapping behavior:


WHEEL_DELTA = 120
LINES_TO_SCROLL = 3

accumulator = 0
function ScrollMain(flags, hotspot_id)
   if bit.band (flags, miniwin.wheel_scroll_back) ~= 0 then
      if direction == -1 then
         accumulator = 0
      end
      direction = 1   -- wheel scrolled down
   else
      if direction == 1 then
         accumulator = 0
      end
      direction = -1  -- wheel scrolled up
   end
   local zDelta = bit.shr(flags, 16)
   local delta_lines = accumulator + ((zDelta / WHEEL_DELTA) * LINES_TO_SCROLL)
   accumulator = delta_lines % 1
   local delta = math.floor(delta_lines) * GetInfo(212)
   if delta == 0 then
      return
   end
   SetScroll(GetInfo(296) + delta*direction, GetInfo(120))
end


Though really LINES_TO_SCROLL would have to come from the OS, but I don't have a way to grab that in pure Lua.
Amended on Sun 16 Feb 2020 11:40 PM by Fiendish
Australia Forum Administrator #4
Try this, it should work better (I multiplied before dividing, which should reduce the instances of getting a zero result from the divide).


https://github.com/nickgammon/mushclient/commit/5c40012