Skip to content

Commit 8cf963c

Browse files
authored
React events: ignore device buttons that aren't for primary interactions (#15402)
The Pointer Events spec mentions that the value of `button` in a nativeEvent can be anything between 0 and 5 for "down" events. We only care about those with a value of 0.
1 parent 38bd570 commit 8cf963c

File tree

2 files changed

+33
-26
lines changed

2 files changed

+33
-26
lines changed

packages/react-events/src/Press.js

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,8 @@ const PressResponder = {
426426
props: PressProps,
427427
state: PressState,
428428
): void {
429-
const {target, type, nativeEvent} = event;
429+
const {target, type} = event;
430+
const nativeEvent: any = event.nativeEvent;
430431

431432
switch (type) {
432433
/**
@@ -442,21 +443,23 @@ const PressResponder = {
442443
const pointerType = getPointerType(nativeEvent);
443444
state.pointerType = pointerType;
444445

445-
if (pointerType === 'mouse' || type === 'mousedown') {
446-
if (
447-
// Ignore right- and middle-clicks
448-
nativeEvent.button === 1 ||
449-
nativeEvent.button === 2 ||
450-
// Ignore pressing on hit slop area with mouse
451-
context.isPositionWithinTouchHitTarget(
452-
target.ownerDocument,
453-
(nativeEvent: any).x,
454-
(nativeEvent: any).y,
455-
)
456-
) {
457-
return;
458-
}
446+
// Ignore any device buttons except left-mouse and touch/pen contact
447+
if (nativeEvent.button > 0) {
448+
return;
449+
}
450+
451+
// Ignore pressing on hit slop area with mouse
452+
if (
453+
(pointerType === 'mouse' || type === 'mousedown') &&
454+
context.isPositionWithinTouchHitTarget(
455+
target.ownerDocument,
456+
nativeEvent.x,
457+
nativeEvent.y,
458+
)
459+
) {
460+
return;
459461
}
462+
460463
state.pressTarget = target;
461464
state.isPressWithinResponderRegion = true;
462465
dispatchPressStartEvents(context, props, state);
@@ -574,7 +577,7 @@ const PressResponder = {
574577

575578
if (type !== 'touchcancel' && props.onPress) {
576579
// Find if the X/Y of the end touch is still that of the original target
577-
const changedTouch = (nativeEvent: any).changedTouches[0];
580+
const changedTouch = nativeEvent.changedTouches[0];
578581
const doc = (target: any).ownerDocument;
579582
const fromTarget = doc.elementFromPoint(
580583
changedTouch.screenX,
@@ -607,14 +610,11 @@ const PressResponder = {
607610
*/
608611
case 'keydown':
609612
case 'keypress': {
610-
if (
611-
!context.hasOwnership() &&
612-
isValidKeyPress((nativeEvent: any).key)
613-
) {
613+
if (!context.hasOwnership() && isValidKeyPress(nativeEvent.key)) {
614614
if (state.isPressed) {
615615
// Prevent spacebar press from scrolling the window
616-
if ((nativeEvent: any).key === ' ') {
617-
(nativeEvent: any).preventDefault();
616+
if (nativeEvent.key === ' ') {
617+
nativeEvent.preventDefault();
618618
}
619619
} else {
620620
const pointerType = getPointerType(nativeEvent);
@@ -627,7 +627,7 @@ const PressResponder = {
627627
break;
628628
}
629629
case 'keyup': {
630-
if (state.isPressed && isValidKeyPress((nativeEvent: any).key)) {
630+
if (state.isPressed && isValidKeyPress(nativeEvent.key)) {
631631
const wasLongPressed = state.isLongPressed;
632632
dispatchPressEndEvents(context, props, state);
633633
if (state.pressTarget !== null && props.onPress) {
@@ -659,11 +659,11 @@ const PressResponder = {
659659

660660
case 'click': {
661661
if (isAnchorTagElement(target)) {
662-
const {ctrlKey, metaKey, shiftKey} = ((nativeEvent: any): MouseEvent);
662+
const {ctrlKey, metaKey, shiftKey} = (nativeEvent: MouseEvent);
663663
// Check "open in new window/tab" and "open context menu" key modifiers
664664
const preventDefault = props.preventDefault;
665665
if (preventDefault !== false && !shiftKey && !metaKey && !ctrlKey) {
666-
(nativeEvent: any).preventDefault();
666+
nativeEvent.preventDefault();
667667
}
668668
}
669669
break;
@@ -672,7 +672,7 @@ const PressResponder = {
672672
case 'contextmenu': {
673673
if (state.isPressed) {
674674
if (props.preventDefault !== false) {
675-
(nativeEvent: any).preventDefault();
675+
nativeEvent.preventDefault();
676676
} else {
677677
state.shouldSkipMouseAfterTouch = false;
678678
dispatchPressEndEvents(context, props, state);

packages/react-events/src/__tests__/Press-test.internal.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ describe('Event responder: Press', () => {
8585
expect(onPressStart).toHaveBeenCalledTimes(1);
8686
});
8787

88+
it('ignores any events not caused by left-click or touch/pen contact', () => {
89+
ref.current.dispatchEvent(createPointerEvent('pointerdown', {button: 1}));
90+
ref.current.dispatchEvent(createPointerEvent('pointerdown', {button: 5}));
91+
ref.current.dispatchEvent(createPointerEvent('mousedown', {button: 2}));
92+
expect(onPressStart).toHaveBeenCalledTimes(0);
93+
});
94+
8895
it('is called once after "keydown" events for Enter', () => {
8996
ref.current.dispatchEvent(createKeyboardEvent('keydown', {key: 'Enter'}));
9097
ref.current.dispatchEvent(createKeyboardEvent('keydown', {key: 'Enter'}));

0 commit comments

Comments
 (0)