A new CurrentPointers class to store current pointers used by the editor

Move current pointer field of DrawingEditor to CurrentPointer class in tools.js: The pointer types fields have been moved to a CurrentPointer object in tools.js. This object is used by eraser.js and ink.js.
Only reset pointer type when user select a new mode: Clear the pointer type when changing mode, instead of at the end of the session. It seems more stable, as the method is not called this way when the user changes pages. Also, clear the pointer type when the mode is changed by an event (the user changes the editor type), otherwise, the same pointer type is kept (the document is changed for example)
This commit is contained in:
legraina 2025-09-02 21:11:04 -04:00
parent 9f397a632c
commit a932804fb5
No known key found for this signature in database
GPG Key ID: 1B9D3DE90074C751
2 changed files with 101 additions and 37 deletions

View File

@ -16,6 +16,7 @@
import { AnnotationEditorParamsType, unreachable } from "../../shared/util.js"; import { AnnotationEditorParamsType, unreachable } from "../../shared/util.js";
import { noContextMenu, stopEvent } from "../display_utils.js"; import { noContextMenu, stopEvent } from "../display_utils.js";
import { AnnotationEditor } from "./editor.js"; import { AnnotationEditor } from "./editor.js";
import { CurrentPointers } from "./tools.js";
class DrawingOptions { class DrawingOptions {
#svgProperties = Object.create(null); #svgProperties = Object.create(null);
@ -81,14 +82,6 @@ class DrawingEditor extends AnnotationEditor {
static #currentDrawingOptions = null; static #currentDrawingOptions = null;
static #currentPointerId = NaN;
static #currentPointerType = null;
static #currentPointerIds = null;
static #currentMoveTimestamp = NaN;
static _INNER_MARGIN = 3; static _INNER_MARGIN = 3;
constructor(params) { constructor(params) {
@ -678,20 +671,15 @@ class DrawingEditor extends AnnotationEditor {
} }
static startDrawing(parent, uiManager, _isLTR, event) { static startDrawing(parent, uiManager, _isLTR, event) {
// The _currentPointerType is set when the user starts an empty drawing // The pointerType of CurrentPointer is set when the user starts an empty
// session. If, in the same drawing session, the user starts using a // drawing session. If, in the same drawing session, the user starts using a
// different type of pointer (e.g. a pen and then a finger), we just return. // different type of pointer (e.g. a pen and then a finger), we just return.
// //
// The _currentPointerId and _currentPointerIds are used to keep track of // If the user starts to draw with a finger and then uses a second finger,
// the pointers with a same type (e.g. two fingers). If the user starts to // we just stop the current drawing and let the user zoom the document.
// draw with a finger and then uses a second finger, we just stop the
// current drawing and let the user zoom the document.
const { target, offsetX: x, offsetY: y, pointerId, pointerType } = event; const { target, offsetX: x, offsetY: y, pointerId, pointerType } = event;
if ( if (CurrentPointers.isInitializedAndDifferentPointerType(pointerType)) {
DrawingEditor.#currentPointerType &&
DrawingEditor.#currentPointerType !== pointerType
) {
return; return;
} }
@ -704,16 +692,13 @@ class DrawingEditor extends AnnotationEditor {
const ac = (DrawingEditor.#currentDrawingAC = new AbortController()); const ac = (DrawingEditor.#currentDrawingAC = new AbortController());
const signal = parent.combinedSignal(ac); const signal = parent.combinedSignal(ac);
DrawingEditor.#currentPointerId ||= pointerId; CurrentPointers.setPointer(pointerType, pointerId);
DrawingEditor.#currentPointerType ??= pointerType;
window.addEventListener( window.addEventListener(
"pointerup", "pointerup",
e => { e => {
if (DrawingEditor.#currentPointerId === e.pointerId) { if (CurrentPointers.isSamePointerIdOrRemove(e.pointerId)) {
this._endDraw(e); this._endDraw(e);
} else {
DrawingEditor.#currentPointerIds?.delete(e.pointerId);
} }
}, },
{ signal } { signal }
@ -721,10 +706,8 @@ class DrawingEditor extends AnnotationEditor {
window.addEventListener( window.addEventListener(
"pointercancel", "pointercancel",
e => { e => {
if (DrawingEditor.#currentPointerId === e.pointerId) { if (CurrentPointers.isSamePointerIdOrRemove(e.pointerId)) {
this._currentParent.endDrawingSession(); this._currentParent.endDrawingSession();
} else {
DrawingEditor.#currentPointerIds?.delete(e.pointerId);
} }
}, },
{ signal } { signal }
@ -732,14 +715,14 @@ class DrawingEditor extends AnnotationEditor {
window.addEventListener( window.addEventListener(
"pointerdown", "pointerdown",
e => { e => {
if (DrawingEditor.#currentPointerType !== e.pointerType) { if (!CurrentPointers.isSamePointerType(e.pointerType)) {
// For example, we started with a pen and the user // For example, we started with a pen and the user
// is now using a finger. // is now using a finger.
return; return;
} }
// For example, the user is using a second finger. // For example, the user is using a second finger.
(DrawingEditor.#currentPointerIds ||= new Set()).add(e.pointerId); CurrentPointers.initializeAndAddPointerId(e.pointerId);
// The first finger created a first point and a second finger just // The first finger created a first point and a second finger just
// started, so we stop the drawing and remove this only point. // started, so we stop the drawing and remove this only point.
@ -765,7 +748,7 @@ class DrawingEditor extends AnnotationEditor {
target.addEventListener( target.addEventListener(
"touchmove", "touchmove",
e => { e => {
if (e.timeStamp === DrawingEditor.#currentMoveTimestamp) { if (CurrentPointers.isSameTimeStamp(e.timeStamp)) {
// This move event is used to draw so we don't want to scroll. // This move event is used to draw so we don't want to scroll.
stopEvent(e); stopEvent(e);
} }
@ -812,16 +795,16 @@ class DrawingEditor extends AnnotationEditor {
} }
static _drawMove(event) { static _drawMove(event) {
DrawingEditor.#currentMoveTimestamp = -1; CurrentPointers.isSameTimeStamp(event.timeStamp);
if (!DrawingEditor.#currentDraw) { if (!DrawingEditor.#currentDraw) {
return; return;
} }
const { offsetX, offsetY, pointerId } = event; const { offsetX, offsetY, pointerId } = event;
if (DrawingEditor.#currentPointerId !== pointerId) { if (!CurrentPointers.isSamePointerId(pointerId)) {
return; return;
} }
if (DrawingEditor.#currentPointerIds?.size >= 1) { if (CurrentPointers.isUsingMultiplePointers()) {
// The user is using multiple fingers and the first one is moving. // The user is using multiple fingers and the first one is moving.
this._endDraw(event); this._endDraw(event);
return; return;
@ -831,7 +814,7 @@ class DrawingEditor extends AnnotationEditor {
DrawingEditor.#currentDraw.add(offsetX, offsetY) DrawingEditor.#currentDraw.add(offsetX, offsetY)
); );
// We track the timestamp to know if the touchmove event is used to draw. // We track the timestamp to know if the touchmove event is used to draw.
DrawingEditor.#currentMoveTimestamp = event.timeStamp; CurrentPointers.setTimeStamp(event.timeStamp);
stopEvent(event); stopEvent(event);
} }
@ -841,15 +824,14 @@ class DrawingEditor extends AnnotationEditor {
this._currentParent = null; this._currentParent = null;
DrawingEditor.#currentDraw = null; DrawingEditor.#currentDraw = null;
DrawingEditor.#currentDrawingOptions = null; DrawingEditor.#currentDrawingOptions = null;
DrawingEditor.#currentPointerType = null; CurrentPointers.clearPointerType();
DrawingEditor.#currentMoveTimestamp = NaN; CurrentPointers.clearTimeStamp();
} }
if (DrawingEditor.#currentDrawingAC) { if (DrawingEditor.#currentDrawingAC) {
DrawingEditor.#currentDrawingAC.abort(); DrawingEditor.#currentDrawingAC.abort();
DrawingEditor.#currentDrawingAC = null; DrawingEditor.#currentDrawingAC = null;
DrawingEditor.#currentPointerId = NaN; CurrentPointers.clearPointerIds();
DrawingEditor.#currentPointerIds = null;
} }
} }

View File

@ -42,6 +42,87 @@ function bindEvents(obj, element, names) {
} }
} }
/**
* Class to store current pointers used by the editor to be able to handle
* multiple pointers (e.g. two fingers, a pen, a mouse, ...).
*/
class CurrentPointers {
// To manage the pointer events.
// The pointerId and pointerIds are used to keep track of
// the pointers with a same type (e.g. two fingers).
static #pointerId = NaN;
static #pointerIds = null;
// Track the timestamp to know if the touchmove event is used.
static #moveTimestamp = NaN;
// The pointerType is used to know if we are using a mouse, a pen or a touch.
static #pointerType = null;
static initializeAndAddPointerId(pointerId) {
// Store pointer ids. For example, the user is using a second finger.
(CurrentPointers.#pointerIds ||= new Set()).add(pointerId);
}
static setPointer(pointerType, pointerId) {
CurrentPointers.#pointerId ||= pointerId;
CurrentPointers.#pointerType ??= pointerType;
}
static setTimeStamp(timeStamp) {
CurrentPointers.#moveTimestamp = timeStamp;
}
static isSamePointerId(pointerId) {
return CurrentPointers.#pointerId === pointerId;
}
// Check if it's the same pointer id, otherwise remove it from the set.
static isSamePointerIdOrRemove(pointerId) {
if (CurrentPointers.#pointerId === pointerId) {
return true;
}
CurrentPointers.#pointerIds?.delete(pointerId);
return false;
}
static isSamePointerType(pointerType) {
return CurrentPointers.#pointerType === pointerType;
}
static isInitializedAndDifferentPointerType(pointerType) {
return (
CurrentPointers.#pointerType !== null &&
!CurrentPointers.isSamePointerType(pointerType)
);
}
static isSameTimeStamp(timeStamp) {
return CurrentPointers.#moveTimestamp === timeStamp;
}
static isUsingMultiplePointers() {
// Check if the user is using multiple fingers
return CurrentPointers.#pointerIds?.size >= 1;
}
static clearPointerType() {
CurrentPointers.#pointerType = null;
}
static clearPointerIds() {
CurrentPointers.#pointerId = NaN;
CurrentPointers.#pointerIds = null;
}
static clearTimeStamp() {
CurrentPointers.#moveTimestamp = NaN;
}
}
/** /**
* Class to create some unique ids for the different editors. * Class to create some unique ids for the different editors.
*/ */
@ -2801,5 +2882,6 @@ export {
bindEvents, bindEvents,
ColorManager, ColorManager,
CommandManager, CommandManager,
CurrentPointers,
KeyboardManager, KeyboardManager,
}; };