Mouse-wheel scrolling feels jerky on macOS

macOS hands a mouse wheel to applications as a sequence of discrete clicks, while a trackpad gets continuous gestures. Making the wheel feel smooth means intercepting those clicks and re-emitting them frame by frame — and that is where three real traps live.

What macOS actually does with a wheel

A trackpad reports a continuous gesture — the system receives a stream of positions and knows the finger is still moving. A mouse wheel reports discrete clicks. One notch is one event, with a line count attached, and macOS hands it to the app and forgets about it.

So a wheel does not "scroll badly" because something is broken. It jumps because that is what it was asked to do: one notch, one jump. Applications that smooth wheel input do it themselves; most do not.

The mechanism that actually fixes it

There are three steps, and all three matter:

This is the architecture the open-source MOS popularised, and it is the right one — our scroll engine mirrors it rather than inventing a worse wheel.

Trap 1 — not every wheel notch means "scroll"

This is the one that bites. In Photos, Maps, Keynote, Numbers, and most spreadsheets, one wheel notch is not a scroll at all — it is a zoom step or a page turn.

Smoothed, that step keeps arriving long after you let go. A photo jumps from 80% to 200%. A slide show skips a dozen pages. Users then work around it with per-app whitelists — which is exactly the manual labour a feature like this is supposed to remove.

So before reshaping an event, the engine asks one question: scroll or zoom? Zoom-semantic events are passed straight through, untouched. The same goes for applications whose wheel is already line-precise — shaping them again makes them worse, not better.

Trap 2 — the display link that quietly becomes a zombie

CVDisplayLink does not always survive the night. After a display wake, or a reconfiguration (a cable, a KVM, a resolution change), it can stop delivering callbacks while still reporting that it is running.

If nothing checks, the visible symptom is scroll that simply stops animating — and, from the outside, an app that "randomly broke". The fix is unglamorous: assume the link can die, detect it, and rebuild it.

Trap 3 — two tools fighting over the same wheel

Two event taps at the same level both consume the wheel. Each engine sees the other’s swallowed events as missing input and its own re-emitted events as new input. The two interpolators then chase each other, and the result is scrolling that stutters, doubles, or stops outright.

Users reasonably conclude that the newest tool broke their scrolling. Naming the conflict — "another scroll utility is running" — is far more useful than leaving someone to debug it blind.

If scrolling is bad right now, check these first

Honest limits

Smoothing is reshaping input, not creating it. It adds a small amount of latency by construction, and it cannot make an app that ignores point-precise deltas behave. Where a wheel is already behaving correctly, the right answer is to leave it alone — which is why the semantic and precise-input checks exist at all.

Related

Dimming on a schedule walks the screen to black · How do I change the brightness of an external display? · Mouse acceleration will not stay off · All guides · DDC/CI not responding · Brightness resets after sleep · Text looks blurry · Colours look washed out · Which app should you use?