Skip to content

Conversation

@Cwiiis
Copy link
Contributor

@Cwiiis Cwiiis commented May 21, 2025

Summary

This is a collection of changes to improve scroll handling and reconcile the difference between Firefox and Chrome. I've made scroll-wheel animations time dependent so that they aren't affected by frame-rate. I've also implemented a new heuristic for touchpad detection, that I've tested to work in Chrome on Linux. Lastly, I've made scroll-wheel scrolling ignore the given delta values and treat the events as ticks, using an internal value for the amount to scroll.

This last change should have made Firefox and Chrome behave identically wrt the scroll-wheel, but for some reason I've not been able to debug yet, Firefox scrolling is still faster than Chrome's. Scroll behaviour in Chrome is still markedly improved for me with these patches though.

For what it's worth, all the weird behaviour seems to come from Chrome. Firefox does what I expect based on documentation, Chrome had some tricky behaviour to work out. Here's a quick summary:

  • requestAnimationFrame in Chrome can call with a timestamp that's before performance.now, even when the latter is called before the call that triggers the callback.
  • Chrome wheel events are just pretty odd. For the mouse wheel, the delta is a multiple of 120 (likely depending on whether a frame was skipped or not - presumably in that situation, events are coalesced and summed).
  • Chrome wheel events have e.deltaX == -e.wheelDeltaX (and the same for y). This is handy to detect Chrome, but also has the fun side-effect that deltaX/Y are never zero, they are negative zero.
  • Chrome wheel events generated from a touch pad appear to round up to some arbitrary coordinate space. This is why touch-pad scrolling is too fast in Chrome, but at least it doesn't feel bad.

None of the above applies to Firefox, which broadly speaking, does what you might expect.

Checklist

  • I have run make prettier-write and formatted the code.
  • All commits have Change-Id
  • I have run tests with make check
  • I have issued make run and manually verified that everything looks okay
  • Documentation (manuals or wiki) has been updated or is not required

@mmeeks
Copy link
Contributor

mmeeks commented May 21, 2025

Interesting; does this mean we can add extra frames between mouse-wheel pseudo-clicks, and some physics/animation goodness too ? =)

@Cwiiis
Copy link
Contributor Author

Cwiiis commented May 21, 2025

Interesting; does this mean we can add extra frames between mouse-wheel pseudo-clicks, and some physics/animation goodness too ? =)

We're already animating for mouse wheel events, this doesn't add any new mechanisms that we didn't already have - but we could have a better animation model for this based on physics, yes 🙂

I've been thinking about why Firefox and Chrome are still different with these patches and I think Chrome must throttle wheel events differently to Firefox, perhaps only one per rendered frame where Firefox allows many? Going to experiment tomorrow to see if that's the case. It's the only obvious thing I can immediately think of...

@Cwiiis
Copy link
Contributor Author

Cwiiis commented May 22, 2025

In my local branch I've added a patch that means we only respond to one mouse-wheel event per rendered frame and still there's a difference between Firefox and Chrome. My best guess is that one or the other is truncating frame times (likely Firefox in this case, going on console output) and the error is accumulating and causing faster animation. I can probably compensate for this by rounding the time delta, just need to verify that it's the case...

@Cwiiis
Copy link
Contributor Author

Cwiiis commented May 22, 2025

Wow, yes, Firefox truncates its requestAnimationFrame timestamps to the millisecond (the first value in this output)... That's quite a lot of accumulated error over time. Chrome does what I would expect and gives an accurate timestamp to many decimal places.
image

We can compensate for this with some rounding - given we're aiming to hit the frame-rate target most of the time and we have vsync, it shouldn't be too much of an issue losing this accuracy.

@Cwiiis
Copy link
Contributor Author

Cwiiis commented May 22, 2025

Filed a Gecko bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1967935 - I'm surprised this bug exists, hopefully I've gotten something wrong somehow but I'll continue to work around it.

@Cwiiis
Copy link
Contributor Author

Cwiiis commented May 22, 2025

Finally - there were just 3 more things; The biggest thing was just not respecting dpiScale in some of these calculations and my install of Chrome for some reason having a different dpiScale to Firefox. Beyond that, I'm not sure that Firefox and Chrome treat fractional scroll distances identically and we need to make sure we only listen to one mousewheel event per frame (Chrome will only deliver one, I think Firefox will possibly deliver multiple).

On my computer, Firefox and Chrome now scroll identically (Chrome is maybe a little smoother).

@Cwiiis Cwiiis requested a review from eszkadev May 23, 2025 09:08
@gokaysatir gokaysatir self-requested a review May 23, 2025 11:45
Copy link
Contributor

@gokaysatir gokaysatir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Cwiiis :) But please make sure this goes in, in the RED code.

@github-project-automation github-project-automation bot moved this from To Review to To Test in Collabora Online May 23, 2025
@juliusknorr
Copy link
Member

On my computer, Firefox and Chrome now scroll identically (Chrome is maybe a little smoother).

@Cwiiis Just some feedback here as I took the time to try out this branch, but cannot confirm this yet. I also tested on Linux this time and put a screen recording here (left is chrome, right is firefox)

Screencast.From.2025-05-27.09-06-21.mp4

@Cwiiis
Copy link
Contributor Author

Cwiiis commented May 27, 2025

On my computer, Firefox and Chrome now scroll identically (Chrome is maybe a little smoother).

@Cwiiis Just some feedback here as I took the time to try out this branch, but cannot confirm this yet. I also tested on Linux this time and put a screen recording here (left is chrome, right is firefox)
Screencast.From.2025-05-27.09-06-21.mp4

hah, ok, Chrome sure is fun! I'll put together a test document so I can gather some data about your mouse events. Obviously some assumptions that hold true for me don't hold true for you...

@Cwiiis
Copy link
Contributor Author

Cwiiis commented May 27, 2025

@juliusknorr could you go to http://demos.chrislord.net/wheeleventviewer.html and use the mouse-wheel on Chrome and Firefox and post your results? Separately, it'd be good to do the same thing with a touchpad too, if you have a touchpad attached to your machine. Thanks!

@juliusknorr
Copy link
Member

Sure, for the linux machine just with a mouse:

Single wheel "step"

Screenshot From 2025-05-27 16-51-21

Fast scrolling down

Screenshot From 2025-05-27 16-51-46

@juliusknorr
Copy link
Member

for macOS

mouse single step

Screenshot 2025-05-27 at 16 48 06

mouse fast scroll

Screenshot 2025-05-27 at 16 48 33

touchpad scroll

Screenshot 2025-05-27 at 16 49 45

@Cwiiis
Copy link
Contributor Author

Cwiiis commented May 27, 2025

Ok, this is good - looks like Chrome's wheel steps are 60 * dpiScale, rather than the 120 that I'd assumed. I'll update this patch queue tomorrow and we can hopefully draw a line through this soon! Looks like MacOS always gives pixel values, but I assume they're sensible - if they aren't, we'd have to start user-agent sniffing I think, but I'd like to avoid that.

@Cwiiis
Copy link
Contributor Author

Cwiiis commented May 28, 2025

hmm, I only glanced at this yesterday but some of my assumptions aren't right. I think at least with Firefox it sends scroll-wheel as line-scroll events, so we can at least quickly determine if it's Firefox and behave correctly there. Not that Firefox has any problems currently, but it'll be nice to succeed fast and guard it against false-positives.

Chrome's behaviour is markedly different between Mac and Linux (fun!), I'm going to need to do more nasty things there I think... The 60*dpiScale thing seems to hold true but the delta === -wheelDelta only holds true on Linux, it looks like there's some more scale factor multiplication that's Mac-specific... Interestingly on Mac, the delta values aren't rounded for mouse-wheel only, which might be something we can rely on. Of course, that's annoying for Firefox which only sends a fractional component when using touchpad events (which makes perfect sense). We may need to store a 'quirks' property to keep track of what nonsense we're having to deal with...

Not a big fan of all of this, it's a shame Chrome behaves so wildly differently between platforms and to how you might expect (why is it sending pixel scroll events for the mouse wheel?!)

@Cwiiis Cwiiis force-pushed the private/cwiiis/scroll-fixups branch from eae221e to e32465f Compare May 28, 2025 10:17
@Cwiiis
Copy link
Contributor Author

Cwiiis commented May 28, 2025

@juliusknorr I've just pushed a new heuristic that I'm hoping will at least be good for Firefox/Chrome on Mac and Linux, but I don't have a Mac to test with - if you could check this out and let me know, that'd be much appreciated. The behaviour should be mostly identical between Firefox and Chrome, but I've said that before...

@juliusknorr
Copy link
Member

juliusknorr commented May 28, 2025

Thank you very much. Just a very quick test: I can confirm on Linux Firefox and Chrome behave the same way now. On macOS chrome is scrolling a lot faster still, though firefox seems to be as fast as my local libreoffice does scroll through the pages.

More generally, but might be a separate discussion with UX people:

Looking at the firefox behaviour right now, as I understood that is the expected scroll speed, from a user experience perspective i feel like the maximum speed that is used to scroll down is a bit too slow when comparing to native apps like Apple Pages, MS Word. It seems to be close to how fast libreoffice scrolls on the desktop however. One "benchmark" i used would be to to use a long file like the 300 page test/samples/writer-large-edit.fodt and try to scrub to the end of the document just with the scrollwheel.

@eszkadev
Copy link
Contributor

I checked on Windows: Chrome scrolls a lot faster than Firefox with this PR. Before it was almost equal, but frame rate was better on Chrome.

@Cwiiis
Copy link
Contributor Author

Cwiiis commented May 29, 2025

Ok, we aren't there yet - running the test linked above and also attaching the result of window.devicePixelRatio in the console would be helpful on any and all browsers/platforms you have.

@Cwiiis
Copy link
Contributor Author

Cwiiis commented May 29, 2025

Re: scroll speed - I think we probably want acceleration, but no point in adjusting that much until we have a consistent base to work from.

@Cwiiis
Copy link
Contributor Author

Cwiiis commented Jun 11, 2025

Did some more testing on my machine under different OS's and it just seems the mouse-wheel step value is some multiple of 60, but unrelated to the devicePixelRatio. A bit of a pain, but I can do something that works here I expect...

Cwiiis added 4 commits June 11, 2025 11:51
Previously, the scroll-wheel animation was dependent on the frame-rate.
Take into account elapsed time since the last frame when calculating
acceleration.

Signed-off-by: Chris Lord <chris.lord@collabora.com>
Change-Id: I8528c65f6b149cd657a38d5f9a48fd85da6ce2fe
Chrome's handling of wheel events is very inconsistent between platforms and
not particularly useful in general. Add a heuristic that can, for the most
part, distinguish touchpad scrolling events in Chrome.

Signed-off-by: Chris Lord <chris.lord@collabora.com>
Change-Id: I83172f3c5ef10f7746866c5722b62ea4acae47a7
Use a multiple of line-height instead of the delta given when we detect
scroll-wheel scrolling. This should increase the consistency of behaviour
between different browsers and OS's when our heuristics succeed. For some
unknown reason, Firefox still scrolls faster than Chrome.

Signed-off-by: Chris Lord <chris.lord@collabora.com>
Change-Id: If35426f50e41e019adf953a8f2740b017027e9f8
Make sure that dpiScale is taken into account when calculating mousewheel
scroll distances/limits and only listen to one mouse-wheel tick per frame.

Signed-off-by: Chris Lord <chris.lord@collabora.com>
Change-Id: I687bbff670e7d06359929559b4d9497460767c7c
@Cwiiis Cwiiis force-pushed the private/cwiiis/scroll-fixups branch from e32465f to 06a462e Compare June 11, 2025 11:06
@Cwiiis
Copy link
Contributor Author

Cwiiis commented Jun 11, 2025

@eszkadev Would you mind checking again with the latest push that behaviour is similar between Firefox/Chrome with the mouse wheel, and if it isn't, could you post your results from both browsers using the mouse-wheel on https://demos.chrislord.net/wheeleventviewer.html please?

@eszkadev
Copy link
Contributor

@Cwiiis looks amazing now :) Edge is very smooth, Firefox doesn't seem to have that level of it, but possibly due to mentioned truncated values?

Tested on Windows with mouse and touchpad (Edge, Chrome, Firefox)

@eszkadev eszkadev merged commit a106845 into master Jun 13, 2025
14 checks passed
@eszkadev eszkadev deleted the private/cwiiis/scroll-fixups branch June 13, 2025 16:13
@github-project-automation github-project-automation bot moved this from To Test to Done in Collabora Online Jun 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

5 participants