From 4452a9fc5ce3e3d6b786c62c826b63ffeeda0425 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Wed, 21 May 2025 22:55:57 +0200 Subject: [PATCH] Handle trackpad scrolling in continuous vertical pager Trackpads fire "wheel" events as if they were a mouse. This is a problem because trackpads can scroll horizontally without having "shift" pressed. In that case, the hook causes the horizontal scrolling on trackpads to break, since it just inverts it, as if it was a vertical scroll. Fixes #951 --- ...seReaderHorizontalModeInvertXYScrolling.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/modules/reader/hooks/useReaderHorizontalModeInvertXYScrolling.ts b/src/modules/reader/hooks/useReaderHorizontalModeInvertXYScrolling.ts index 49ee1dcd..d6415527 100644 --- a/src/modules/reader/hooks/useReaderHorizontalModeInvertXYScrolling.ts +++ b/src/modules/reader/hooks/useReaderHorizontalModeInvertXYScrolling.ts @@ -24,9 +24,39 @@ export const useReaderHorizontalModeInvertXYScrolling = ( return () => {}; } + let previousDeltaX: number | undefined; + let previousDeltaY: number | undefined; + + // Trackpads can be identified by checking the delta values. + // For a trackpad these values are not consistent since it basically behaves like scrolling via touch. + // While for a mouse the values should always have the same value because each wheel turn scrolls the same exact amount. + let isTrackpad: boolean | undefined; + const handleScroll = (e: WheelEvent) => { + // Trackpads can scroll horizontally without the need of having "shift" pressed. + // This is a problem because the hook will consider this to be a vertical scroll event and will invert it, which + // breaks scrolling horizontally on trackpads. + if (isTrackpad === true) { + return; + } + e.preventDefault(); + const isConsistentDeltaX = !Math.abs(Math.abs(previousDeltaX ?? e.deltaX) - Math.abs(e.deltaX)); + const isConsistentDeltaY = !Math.abs(Math.abs(previousDeltaY ?? e.deltaY) - Math.abs(e.deltaY)); + + previousDeltaX = e.deltaX; + previousDeltaY = e.deltaY; + + if (!isTrackpad) { + isTrackpad = !isConsistentDeltaX || !isConsistentDeltaY; + } + + const preventInversion = isTrackpad === undefined; + if (preventInversion) { + return; + } + if (e.shiftKey) { scrollElementRef.current?.scrollBy({ top: e.deltaY,