From 545b214558c1f7fc33b0ed8f6bcbfa406c1bfc18 Mon Sep 17 00:00:00 2001 From: Christopher Chedeau Date: Sat, 5 Dec 2020 15:06:50 -0800 Subject: [PATCH] Don't open context menu when multi-touch (#2455) This was very annoying when you would zoom on mobile and the context menu would appear. The problem was the following: - You put a finger in, it creates a timeout - You put a second finger in, it creates another timeout - 300ms elapsed, which is not that much - The context menu opens - Now you move your fingers, which works, but the context menu is still open The fix is to invalidate the context menu if a second finger is added even if the first one hasn't moved. --- src/components/App.tsx | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/components/App.tsx b/src/components/App.tsx index 8a463a60..48cc9ffa 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -186,7 +186,7 @@ let isPanning: boolean = false; let isDraggingScrollBar: boolean = false; let currentScrollBars: ScrollBars = { horizontal: null, vertical: null }; let touchTimeout = 0; -let touchMoving = false; +let invalidateContextMenu = false; let lastPointerUp: ((event: any) => void) | null = null; const gesture: Gesture = { @@ -645,6 +645,7 @@ class App extends React.Component { this.removeEventListeners(); this.scene.destroy(); clearTimeout(touchTimeout); + touchTimeout = 0; } private onResize = withBatchedUpdates(() => { @@ -1097,7 +1098,8 @@ class App extends React.Component { // remove touch handler for context menu on touch devices if (event.pointerType === "touch" && touchTimeout) { clearTimeout(touchTimeout); - touchMoving = false; + touchTimeout = 0; + invalidateContextMenu = false; } gesture.pointers.delete(event.pointerId); @@ -1924,7 +1926,7 @@ class App extends React.Component { // set touch moving for mobile context menu private handleTouchMove = (event: React.TouchEvent) => { - touchMoving = true; + invalidateContextMenu = true; }; private handleCanvasPointerDown = ( @@ -2029,18 +2031,26 @@ class App extends React.Component { ): void => { // deal with opening context menu on touch devices if (event.pointerType === "touch") { - touchMoving = false; + invalidateContextMenu = false; - // open the context menu with the first touch's clientX and clientY - // if the touch is not moving - touchTimeout = window.setTimeout(() => { - if (!touchMoving) { - this.openContextMenu({ - clientX: event.clientX, - clientY: event.clientY, - }); - } - }, TOUCH_CTX_MENU_TIMEOUT); + if (touchTimeout) { + // If there's already a touchTimeout, this means that there's another + // touch down and we are doing another touch, so we shouldn't open the + // context menu. + invalidateContextMenu = true; + } else { + // open the context menu with the first touch's clientX and clientY + // if the touch is not moving + touchTimeout = window.setTimeout(() => { + touchTimeout = 0; + if (!invalidateContextMenu) { + this.openContextMenu({ + clientX: event.clientX, + clientY: event.clientY, + }); + } + }, TOUCH_CTX_MENU_TIMEOUT); + } } };