Skip to content

Commit 2c9c946

Browse files
committed
Add onAuxClick event
1 parent 7e48445 commit 2c9c946

10 files changed

Lines changed: 500 additions & 3 deletions

File tree

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* Copyright (c) Microsoft Corporation.
3+
* Licensed under the MIT License.
4+
*
5+
* @flow strict-local
6+
* @format
7+
*/
8+
9+
'use strict';
10+
11+
import type {RNTesterModuleExample} from '../../types/RNTesterTypes';
12+
13+
const React = require('react');
14+
import {Pressable, StyleSheet, View} from 'react-native';
15+
import RNTesterText from '../../components/RNTesterText';
16+
17+
function PointerClickEventsExample(): React.Node {
18+
const [text, setText] = React.useState(
19+
'onClick should cause the box to go red, onAuxClick will cause it go green',
20+
);
21+
const [bgColor, setBgColor]= React.useState('gray');
22+
return (
23+
<View>
24+
<View
25+
accessible
26+
testID="pointer-click-target"
27+
style={[styles.targetBox, {backgroundColor: bgColor}]}
28+
onClick={(e) => {
29+
setBgColor('red');
30+
setText('onClick.nativeEvent: ' + JSON.stringify(e.nativeEvent, null, 2));
31+
}}
32+
onAuxClick={(e) => {
33+
setBgColor('green');
34+
setText('onAuxClick.nativeEvent: ' + JSON.stringify(e.nativeEvent, null, 2));
35+
}}
36+
/>
37+
<RNTesterText accessible testID='pointer-click-text'>{text}</RNTesterText>
38+
</View>
39+
40+
);
41+
}
42+
43+
exports.displayName = 'PointerClickExample';
44+
exports.framework = 'React';
45+
exports.category = 'Basic';
46+
exports.title = 'Pointer Clicks';
47+
exports.documentationURL =
48+
'https://developer.mozilla.org/en-US/docs/Web/API/Element/auxclick_event';
49+
exports.description =
50+
'Tests that onClick and onAuxClick work.';
51+
52+
exports.examples = [
53+
{
54+
title: 'onClick/onAuxClick test',
55+
description:
56+
'Click the box with different pointers/buttons to test pointer click events.',
57+
render: function (): React.Node {
58+
return <PointerClickEventsExample />;
59+
},
60+
},
61+
] as Array<RNTesterModuleExample>;
62+
63+
const styles = StyleSheet.create({
64+
targetBox: {
65+
width: 200,
66+
height: 200,
67+
margin: 10,
68+
borderRadius: 10,
69+
justifyContent: 'center',
70+
alignItems: 'center',
71+
},
72+
});

packages/@react-native-windows/tester/src/js/utils/RNTesterList.windows.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,11 @@ const APIs: Array<RNTesterModuleInfo> = ([
401401
category: 'Basic',
402402
module: require('../examples/PointerEvents/PointerEventsExample'),
403403
},
404+
{
405+
key: 'PointerClickEventsExample',
406+
category: 'Basic',
407+
module: require('../examples-win/Pointer/PointerClickEventsExample'),
408+
},
404409
{
405410
key: 'PointerButtonExample',
406411
category: 'Basic',
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/**
2+
* Copyright (c) Microsoft Corporation.
3+
* Licensed under the MIT License.
4+
*
5+
* @format
6+
*/
7+
8+
import { dumpVisualTree } from '@react-native-windows/automation-commands';
9+
import { goToApiExample } from './RNTesterNavigation';
10+
import { verifyNoErrorLogs } from './Helpers';
11+
import { app } from '@react-native-windows/automation';
12+
13+
beforeAll(async () => {
14+
// If window is partially offscreen, tests will fail to click on certain elements
15+
await app.setWindowPosition(0, 0);
16+
await app.setWindowSize(1000, 1250);
17+
await goToApiExample('Pointer Clicks');
18+
});
19+
20+
afterEach(async () => {
21+
await verifyNoErrorLogs();
22+
});
23+
24+
25+
describe('Pointer onClick Test', () => {
26+
test('onClick reports correct native event properties on left click', async () => {
27+
const component = await app.findElementByTestID('pointer-click-target');
28+
await component.waitForDisplayed({ timeout: 5000 });
29+
30+
// Left click triggers onPointerDown with button=0
31+
await component.click();
32+
const stateText = await app.findElementByTestID('pointer-click-text');
33+
34+
await app.waitUntil(
35+
async () => {
36+
const currentText = await stateText.getText();
37+
return currentText.includes('"button": 0') && currentText.includes('onClick');
38+
},
39+
{
40+
timeout: 5000,
41+
timeoutMsg:
42+
'State text not updated after onClick with button property.',
43+
},
44+
);
45+
46+
const text = await stateText.getText();
47+
expect(text).toMatchSnapshot();
48+
});
49+
test('onAuxClick reports correct native event properties on middle click', async () => {
50+
const component = await app.findElementByTestID('pointer-click-target');
51+
await component.waitForDisplayed({ timeout: 5000 });
52+
53+
// Middle click triggers onPointerDown with button=1
54+
await component.click({ button: 'middle' });
55+
const stateText = await app.findElementByTestID('pointer-click-text');
56+
57+
await app.waitUntil(
58+
async () => {
59+
const currentText = await stateText.getText();
60+
return currentText.includes('"button": 1') && currentText.includes('onAuxClick');
61+
},
62+
{
63+
timeout: 5000,
64+
timeoutMsg:
65+
'State text not updated after onAuxClick with middle button property.',
66+
},
67+
);
68+
69+
const text = await stateText.getText();
70+
expect(text).toMatchSnapshot();
71+
});
72+
test('onAuxClick reports correct native event properties on right click', async () => {
73+
const component = await app.findElementByTestID('pointer-click-target');
74+
await component.waitForDisplayed({ timeout: 5000 });
75+
76+
// Middle click triggers onPointerDown with button=2
77+
await component.click({ button: 'right' });
78+
const stateText = await app.findElementByTestID('pointer-click-text');
79+
80+
await app.waitUntil(
81+
async () => {
82+
const currentText = await stateText.getText();
83+
return currentText.includes('"button": 2') && currentText.includes('onAuxClick');
84+
},
85+
{
86+
timeout: 5000,
87+
timeoutMsg:
88+
'State text not updated after onAuxClick with right button property.',
89+
},
90+
);
91+
92+
const text = await stateText.getText();
93+
expect(text).toMatchSnapshot();
94+
});
95+
96+
});
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Pointer onClick Test onAuxClick reports correct native event properties on middle click 1`] = `
4+
"onAuxClick.nativeEvent: {
5+
"pointerId": 1,
6+
"pressure": 0,
7+
"pointerType": "mouse",
8+
"clientX": 110,
9+
"clientY": 166,
10+
"x": 110,
11+
"y": 166,
12+
"pageX": 110,
13+
"pageY": 166,
14+
"screenX": 100,
15+
"screenY": 100,
16+
"offsetX": 100,
17+
"offsetY": 100,
18+
"width": 0,
19+
"height": 0,
20+
"tiltX": 0,
21+
"tiltY": 0,
22+
"detail": 0,
23+
"buttons": 0,
24+
"tangentialPressure": 0,
25+
"twist": 0,
26+
"ctrlKey": false,
27+
"shiftKey": false,
28+
"altKey": false,
29+
"metaKey": false,
30+
"isPrimary": true,
31+
"button": 1,
32+
"target": 1276
33+
}"
34+
`;
35+
36+
exports[`Pointer onClick Test onAuxClick reports correct native event properties on right click 1`] = `
37+
"onAuxClick.nativeEvent: {
38+
"pointerId": 1,
39+
"pressure": 0,
40+
"pointerType": "mouse",
41+
"clientX": 110,
42+
"clientY": 166,
43+
"x": 110,
44+
"y": 166,
45+
"pageX": 110,
46+
"pageY": 166,
47+
"screenX": 100,
48+
"screenY": 100,
49+
"offsetX": 100,
50+
"offsetY": 100,
51+
"width": 0,
52+
"height": 0,
53+
"tiltX": 0,
54+
"tiltY": 0,
55+
"detail": 0,
56+
"buttons": 0,
57+
"tangentialPressure": 0,
58+
"twist": 0,
59+
"ctrlKey": false,
60+
"shiftKey": false,
61+
"altKey": false,
62+
"metaKey": false,
63+
"isPrimary": true,
64+
"button": 2,
65+
"target": 1276
66+
}"
67+
`;
68+
69+
exports[`Pointer onClick Test onClick reports correct native event properties on left click 1`] = `
70+
"onClick.nativeEvent: {
71+
"pointerId": 1,
72+
"pressure": 0,
73+
"pointerType": "mouse",
74+
"clientX": 110,
75+
"clientY": 166,
76+
"x": 110,
77+
"y": 166,
78+
"pageX": 110,
79+
"pageY": 166,
80+
"screenX": 100,
81+
"screenY": 100,
82+
"offsetX": 100,
83+
"offsetY": 100,
84+
"width": 0,
85+
"height": 0,
86+
"tiltX": 0,
87+
"tiltY": 0,
88+
"detail": 0,
89+
"buttons": 0,
90+
"tangentialPressure": 0,
91+
"twist": 0,
92+
"ctrlKey": false,
93+
"shiftKey": false,
94+
"altKey": false,
95+
"metaKey": false,
96+
"isPrimary": true,
97+
"button": 0,
98+
"target": 1276
99+
}"
100+
`;

vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,9 +1543,9 @@ void CompositionEventHandler::DispatchTouchEvent(
15431543
if (IsPointerWithinInitialTree(activeTouch)) {
15441544
activeTouch.eventEmitter->onClick(pointerEvent);
15451545
}
1546-
} /* else if (IsPointerWithinInitialTree(activeTouch)) {
1546+
} else if (IsPointerWithinInitialTree(activeTouch)) {
15471547
activeTouch.eventEmitter->onAuxClick(pointerEvent);
1548-
} */
1548+
}
15491549
break;
15501550
case TouchEventType::Cancel:
15511551
case TouchEventType::CaptureLost:

0 commit comments

Comments
 (0)