diff --git a/src/components/Trackpad/TouchArea.tsx b/src/components/Trackpad/TouchArea.tsx index 03c367e8..16062095 100644 --- a/src/components/Trackpad/TouchArea.tsx +++ b/src/components/Trackpad/TouchArea.tsx @@ -7,6 +7,7 @@ interface TouchAreaProps { onTouchStart: (e: React.TouchEvent) => void onTouchMove: (e: React.TouchEvent) => void onTouchEnd: (e: React.TouchEvent) => void + onTouchCancel: (e: React.TouchEvent) => void } } @@ -32,6 +33,7 @@ export const TouchArea: React.FC = ({ onTouchStart={handleStart} onTouchMove={handlers.onTouchMove} onTouchEnd={handlers.onTouchEnd} + onTouchCancel={handlers.onTouchCancel} onMouseDown={handlePreventFocus} >
diff --git a/src/hooks/useTrackpadGesture.ts b/src/hooks/useTrackpadGesture.ts index 66f801d8..16d467d2 100644 --- a/src/hooks/useTrackpadGesture.ts +++ b/src/hooks/useTrackpadGesture.ts @@ -254,12 +254,41 @@ export const useTrackpadGesture = ( } } + const handleTouchCancel = () => { + // Clear all active touches + ongoingTouches.current.clear() + + // Reset gesture state + setIsTracking(false) + moved.current = false + releasedCount.current = 0 + + // Reset pinch state + lastPinchDist.current = null + pinching.current = false + + // Clear dragging timeout if exists + if (draggingTimeout.current) { + clearTimeout(draggingTimeout.current) + draggingTimeout.current = null + } + + // Release drag if active + if (dragging.current) { + dragging.current = false + } + + // 🔥 Safety: ensure no stuck mouse state + send({ type: "click", button: "left", press: false }) + } + return { isTracking, handlers: { onTouchStart: handleTouchStart, onTouchMove: handleTouchMove, onTouchEnd: handleTouchEnd, + onTouchCancel: handleTouchCancel, }, } }