Do not apply synthetic momentum for mouse wheel based scrolling by default

Many mice wheels have their own physical momentum
This commit is contained in:
Kovid Goyal
2025-12-12 23:10:57 +05:30
parent 959e7e6c58
commit 695162a2e9
+10 -7
View File
@@ -54,6 +54,8 @@ class MomentumSettings(NamedTuple):
# How much to scale scroll amounts by
x_multiplier: float = 1
y_multiplier: float = 1
# Synthesize momentum for mouse wheels or trackpads that send NoScrollPhase events
synthesize_without_gestures: bool = False
class MomentumScroller:
@@ -63,7 +65,7 @@ class MomentumScroller:
Behavior by platform/device:
- macOS trackpad: Uses system-provided momentum (ScrollMomentum phase)
- Linux trackpad: Has phases but sometimes no momentum, so we synthesize it when needed
- Mouse wheel (all platforms): No phases, we synthesize momentum
- Mouse wheel (all platforms): No phases, we synthesize momentum if enabled in settings
'''
def __init__(self, scroll_area: QAbstractScrollArea, settings: MomentumSettings = MomentumSettings()):
@@ -113,14 +115,14 @@ class MomentumScroller:
match event.phase():
case Qt.ScrollPhase.NoScrollPhase:
# Record sample
# typically generated by mouse wheel and on windows
if not self.settings.synthesize_without_gestures:
return False
self.samples.append(ScrollSample(dx, dy, current_time))
# Apply immediate scroll
self._do_scroll(dx, dy)
# Reset momentum timer - will start coasting after input stops
self.momentum_timer.stop()
self.momentum_timer.start(self.settings.timer_interval_ms)
self._last_scroll_end_time = current_time
self._do_scroll(dx, dy)
self.momentum_timer.start(self.settings.timer_interval_ms)
case Qt.ScrollPhase.ScrollBegin:
# User started a new scroll gesture
@@ -335,7 +337,8 @@ class MomentumScrollMixin:
if (not self._momentum_scroller.settings.enable_x and event.angleDelta().x() != 0) or (
not self._momentum_scroller.settings.enable_y and event.angleDelta().y() != 0):
return super().wheelEvent(event)
self._momentum_scroller.handle_wheel_event(event)
if not self._momentum_scroller.handle_wheel_event(event):
return super().wheelEvent(event)
event.accept()
def stopMomentumScroll(self):