Skip to content

Commit

Permalink
[react-interactions] Tap cancels on second pointerdown
Browse files Browse the repository at this point in the history
This patch causes onTapCancel to be called whenever a second pointer interacts
with the responder target.
  • Loading branch information
necolas committed Sep 27, 2019
1 parent d1121c0 commit b889a06
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 20 deletions.
44 changes: 27 additions & 17 deletions packages/react-interactions/events/src/dom/Tap.js
Original file line number Diff line number Diff line change
Expand Up @@ -496,26 +496,29 @@ const responderImpl = {
case 'pointerdown':
case 'mousedown':
case 'touchstart': {
if (hasPointerEvents) {
const pointerId = nativeEvent.pointerId;
state.activePointerId = pointerId;
// Make mouse and touch pointers consistent.
// Flow bug: https://github.com/facebook/flow/issues/8055
// $FlowExpectedError
eventTarget.releasePointerCapture(pointerId);
} else {
if (eventType === 'touchstart') {
const targetTouches = nativeEvent.targetTouches;
if (targetTouches.length > 0) {
state.activePointerId = targetTouches[0].identifier;
}
}
if (eventType === 'mousedown' && state.ignoreEmulatedEvents) {
return;
}
if (eventType === 'mousedown' && state.ignoreEmulatedEvents) {
return;
}

if (!state.isActive) {
if (hasPointerEvents) {
const pointerId = nativeEvent.pointerId;
state.activePointerId = pointerId;
// Make mouse and touch pointers consistent.
// Flow bug: https://github.com/facebook/flow/issues/8055
// $FlowExpectedError
eventTarget.releasePointerCapture(pointerId);
} else {
if (eventType === 'touchstart') {
const targetTouches = nativeEvent.targetTouches;
if (targetTouches.length === 1) {
state.activePointerId = targetTouches[0].identifier;
} else {
return;
}
}
}

const activate = shouldActivate(event);
const activateAuxiliary = isAuxiliary(nativeEvent.buttons, event);

Expand Down Expand Up @@ -547,6 +550,13 @@ const responderImpl = {
state.initialPosition.y = gestureState.y;
dispatchStart(context, props, state);
}
} else if (
!isActivePointer(event, state) ||
(eventType === 'touchstart' && nativeEvent.targetTouches.length > 1)
) {
// Cancel the gesture if a second pointer becomes active on the target.
state.isActive = false;
dispatchCancel(context, props, state);
}
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,23 @@ describeWithPointerEvent('Tap responder', hasPointerEvents => {
expect(onTapUpdate).not.toBeCalled();
});

test('second pointer down', () => {
const pointerType = 'touch';
const target = createEventTarget(ref.current);
const buttons = buttonsType.primary;
target.pointerdown({buttons, pointerId: 1, pointerType});
if (hasPointerEvents) {
target.pointerdown({buttons, pointerId: 2, pointerType});
} else {
// TouchEvents
target.pointerdown([
{pointerId: 1, pointerType},
{pointerId: 2, pointerType},
]);
}
expect(onTapCancel).toHaveBeenCalledTimes(1);
});

testWithPointerType('pointer move outside target', pointerType => {
const downTarget = createEventTarget(ref.current);
const upTarget = createEventTarget(container);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ function getPointerType(payload) {
let pointerType = 'mouse';
if (payload != null && payload.pointerType != null) {
pointerType = payload.pointerType;
} else if (
Array.isArray(payload) &&
payload[0] != null &&
payload[0].pointerType != null
) {
pointerType = payload[0].pointerType;
}
return pointerType;
}
Expand Down Expand Up @@ -77,7 +83,12 @@ export function pointercancel(target, payload) {
export function pointerdown(target, defaultPayload) {
const dispatch = arg => target.dispatchEvent(arg);
const pointerType = getPointerType(defaultPayload);
const payload = {buttons: buttonsType.primary, ...defaultPayload};

// Payload could be an array for TouchEvents
const payload =
hasPointerEvent() || pointerType === 'mouse'
? {buttons: buttonsType.primary, ...defaultPayload}
: defaultPayload;

if (pointerType === 'mouse') {
if (hasPointerEvent()) {
Expand Down Expand Up @@ -156,8 +167,12 @@ export function pointermove(target, payload) {
export function pointerup(target, defaultPayload = {}) {
const dispatch = arg => target.dispatchEvent(arg);
const pointerType = getPointerType(defaultPayload);
// eslint-disable-next-line no-unused-vars
const {buttons, ...payload} = defaultPayload;

// Payload could be an array for TouchEvents
const payload = defaultPayload;
if (defaultPayload.buttons) {
delete payload.buttons;
}

if (pointerType === 'mouse') {
if (hasPointerEvent()) {
Expand Down

0 comments on commit b889a06

Please sign in to comment.