Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 54 additions & 55 deletions src/hooks/useTrackpadGesture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export const useTrackpadGesture = (
const ongoingTouches = useRef<TrackedTouch[]>([]);
const moved = useRef(false);
const startTimeStamp = useRef(0);
const lastEndTimeStamp = useRef(0);
const releasedCount = useRef(0);
const dragging = useRef(false);
const draggingTimeout = useRef<NodeJS.Timeout | null>(null);
Expand All @@ -39,6 +38,57 @@ export const useTrackpadGesture = (
// Helpers
const findTouchIndex = (id: number) => ongoingTouches.current.findIndex(t => t.identifier === id);

const processMovement = (sumX: number, sumY: number) => {
if (dragging.current) {
send({
type: 'move',
dx: Math.round(sumX * sensitivity * 10) / 10,
dy: Math.round(sumY * sensitivity * 10) / 10
});
return;
}
const invertMult = invertScroll ? -1 : 1;
if (!scrollMode && ongoingTouches.current.length === 2) {
const dist = getTouchDistance(ongoingTouches.current[0], ongoingTouches.current[1]);
const delta = lastPinchDist.current !== null ? dist - lastPinchDist.current : 0;
if (pinching.current || Math.abs(delta) > PINCH_THRESHOLD) {
pinching.current = true;
lastPinchDist.current = dist;
send({ type: 'zoom', delta: delta * sensitivity * invertMult });
} else {
lastPinchDist.current = dist;
send({
type: 'scroll',
dx: -sumX * sensitivity * invertMult,
dy: -sumY * sensitivity * invertMult
});
}
} else if (scrollMode || ongoingTouches.current.length === 2) {
let scrollDx = sumX;
let scrollDy = sumY;
if (scrollMode) {
const absDx = Math.abs(scrollDx);
const absDy = Math.abs(scrollDy);
if (absDx > absDy * axisThreshold) {
scrollDy = 0;
} else if (absDy > absDx * axisThreshold) {
scrollDx = 0;
}
}
send({
type: 'scroll',
dx: Math.round(-scrollDx * sensitivity * 10 * invertMult) / 10,
dy: Math.round(-scrollDy * sensitivity * 10 * invertMult) / 10
});
} else if (ongoingTouches.current.length === 1) {
send({
type: 'move',
dx: Math.round(sumX * sensitivity * 10) / 10,
dy: Math.round(sumY * sensitivity * 10) / 10
});
}
};

const handleDraggingTimeout = () => {
draggingTimeout.current = null;
send({ type: 'click', button: 'left', press: false });
Expand Down Expand Up @@ -75,7 +125,6 @@ export const useTrackpadGesture = (
}

setIsTracking(true);
lastEndTimeStamp.current = 0;

// If we're in dragging timeout, convert to actual drag
if (draggingTimeout.current) {
Expand Down Expand Up @@ -131,57 +180,9 @@ export const useTrackpadGesture = (
tracked.timeStamp = e.timeStamp;
}

// Send movement if we've moved and not in timeout period
if (moved.current && e.timeStamp - lastEndTimeStamp.current >= TOUCH_TIMEOUT) {
// Apply Inversion Factor (Client Side)
const invertMult = invertScroll ? -1 : 1;

if (!scrollMode && ongoingTouches.current.length === 2) {
const dist = getTouchDistance(ongoingTouches.current[0], ongoingTouches.current[1]);
const delta = lastPinchDist.current !== null ? dist - lastPinchDist.current : 0;

if (pinching.current || Math.abs(delta) > PINCH_THRESHOLD) {
pinching.current = true;
lastPinchDist.current = dist;
// Zoom inversion typically matches scroll inversion preference
send({ type: 'zoom', delta: delta * sensitivity * invertMult });
} else {
lastPinchDist.current = dist;
send({
type: 'scroll',
dx: -sumX * sensitivity * invertMult,
dy: -sumY * sensitivity * invertMult
});
}
} else if (scrollMode) {
// Scroll mode: single finger scrolls, or two-finger scroll in cursor mode
let scrollDx = sumX;
let scrollDy = sumY;
const absDx = Math.abs(scrollDx);
const absDy = Math.abs(scrollDy);
if (scrollMode) {
if (absDx > absDy * axisThreshold) {
// Horizontal is dominant - ignore vertical
scrollDy = 0;
} else if (absDy > absDx * axisThreshold) {
// Vertical is dominant - ignore horizontal
scrollDx = 0;
}
}
send({
type: 'scroll',
dx: Math.round(-scrollDx * sensitivity * 10 * invertMult) / 10 ,
dy: Math.round(-scrollDy * sensitivity * 10 * invertMult) / 10
});
} else if (ongoingTouches.current.length === 1 || dragging.current) {
// Cursor movement (only in cursor mode with 1 finger, or when dragging)
// Inversion usually does NOT apply to pointer movement, only scroll/zoom
send({
type: 'move',
dx: Math.round(sumX * sensitivity * 10) / 10 ,
dy: Math.round(sumY * sensitivity * 10) / 10
});
}
// Send movement if we've moved
if (moved.current) {
processMovement(sumX, sumY);
}
};

Expand All @@ -197,8 +198,6 @@ export const useTrackpadGesture = (
}
}

lastEndTimeStamp.current = e.timeStamp;

if (ongoingTouches.current.length < 2) {
lastPinchDist.current = null;
pinching.current = false;
Expand Down