Skip to content

Commit e0bc7ac

Browse files
author
Nicolas Gallagher
committed
[react-interactions] fix Press/Tap behavior for virtual middle clicks
Tools like BetterTouchTool for macOS trigger middle-clicks with a 'buttons' value that doesn't correspond to the middle-mouse button. To account for this we also inspect the value of 'button'. Close #17367
1 parent b43eec7 commit e0bc7ac

9 files changed

Lines changed: 292 additions & 65 deletions

File tree

packages/react-interactions/events/src/dom/PressLegacy.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,9 @@ const pressResponderImpl = {
626626
state.responderRegionOnDeactivation = null;
627627
state.isPressWithinResponderRegion = true;
628628
state.buttons = nativeEvent.buttons;
629+
if (nativeEvent.button === 1) {
630+
state.buttons = 4;
631+
}
629632
dispatchPressStartEvents(event, context, props, state);
630633
addRootEventTypes(context, state);
631634
} else {

packages/react-interactions/events/src/dom/Tap.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,10 +520,14 @@ const responderImpl = {
520520
}
521521

522522
const activate = shouldActivate(event);
523-
const activateAuxiliary = isAuxiliary(nativeEvent.buttons, event);
523+
const buttons =
524+
nativeEvent.button === 1
525+
? buttonsEnum.auxiliary
526+
: nativeEvent.buttons;
527+
const activateAuxiliary = isAuxiliary(buttons, event);
524528

525529
if (activate || activateAuxiliary) {
526-
state.buttons = nativeEvent.buttons;
530+
state.buttons = buttons;
527531
state.pointerType = event.pointerType;
528532
state.responderTarget = context.getResponderNode();
529533
addRootEventTypes(rootEventTypes, context, state);

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

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
'use strict';
1111

1212
import {
13+
buttonType,
1314
buttonsType,
1415
createEventTarget,
1516
describeWithPointerEvent,
@@ -126,7 +127,30 @@ describeWithPointerEvent('Press responder', hasPointerEvents => {
126127
it('is called after middle-button pointer down', () => {
127128
const target = createEventTarget(ref.current);
128129
const pointerType = 'mouse';
129-
target.pointerdown({buttons: buttonsType.auxiliary, pointerType});
130+
target.pointerdown({
131+
button: buttonType.auxiliary,
132+
buttons: buttonsType.auxiliary,
133+
pointerType,
134+
});
135+
target.pointerup({pointerType});
136+
expect(onPressStart).toHaveBeenCalledTimes(1);
137+
expect(onPressStart).toHaveBeenCalledWith(
138+
expect.objectContaining({
139+
buttons: buttonsType.auxiliary,
140+
pointerType: 'mouse',
141+
type: 'pressstart',
142+
}),
143+
);
144+
});
145+
146+
it('is called after virtual middle-button pointer down', () => {
147+
const target = createEventTarget(ref.current);
148+
const pointerType = 'mouse';
149+
target.pointerdown({
150+
button: buttonType.auxiliary,
151+
buttons: 0,
152+
pointerType,
153+
});
130154
target.pointerup({pointerType});
131155
expect(onPressStart).toHaveBeenCalledTimes(1);
132156
expect(onPressStart).toHaveBeenCalledWith(
@@ -212,6 +236,7 @@ describeWithPointerEvent('Press responder', hasPointerEvents => {
212236
it('is called after middle-button pointer up', () => {
213237
const target = createEventTarget(ref.current);
214238
target.pointerdown({
239+
button: buttonType.auxiliary,
215240
buttons: buttonsType.auxiliary,
216241
pointerType: 'mouse',
217242
});
@@ -226,6 +251,24 @@ describeWithPointerEvent('Press responder', hasPointerEvents => {
226251
);
227252
});
228253

254+
it('is called after virtual middle-button pointer up', () => {
255+
const target = createEventTarget(ref.current);
256+
target.pointerdown({
257+
button: buttonType.auxiliary,
258+
buttons: 0,
259+
pointerType: 'mouse',
260+
});
261+
target.pointerup({pointerType: 'mouse'});
262+
expect(onPressEnd).toHaveBeenCalledTimes(1);
263+
expect(onPressEnd).toHaveBeenCalledWith(
264+
expect.objectContaining({
265+
buttons: buttonsType.auxiliary,
266+
pointerType: 'mouse',
267+
type: 'pressend',
268+
}),
269+
);
270+
});
271+
229272
it('is called after "keyup" event for Enter', () => {
230273
const target = createEventTarget(ref.current);
231274
target.keydown({key: 'Enter'});
@@ -356,13 +399,25 @@ describeWithPointerEvent('Press responder', hasPointerEvents => {
356399
it('is not called after middle-button press', () => {
357400
const target = createEventTarget(ref.current);
358401
target.pointerdown({
402+
button: buttonType.auxiliary,
359403
buttons: buttonsType.auxiliary,
360404
pointerType: 'mouse',
361405
});
362406
target.pointerup({pointerType: 'mouse'});
363407
expect(onPress).not.toHaveBeenCalled();
364408
});
365409

410+
it('is not called after virtual middle-button press', () => {
411+
const target = createEventTarget(ref.current);
412+
target.pointerdown({
413+
button: buttonType.auxiliary,
414+
buttons: 0,
415+
pointerType: 'mouse',
416+
});
417+
target.pointerup({pointerType: 'mouse'});
418+
expect(onPress).not.toHaveBeenCalled();
419+
});
420+
366421
it('is called after valid "keyup" event', () => {
367422
const target = createEventTarget(ref.current);
368423
target.keydown({key: 'Enter'});

packages/react-interactions/events/src/dom/__tests__/PressLegacy-test.internal.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
'use strict';
1111

1212
import {
13+
buttonType,
1314
buttonsType,
1415
createEventTarget,
1516
setPointerEvent,
@@ -122,6 +123,7 @@ describe.each(environmentTable)('Press responder', hasPointerEvents => {
122123
it('is called after middle-button pointer down', () => {
123124
const target = createEventTarget(ref.current);
124125
target.pointerdown({
126+
button: buttonType.auxiliary,
125127
buttons: buttonsType.auxiliary,
126128
pointerType: 'mouse',
127129
});
@@ -140,6 +142,7 @@ describe.each(environmentTable)('Press responder', hasPointerEvents => {
140142
const target = createEventTarget(node);
141143
target.setBoundingClientRect({x: 0, y: 0, width: 100, height: 100});
142144
target.pointerdown({
145+
button: buttonType.auxiliary,
143146
buttons: buttonsType.auxiliary,
144147
pointerType: 'mouse',
145148
});
@@ -374,6 +377,17 @@ describe.each(environmentTable)('Press responder', hasPointerEvents => {
374377
expect(onPress).not.toHaveBeenCalled();
375378
});
376379

380+
it('is not called after virtual middle-button press', () => {
381+
const target = createEventTarget(ref.current);
382+
target.pointerdown({
383+
button: buttonType.auxiliary,
384+
buttons: 0,
385+
pointerType: 'mouse',
386+
});
387+
target.pointerup({pointerType: 'mouse'});
388+
expect(onPress).not.toHaveBeenCalled();
389+
});
390+
377391
it('is called after valid "keyup" event', () => {
378392
const target = createEventTarget(ref.current);
379393
target.keydown({key: 'Enter'});

0 commit comments

Comments
 (0)