Skip to content

Commit

Permalink
[react-interactions] Improve consistency of Tap responder (#16837)
Browse files Browse the repository at this point in the history
Makes sure that touch events with modifier keys behave the same way as other
pointer types (i.e., does not call `onTapStart` if the gesture begins with a
modifier key held down)
  • Loading branch information
necolas authored Sep 23, 2019
1 parent 70754f1 commit 312b462
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 31 deletions.
32 changes: 16 additions & 16 deletions packages/react-interactions/events/src/dom/Tap.js
Original file line number Diff line number Diff line change
Expand Up @@ -350,23 +350,26 @@ function isActivePointer(
}
}

function isAuxiliary(buttons: number, nativeEvent: any): boolean {
function isAuxiliary(buttons: number, event: ReactDOMResponderEvent): boolean {
const nativeEvent: any = event.nativeEvent;
const isPrimaryPointer =
buttons === buttonsEnum.primary || event.pointerType === 'touch';
return (
// middle-click
buttons === buttonsEnum.auxiliary ||
// open-in-new-tab
(buttons === buttonsEnum.primary && nativeEvent.metaKey) ||
(isPrimaryPointer && nativeEvent.metaKey) ||
// open-in-new-window
(buttons === buttonsEnum.primary && nativeEvent.shiftKey)
(isPrimaryPointer && nativeEvent.shiftKey)
);
}

function shouldActivate(event: ReactDOMResponderEvent): boolean {
const nativeEvent: any = event.nativeEvent;
const pointerType = event.pointerType;
const buttons = nativeEvent.buttons;
const isValidButton = buttons === buttonsEnum.primary;
return pointerType === 'touch' || (isValidButton && !hasModifierKey(event));
const isPrimaryPointer =
nativeEvent.buttons === buttonsEnum.primary ||
event.pointerType === 'touch';
return isPrimaryPointer && !hasModifierKey(event);
}

/**
Expand Down Expand Up @@ -514,10 +517,7 @@ const responderImpl = {

if (!state.isActive) {
const activate = shouldActivate(event);
const activateAuxiliary = isAuxiliary(
nativeEvent.buttons,
nativeEvent,
);
const activateAuxiliary = isAuxiliary(nativeEvent.buttons, event);

if (activate || activateAuxiliary) {
state.buttons = nativeEvent.buttons;
Expand All @@ -531,7 +531,9 @@ const responderImpl = {
}
}

if (activate) {
if (activateAuxiliary) {
state.isAuxiliaryActive = true;
} else if (activate) {
const gestureState = createGestureState(
context,
props,
Expand All @@ -544,8 +546,6 @@ const responderImpl = {
state.initialPosition.x = gestureState.x;
state.initialPosition.y = gestureState.y;
dispatchStart(context, props, state);
} else if (activateAuxiliary) {
state.isAuxiliaryActive = true;
}
}
break;
Expand Down Expand Up @@ -611,7 +611,7 @@ const responderImpl = {
if (state.isActive && isActivePointer(event, state)) {
state.gestureState = createGestureState(context, props, state, event);
state.isActive = false;
if (isAuxiliary(state.buttons, nativeEvent)) {
if (isAuxiliary(state.buttons, event)) {
dispatchCancel(context, props, state);
dispatchAuxiliaryTap(context, props, state);
// Remove the root events here as no 'click' event is dispatched
Expand All @@ -626,7 +626,7 @@ const responderImpl = {
}
} else if (
state.isAuxiliaryActive &&
isAuxiliary(state.buttons, nativeEvent)
isAuxiliary(state.buttons, event)
) {
state.isAuxiliaryActive = false;
state.gestureState = createGestureState(context, props, state, event);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,29 +302,31 @@ describeWithPointerEvent('Tap responder', hasPointerEvents => {
expect(onTapStart).toHaveBeenCalledTimes(1);
});

test('ignored buttons and modifiers', () => {
testWithPointerType('ignored buttons and modifiers', pointerType => {
const target = createEventTarget(ref.current);
const primary = buttonsType.primary;
// right-click
target.pointerdown({buttons: buttonsType.secondary});
target.pointerup();
// middle-click
target.pointerdown({buttons: buttonsType.auxiliary});
target.pointerup();
// pen eraser
target.pointerdown({buttons: buttonsType.eraser});
target.pointerup();
const {auxiliary, eraser, primary, secondary} = buttonsType;
if (pointerType !== 'touch') {
// right-click
target.pointerdown({buttons: secondary, pointerType});
target.pointerup();
// middle-click
target.pointerdown({buttons: auxiliary, pointerType});
target.pointerup();
// pen eraser
target.pointerdown({buttons: eraser, pointerType});
target.pointerup();
}
// alt-click
target.pointerdown({buttons: primary, altKey: true});
target.pointerdown({buttons: primary, altKey: true, pointerType});
target.pointerup();
// ctrl-click
target.pointerdown({buttons: primary, ctrlKey: true});
target.pointerdown({buttons: primary, ctrlKey: true, pointerType});
target.pointerup();
// meta-click
target.pointerdown({buttons: primary, metaKey: true});
target.pointerdown({buttons: primary, metaKey: true, pointerType});
target.pointerup();
// shift-click
target.pointerdown({buttons: primary, shiftKey: true});
target.pointerdown({buttons: primary, shiftKey: true, pointerType});
target.pointerup();

expect(onTapStart).toHaveBeenCalledTimes(0);
Expand Down

0 comments on commit 312b462

Please sign in to comment.