From 6753a3fe322aa1ed951b2d725a672ea72933e8b9 Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Tue, 26 Nov 2024 15:59:10 +0100 Subject: [PATCH] [Editor] Disallow to have multiple pointers while dragging an editor It'll let the user dragging with two fingers. --- src/display/display_utils.js | 6 ++ src/display/editor/editor.js | 88 +++++++++++++++---------- test/integration/stamp_editor_spec.mjs | 33 ++++++++++ web/annotation_editor_layer_builder.css | 4 -- 4 files changed, 94 insertions(+), 37 deletions(-) diff --git a/src/display/display_utils.js b/src/display/display_utils.js index 16fc7093e8238e..3a0b653b7e793f 100644 --- a/src/display/display_utils.js +++ b/src/display/display_utils.js @@ -411,6 +411,11 @@ function noContextMenu(e) { e.preventDefault(); } +function stopEvent(e) { + e.preventDefault(); + e.stopPropagation(); +} + // Deprecated API function -- display regardless of the `verbosity` setting. function deprecated(details) { // eslint-disable-next-line no-console @@ -657,5 +662,6 @@ export { RenderingCancelledException, setLayerDimensions, StatTimer, + stopEvent, SVG_NS, }; diff --git a/src/display/editor/editor.js b/src/display/editor/editor.js index 2ace781179e4ea..0c1495c6c2e4ba 100644 --- a/src/display/editor/editor.js +++ b/src/display/editor/editor.js @@ -23,9 +23,9 @@ import { KeyboardManager, } from "./tools.js"; import { FeatureTest, shadow, unreachable } from "../../shared/util.js"; +import { noContextMenu, stopEvent } from "../display_utils.js"; import { AltText } from "./alt_text.js"; import { EditorToolbar } from "./toolbar.js"; -import { noContextMenu } from "../display_utils.js"; /** * @typedef {Object} AnnotationEditorParameters @@ -48,6 +48,10 @@ class AnnotationEditor { #disabled = false; + #dragPointerId = null; + + #dragPointerType = ""; + #keepAspectRatio = false; #resizersDiv = null; @@ -751,10 +755,7 @@ class AnnotationEditor { ); window.addEventListener( "touchmove", - e => { - // Prevent the page from scrolling. - e.preventDefault(); - }, + stopEvent /* Prevent the page from scrolling */, { passive: false, signal } ); window.addEventListener("contextmenu", noContextMenu, { signal }); @@ -1138,46 +1139,67 @@ class AnnotationEditor { const ac = new AbortController(); const signal = this._uiManager.combinedSignal(ac); + const opts = { capture: true, passive: false, signal }; + const cancelDrag = e => { + ac.abort(); + + this.#dragPointerId = null; + this.#hasBeenClicked = false; + if (!this._uiManager.endDragSession()) { + this.#selectOnPointerEvent(e); + } + }; if (isSelected) { - this.div.classList.add("moving"); this.#prevDragX = event.clientX; this.#prevDragY = event.clientY; - const pointerMoveCallback = e => { - const { clientX: x, clientY: y } = e; - const [tx, ty] = this.screenToPageTranslation( - x - this.#prevDragX, - y - this.#prevDragY - ); - this.#prevDragX = x; - this.#prevDragY = y; - this._uiManager.dragSelectedEditors(tx, ty); - }; - window.addEventListener("pointermove", pointerMoveCallback, { - passive: true, - capture: true, - signal, - }); + this.#dragPointerId = event.pointerId; + this.#dragPointerType = event.pointerType; + window.addEventListener( + "pointermove", + e => { + const { clientX: x, clientY: y, pointerId } = e; + if (pointerId !== this.#dragPointerId) { + stopEvent(e); + return; + } + const [tx, ty] = this.screenToPageTranslation( + x - this.#prevDragX, + y - this.#prevDragY + ); + this.#prevDragX = x; + this.#prevDragY = y; + this._uiManager.dragSelectedEditors(tx, ty); + }, + opts + ); window.addEventListener( "touchmove", + stopEvent /* Prevent the page from scrolling */, + opts + ); + window.addEventListener( + "pointerdown", + // If the user drags with one finger and then clicks with another. e => { - // Prevent the page from scrolling. - e.preventDefault(); + if (e.isPrimary && e.pointerType === this.#dragPointerType) { + // We cannot have two primaries at the same time. + // It's possible to be in this state with Firefox and Gnome when + // trying to drag with three fingers (see bug 1933716). + cancelDrag(e); + } + stopEvent(e); }, - { passive: false, signal } + opts ); } - const pointerUpCallback = () => { - ac.abort(); - if (isSelected) { - this.div.classList.remove("moving"); - } - - this.#hasBeenClicked = false; - if (!this._uiManager.endDragSession()) { - this.#selectOnPointerEvent(event); + const pointerUpCallback = e => { + if (this.#dragPointerId === e.pointerId) { + cancelDrag(e); + return; } + stopEvent(e); }; window.addEventListener("pointerup", pointerUpCallback, { signal }); // If the user is using alt+tab during the dragging session, the pointerup diff --git a/test/integration/stamp_editor_spec.mjs b/test/integration/stamp_editor_spec.mjs index 224e6cf2ab5a52..dd059f1712f968 100644 --- a/test/integration/stamp_editor_spec.mjs +++ b/test/integration/stamp_editor_spec.mjs @@ -1492,4 +1492,37 @@ describe("Stamp Editor", () => { ); }); }); + + describe("Drag a stamp annotation and click on a touchscreen", () => { + let pages; + + beforeAll(async () => { + pages = await loadAndWait("empty.pdf", ".annotationEditorLayer"); + }); + + afterAll(async () => { + await closePages(pages); + }); + + it("must check that the annotation isn't unselected when an other finger taps on the screen", async () => { + // Run sequentially to avoid clipboard issues. + for (const [, page] of pages) { + await switchToStamp(page); + + await copyImage(page, "../images/firefox_logo.png", 0); + const editorSelector = getEditorSelector(0); + const stampRect = await getRect(page, editorSelector); + + await page.touchscreen.tap(stampRect.x + 10, stampRect.y + 10); + await waitForSelectedEditor(page, editorSelector); + + await page.touchscreen.touchStart(stampRect.x + 10, stampRect.y + 10); + await page.touchscreen.touchMove(stampRect.x + 20, stampRect.y + 20); + await page.touchscreen.tap(stampRect.x - 10, stampRect.y - 10); + await page.touchscreen.touchEnd(); + + await waitForSelectedEditor(page, editorSelector); + } + }); + }); }); diff --git a/web/annotation_editor_layer_builder.css b/web/annotation_editor_layer_builder.css index 9592b9a744f24c..21671995bddae6 100644 --- a/web/annotation_editor_layer_builder.css +++ b/web/annotation_editor_layer_builder.css @@ -170,10 +170,6 @@ cursor: move; } - &.moving { - touch-action: none; - } - &.selectedEditor { border: var(--focus-outline); outline: var(--focus-outline-around);