[firefox] Fix the pointer getting stuck down when you press the control key (#1390)
This PR fixes a bug in firefox where the pointer can get stuck down while pressing the control key. It achieves this by taking a previous fix (specifically for `useShapeEvents`), and it applies the fix at a deeper level (within `app.dispatch`). ## Before ![2023-05-16 at 15 33 02 - Crimson Coyote](https://github.com/tldraw/tldraw/assets/15892272/7d4b5bb1-a2e5-400c-9935-fddcc9645e52) ## After ![2023-05-16 at 15 34 03 - Purple Panda](https://github.com/tldraw/tldraw/assets/15892272/34a598b2-bf6d-4847-8ce9-a3d52c418174) ### Change Type - [x] `patch` — Bug Fix ### Test Plan 1. Use firefox. 2. On the canvas... pointer down (to start a selection box). 3. Control key down. 4. Pointer up. 5. Make sure that that the selection box is gone. ^ Repeat the above for: Pointer down on a shape. Pointer down on a handle. ### Release Notes - [Firefox] Fixed a bug where the pointer could get stuck down when the control key is held down.
This commit is contained in:
parent
f59bfe01b1
commit
9c28d8a6bd
4 changed files with 27 additions and 29 deletions
|
@ -156,6 +156,8 @@ export class App extends EventEmitter<TLEventMap> {
|
|||
set canMoveCamera(canMove: boolean);
|
||||
get canRedo(): boolean;
|
||||
get canUndo(): boolean;
|
||||
// @internal (undocumented)
|
||||
capturedPointerId: null | number;
|
||||
centerOnPoint(x: number, y: number, opts?: AnimationOptions): this;
|
||||
// @internal
|
||||
protected _clickManager: ClickManager;
|
||||
|
|
|
@ -3527,6 +3527,9 @@ export class App extends EventEmitter<TLEventMap> {
|
|||
/** @internal */
|
||||
private _selectedIdsAtPointerDown: TLShapeId[] = []
|
||||
|
||||
/** @internal */
|
||||
capturedPointerId: number | null = null
|
||||
|
||||
/**
|
||||
* Dispatch an event to the app.
|
||||
*
|
||||
|
@ -3742,6 +3745,12 @@ export class App extends EventEmitter<TLEventMap> {
|
|||
case 'pointer_down': {
|
||||
this._selectedIdsAtPointerDown = this.selectedIds.slice()
|
||||
|
||||
// Firefox bug fix...
|
||||
// If it's a left-mouse-click, we store the pointer id for later user
|
||||
if (info.button === 0) {
|
||||
this.capturedPointerId = info.pointerId
|
||||
}
|
||||
|
||||
// Add the button from the buttons set
|
||||
inputs.buttons.add(info.button)
|
||||
|
||||
|
@ -3833,6 +3842,14 @@ export class App extends EventEmitter<TLEventMap> {
|
|||
return
|
||||
}
|
||||
|
||||
// Firefox bug fix...
|
||||
// If it's the same pointer that we stored earlier...
|
||||
// ... then it's probably still a left-mouse-click!
|
||||
if (this.capturedPointerId === info.pointerId) {
|
||||
this.capturedPointerId = null
|
||||
info.button = 0
|
||||
}
|
||||
|
||||
if (inputs.isPanning) {
|
||||
if (info.button === 1) {
|
||||
if (!this.inputs.keys.has(' ')) {
|
||||
|
|
|
@ -43,7 +43,7 @@ export function useCanvasEvents() {
|
|||
|
||||
function onPointerUp(e: React.PointerEvent) {
|
||||
if ((e as any).isKilled) return
|
||||
if (e.button !== 0 && e.button !== 1 && e.button !== 5) return
|
||||
if (e.button !== 0 && e.button !== 1 && e.button !== 2 && e.button !== 5) return
|
||||
lastX = e.clientX
|
||||
lastY = e.clientY
|
||||
|
||||
|
|
|
@ -6,38 +6,18 @@ import { preventDefault, releasePointerCapture, setPointerCapture } from '../uti
|
|||
import { getPointerInfo } from '../utils/svg'
|
||||
import { useApp } from './useApp'
|
||||
|
||||
const pointerEventHandler = (
|
||||
app: App,
|
||||
shapeId: TLShapeId,
|
||||
name: TLPointerEventName,
|
||||
capturedPointerIdLookup: Set<string>
|
||||
) => {
|
||||
const pointerEventHandler = (app: App, shapeId: TLShapeId, name: TLPointerEventName) => {
|
||||
return (e: React.PointerEvent) => {
|
||||
if (name !== 'pointer_move' && app.pageState.editingId === shapeId) (e as any).isKilled = true
|
||||
if ((e as any).isKilled) return
|
||||
|
||||
let pointerInfo = getPointerInfo(e, app.getContainer())
|
||||
|
||||
switch (name) {
|
||||
case 'pointer_down': {
|
||||
if (e.button !== 0 && e.button !== 1 && e.button !== 2) return
|
||||
setPointerCapture(e.currentTarget, e)
|
||||
if (e.button === 0) {
|
||||
capturedPointerIdLookup.add(`pointer_down:${e.pointerId}:0`)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'pointer_up': {
|
||||
const key = `pointer_down:${e.pointerId}:0`
|
||||
// Due to an issue with how firefox handles click events, see <https://linear.app/tldraw/issue/TLD-1056/firefox-pointer-events-do-not-fire-when-control-clicking>
|
||||
if (capturedPointerIdLookup.has(key)) {
|
||||
// Because we've tracked the pointer event as a pointer_down with button 0, we can assume this is the invalid right click FF issue.
|
||||
pointerInfo = {
|
||||
...pointerInfo,
|
||||
button: 0,
|
||||
}
|
||||
capturedPointerIdLookup.delete(key)
|
||||
}
|
||||
releasePointerCapture(e.currentTarget, e)
|
||||
break
|
||||
}
|
||||
|
@ -55,7 +35,7 @@ const pointerEventHandler = (
|
|||
target: 'shape',
|
||||
shape,
|
||||
name,
|
||||
...pointerInfo,
|
||||
...getPointerInfo(e, app.getContainer()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +44,6 @@ export function useShapeEvents(id: TLShapeId) {
|
|||
const app = useApp()
|
||||
|
||||
return React.useMemo(() => {
|
||||
const capturedPointerIdLookup = new Set<string>()
|
||||
function onTouchStart(e: React.TouchEvent) {
|
||||
;(e as any).isKilled = true
|
||||
preventDefault(e)
|
||||
|
@ -75,7 +54,7 @@ export function useShapeEvents(id: TLShapeId) {
|
|||
preventDefault(e)
|
||||
}
|
||||
|
||||
const handlePointerMove = pointerEventHandler(app, id, 'pointer_move', capturedPointerIdLookup)
|
||||
const handlePointerMove = pointerEventHandler(app, id, 'pointer_move')
|
||||
|
||||
// Track the last screen point
|
||||
let lastX: number, lastY: number
|
||||
|
@ -90,10 +69,10 @@ export function useShapeEvents(id: TLShapeId) {
|
|||
}
|
||||
|
||||
return {
|
||||
onPointerDown: pointerEventHandler(app, id, 'pointer_down', capturedPointerIdLookup),
|
||||
onPointerUp: pointerEventHandler(app, id, 'pointer_up', capturedPointerIdLookup),
|
||||
onPointerEnter: pointerEventHandler(app, id, 'pointer_enter', capturedPointerIdLookup),
|
||||
onPointerLeave: pointerEventHandler(app, id, 'pointer_leave', capturedPointerIdLookup),
|
||||
onPointerDown: pointerEventHandler(app, id, 'pointer_down'),
|
||||
onPointerUp: pointerEventHandler(app, id, 'pointer_up'),
|
||||
onPointerEnter: pointerEventHandler(app, id, 'pointer_enter'),
|
||||
onPointerLeave: pointerEventHandler(app, id, 'pointer_leave'),
|
||||
onPointerMove,
|
||||
onTouchStart,
|
||||
onTouchEnd,
|
||||
|
|
Loading…
Reference in a new issue