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
This commit is contained in:
schroda
2025-05-21 22:55:57 +02:00
parent fe30c8e281
commit 4452a9fc5c

View File

@@ -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,