@samitouri / QOS-React-2 / commits / 8cf963c6c3

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.

Nicolas Gallagher committed Apr 12, 2019 at 13:36 UTC 8cf963c6c3e4dc41d0c006513aff19d725348d82
2 files changed +33 -26
packages/react-events/src/Press.js
+26 -26
@@ -426,7 +426,8 @@ const PressResponder = {
426 props: PressProps,
427 state: PressState,
428 ): void {
429 - const {target, type, nativeEvent} = event;
429 + const {target, type} = event;
430 + const nativeEvent: any = event.nativeEvent;
431
432 switch (type) {
433 /**
@@ -442,21 +443,23 @@ const PressResponder = {
443 const pointerType = getPointerType(nativeEvent);
444 state.pointerType = pointerType;
445
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;
461 }
462 +
463 state.pressTarget = target;
464 state.isPressWithinResponderRegion = true;
465 dispatchPressStartEvents(context, props, state);
@@ -574,7 +577,7 @@ const PressResponder = {
577
578 if (type !== 'touchcancel' && props.onPress) {
579 // 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];
581 const doc = (target: any).ownerDocument;
582 const fromTarget = doc.elementFromPoint(
583 changedTouch.screenX,
@@ -607,14 +610,11 @@ const PressResponder = {
610 */
611 case 'keydown':
612 case 'keypress': {
610 - if (
611 - !context.hasOwnership() &&
612 - isValidKeyPress((nativeEvent: any).key)
613 - ) {
613 + if (!context.hasOwnership() && isValidKeyPress(nativeEvent.key)) {
614 if (state.isPressed) {
615 // Prevent spacebar press from scrolling the window
616 - if ((nativeEvent: any).key === ' ') {
617 - (nativeEvent: any).preventDefault();
616 + if (nativeEvent.key === ' ') {
617 + nativeEvent.preventDefault();
618 }
619 } else {
620 const pointerType = getPointerType(nativeEvent);
@@ -627,7 +627,7 @@ const PressResponder = {
627 break;
628 }
629 case 'keyup': {
630 - if (state.isPressed && isValidKeyPress((nativeEvent: any).key)) {
630 + if (state.isPressed && isValidKeyPress(nativeEvent.key)) {
631 const wasLongPressed = state.isLongPressed;
632 dispatchPressEndEvents(context, props, state);
633 if (state.pressTarget !== null && props.onPress) {
@@ -659,11 +659,11 @@ const PressResponder = {
659
660 case 'click': {
661 if (isAnchorTagElement(target)) {
662 - const {ctrlKey, metaKey, shiftKey} = ((nativeEvent: any): MouseEvent);
662 + const {ctrlKey, metaKey, shiftKey} = (nativeEvent: MouseEvent);
663 // Check "open in new window/tab" and "open context menu" key modifiers
664 const preventDefault = props.preventDefault;
665 if (preventDefault !== false && !shiftKey && !metaKey && !ctrlKey) {
666 - (nativeEvent: any).preventDefault();
666 + nativeEvent.preventDefault();
667 }
668 }
669 break;
@@ -672,7 +672,7 @@ const PressResponder = {
672 case 'contextmenu': {
673 if (state.isPressed) {
674 if (props.preventDefault !== false) {
675 - (nativeEvent: any).preventDefault();
675 + nativeEvent.preventDefault();
676 } else {
677 state.shouldSkipMouseAfterTouch = false;
678 dispatchPressEndEvents(context, props, state);
packages/react-events/src/__tests__/Press-test.internal.js
+7
@@ -85,6 +85,13 @@ describe('Event responder: Press', () => {
85 expect(onPressStart).toHaveBeenCalledTimes(1);
86 });
87
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 +
95 it('is called once after "keydown" events for Enter', () => {
96 ref.current.dispatchEvent(createKeyboardEvent('keydown', {key: 'Enter'}));
97 ref.current.dispatchEvent(createKeyboardEvent('keydown', {key: 'Enter'}));