forked from facebook/react-native
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add isPrimary property implementation to the PointerEvent object
Summary: Changelog: [iOS][Internal] - Add isPrimary property implementation to the PointerEvent object This diff adds the `isPrimary` property to the PointerEvent object iOS implementation. In addition this adds a related change where we "reserve" the 0 touch identifier for mouse events and the 1 identifier for apple pencil events. This is an easy way to ensure that these pointers are always consistent no matter what happens. Since mouse & pencil pointers should always be considered the primary pointer, that allows us to focus the more advanced primary pointer differentiation purely on touch events. The logic for this touch event primary pointer differentiation is essentially setting the first touch it recieves as a primary pointer, setting it on touch registration, and sets all subsequent touchs (while the first touch is down) as not the primary pointers. When that primary pointer is lifted, the class property keeping track of the primary pointer is reset and then the **next** pointer (secondary pointers which had already started before the previous primary pointer was lifted are not "upgraded" to primary) is marked as primary. A new platform test is also included in this diff in order to verify the aforementioned behavior. Reviewed By: lunaleaps Differential Revision: D37961707 fbshipit-source-id: ae8b78c5bfea6902fb73094fca1552e4e648ea44
- Loading branch information
1 parent
8441c4a
commit 546c4b4
Showing
6 changed files
with
227 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
144 changes: 144 additions & 0 deletions
144
.../js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventPrimaryTouchPointer.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
/** | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @format | ||
* @flow | ||
*/ | ||
|
||
import type {PlatformTestComponentBaseProps} from '../PlatformTest/RNTesterPlatformTestTypes'; | ||
import type {PointerEvent} from 'react-native/Libraries/Types/CoreEventTypes'; | ||
|
||
import {useTestEventHandler} from './PointerEventSupport'; | ||
import RNTesterPlatformTest from '../PlatformTest/RNTesterPlatformTest'; | ||
import * as React from 'react'; | ||
import {useRef, useCallback, useMemo} from 'react'; | ||
import {StyleSheet, View} from 'react-native'; | ||
|
||
const styles = StyleSheet.create({ | ||
root: { | ||
flexDirection: 'row', | ||
justifyContent: 'space-around', | ||
paddingTop: 20, | ||
}, | ||
box: { | ||
width: 80, | ||
height: 80, | ||
}, | ||
}); | ||
|
||
const listenedEvents = ['pointerDown', 'pointerUp']; | ||
|
||
const expectedOrder = [ | ||
['red', 'pointerDown', true], | ||
['green', 'pointerDown', false], | ||
['red', 'pointerUp', true], | ||
['blue', 'pointerDown', true], | ||
['green', 'pointerUp', false], | ||
['blue', 'pointerUp', true], | ||
]; | ||
|
||
function PointerEventPrimaryTouchPointerTestCase( | ||
props: PlatformTestComponentBaseProps, | ||
) { | ||
const {harness} = props; | ||
|
||
const detected_eventsRef = useRef({}); | ||
|
||
const handleIncomingPointerEvent = useCallback( | ||
(boxLabel: string, eventType: string, isPrimary: boolean) => { | ||
const detected_events = detected_eventsRef.current; | ||
|
||
const pointerEventIdentifier = `${boxLabel}-${eventType}-${String( | ||
isPrimary, | ||
)}`; | ||
if (detected_events[pointerEventIdentifier]) { | ||
return; | ||
} | ||
|
||
const [expectedBoxLabel, expectedEventType, expectedIsPrimary] = | ||
expectedOrder[Object.keys(detected_events).length]; | ||
detected_events[pointerEventIdentifier] = true; | ||
|
||
harness.test(({assert_equals}) => { | ||
assert_equals( | ||
boxLabel, | ||
expectedBoxLabel, | ||
'event should be coming from the correct box', | ||
); | ||
assert_equals( | ||
eventType, | ||
expectedEventType.toLowerCase(), | ||
'event should have the right type', | ||
); | ||
assert_equals( | ||
isPrimary, | ||
expectedIsPrimary, | ||
'event should be correctly primary', | ||
); | ||
}, `${expectedBoxLabel} box's ${expectedEventType} should${!expectedIsPrimary ? ' not' : ''} be marked as the primary pointer`); | ||
}, | ||
[harness], | ||
); | ||
|
||
const createBoxHandler = useCallback( | ||
(boxLabel: string) => (event: PointerEvent, eventName: string) => { | ||
if ( | ||
Object.keys(detected_eventsRef.current).length < expectedOrder.length | ||
) { | ||
handleIncomingPointerEvent( | ||
boxLabel, | ||
eventName, | ||
event.nativeEvent.isPrimary, | ||
); | ||
} | ||
}, | ||
[handleIncomingPointerEvent], | ||
); | ||
|
||
const {handleBoxAEvent, handleBoxBEvent, handleBoxCEvent} = useMemo( | ||
() => ({ | ||
handleBoxAEvent: createBoxHandler('red'), | ||
handleBoxBEvent: createBoxHandler('green'), | ||
handleBoxCEvent: createBoxHandler('blue'), | ||
}), | ||
[createBoxHandler], | ||
); | ||
|
||
const boxAHandlers = useTestEventHandler(listenedEvents, handleBoxAEvent); | ||
const boxBHandlers = useTestEventHandler(listenedEvents, handleBoxBEvent); | ||
const boxCHandlers = useTestEventHandler(listenedEvents, handleBoxCEvent); | ||
|
||
return ( | ||
<View style={styles.root}> | ||
<View {...boxAHandlers} style={[styles.box, {backgroundColor: 'red'}]} /> | ||
<View | ||
{...boxBHandlers} | ||
style={[styles.box, {backgroundColor: 'green'}]} | ||
/> | ||
<View {...boxCHandlers} style={[styles.box, {backgroundColor: 'blue'}]} /> | ||
</View> | ||
); | ||
} | ||
|
||
type Props = $ReadOnly<{}>; | ||
export default function PointerEventPrimaryTouchPointer( | ||
props: Props, | ||
): React.MixedElement { | ||
return ( | ||
<RNTesterPlatformTest | ||
component={PointerEventPrimaryTouchPointerTestCase} | ||
description="This test checks for the correct differentiation of a primary pointer in a multitouch scenario" | ||
instructions={[ | ||
'Touch and hold your finger on the red box', | ||
'Take different finger and touch and hold the green box', | ||
'Lift your finger from the red box and place it on the blue box', | ||
'Lift your finger from the green box', | ||
'Lift your finger from the blue box', | ||
]} | ||
title="Pointer Event primary touch pointer test" | ||
/> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters