Handle requestPointerLock error cases in iframes P-199 (#272)
See https://linear.app/theatre/issue/P-199/dont-use-pointer-lock-when-in-an-iframe
This commit is contained in:
parent
8bd37a28d6
commit
2ef9d5e346
2 changed files with 34 additions and 3 deletions
11
packages/playground/src/tests/in-iframe/index.tsx
Normal file
11
packages/playground/src/tests/in-iframe/index.tsx
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import React from 'react'
|
||||||
|
import ReactDOM from 'react-dom'
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<iframe
|
||||||
|
src="/shared/dom"
|
||||||
|
style={{width: '600px', height: '600px'}}
|
||||||
|
sandbox="allow-scripts allow-same-origin"
|
||||||
|
/>,
|
||||||
|
document.getElementById('root'),
|
||||||
|
)
|
|
@ -151,6 +151,24 @@ type IUseDragStateDetection_Detected = {
|
||||||
dragEventCount: number
|
dragEventCount: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pointer lock may not have been accepted, because we might be in an iframe which disallows pointer locking
|
||||||
|
let isPointerLockAllowed = !isSafari
|
||||||
|
function requestPointerLockSafely(target: Element): Promise<boolean> {
|
||||||
|
if (!isPointerLockAllowed) return Promise.resolve(false)
|
||||||
|
try {
|
||||||
|
// Checking introduced with https://linear.app/theatre/issue/P-199/dont-use-pointer-lock-when-in-an-iframe
|
||||||
|
return Promise.resolve(target.requestPointerLock())
|
||||||
|
.then(() => true)
|
||||||
|
.catch(() => {
|
||||||
|
isPointerLockAllowed = false
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
} catch (_err) {
|
||||||
|
isPointerLockAllowed = false
|
||||||
|
return Promise.resolve(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default function useDrag(
|
export default function useDrag(
|
||||||
target: HTMLElement | SVGElement | undefined | null,
|
target: HTMLElement | SVGElement | undefined | null,
|
||||||
opts: UseDragOpts,
|
opts: UseDragOpts,
|
||||||
|
@ -162,7 +180,7 @@ export default function useDrag(
|
||||||
* Safari has a gross behavior with locking the pointer changes the height of the webpage
|
* Safari has a gross behavior with locking the pointer changes the height of the webpage
|
||||||
* See {@link UseDragOpts.shouldPointerLock} for more context.
|
* See {@link UseDragOpts.shouldPointerLock} for more context.
|
||||||
*/
|
*/
|
||||||
const isPointerLockUsed = opts.shouldPointerLock && !isSafari
|
const isPointerLockUsed = opts.shouldPointerLock && isPointerLockAllowed
|
||||||
|
|
||||||
const stateRef = useRef<IUseDragStateRef>({
|
const stateRef = useRef<IUseDragStateRef>({
|
||||||
domDragStarted: false,
|
domDragStarted: false,
|
||||||
|
@ -206,7 +224,7 @@ export default function useDrag(
|
||||||
DRAG_DETECTION_DISTANCE_THRESHOLD
|
DRAG_DETECTION_DISTANCE_THRESHOLD
|
||||||
) {
|
) {
|
||||||
if (isPointerLockUsed) {
|
if (isPointerLockUsed) {
|
||||||
target.requestPointerLock()
|
requestPointerLockSafely(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
stateStarted.detection = {
|
stateStarted.detection = {
|
||||||
|
@ -248,7 +266,9 @@ export default function useDrag(
|
||||||
if (!stateRef.current.domDragStarted) return
|
if (!stateRef.current.domDragStarted) return
|
||||||
const dragHappened = stateRef.current.detection.detected
|
const dragHappened = stateRef.current.detection.detected
|
||||||
stateRef.current = {domDragStarted: false}
|
stateRef.current = {domDragStarted: false}
|
||||||
if (opts.shouldPointerLock && !isSafari) document.exitPointerLock()
|
if (isPointerLockUsed && document.pointerLockElement === target) {
|
||||||
|
document.exitPointerLock()
|
||||||
|
}
|
||||||
callbacksRef.current.onDragEnd(dragHappened)
|
callbacksRef.current.onDragEnd(dragHappened)
|
||||||
|
|
||||||
// ensure that the window is focused after a successful drag
|
// ensure that the window is focused after a successful drag
|
||||||
|
|
Loading…
Reference in a new issue