Replace QScroller with custom KineticScroller. - #327
Conversation
4e67bb3 to
c31e373
Compare
4ee73c5 to
a7ed8d7
Compare
|
Last stylistic thing I see right now: both new .cpp and .h seem to use spaces rather than tabs. And to technical things:
|
72cac0f to
3ca8239
Compare
I don't think they do.
All three implemented (as separate commits for now, lmk if I should fixup). |
b339eed to
7e54a46
Compare
| const auto vertical = verticalScrollBar(); | ||
| const auto wasX = horizontal->value(); | ||
| const auto wasY = vertical->value(); | ||
| horizontal->setValue(wasX - delta.x()); |
There was a problem hiding this comment.
Why this is done? Now that KineticScroller produces wheel events, QScrollArea should handle it just fine by itself!
| _target->mapFromGlobal(global), | ||
| global, | ||
| pixel, | ||
| pixel * kPixelToAngleDelta, |
There was a problem hiding this comment.
Maybe count kinetic effect from both pixel and angle delta instead of emulating angle delta from pixel delta? Or is it not possible?
d76569a to
23b583f
Compare
5757c0d to
32f0b57
Compare
This reverts commit 1b34cf4.
QScroller has: 1. A bad inertia curve (all of the default ones). 2. A bad initial acceleration estimation. These can't be properly tuned, so the only option is to reimplement QScroller. This implementation's maths is based on Chromium and GTK4.
This only existed because QScroller couldn't watch mouse events itself. KineticScroller already event-filters its frame window, so stopping the fling on real pointer activity belongs to its Scrolling state.
Avoids duplicating the delta application logic: the scroller now only measures the release velocity from the gesture stream, and the fling comes back as a synthesized momentum event stream handled by the very same wheel path as the native macOS momentum streams. Both channels are recorded and replayed in the device's own raw units (only the Wayland multiplier is pre-applied, since ScrollDeltaF skips it for synthesized events), so even the stock Qt wheel handling applies the fling at the drag's own rate, and ScrollArea needs no custom path.
The synthesized momentum deltas are truncated to whole pixels per tick, so the velocity tracked back from them reads zero in the slow tail of a fling and suppressed the spring. The scroller's closed-form velocity is exact at any instant, so use it instead.
32f0b57 to
412b788
Compare
| #include "ui/ui_utility.h" | ||
| #include "ui/effects/animations.h" | ||
| #include "ui/widgets/kinetic_scroller.h" | ||
| #include "ui/widgets/kinetic_scroller.h" // For kOptionKineticScroller. |
| || (delta < 0 && was == bar->maximum()))) { | ||
| // The fling ran into the end of the range. | ||
| _scroller->stop(); | ||
| if (ev->phase() == Qt::ScrollMomentum) { |
There was a problem hiding this comment.
Why do we need to special case kinetic scroller here?
| return false; | ||
| } | ||
| } | ||
| _target = target.get(); |
There was a problem hiding this comment.
Why do we care about widgets?
| return true; | ||
| } | ||
| const auto phase = e->phase(); | ||
| const auto scroller = (phase != Qt::NoScrollPhase) |
There was a problem hiding this comment.
Why do we need to special case kinetic scroller here?
QScrollerhas:These can't be properly tuned, so the only option is to reimplement
QScroller.This implementation's maths is based on Chromium and GTK4.
This also replaces the screen refresh rate heuristics with proper frame scheduling (vsync-accurate).
KineticScrolleralso exposes velocity directly, allowing more precise overscroll behavior without relying on estimated velocity from rounded per-tick deltas (fixing the spring suppression in the slow fling tails).