Merge pull request #20213 from lab-core/pointer-type

[Editor] A new CurrentPointers class to store current pointers used by the editor
This commit is contained in:
calixteman 2025-11-01 19:17:32 +01:00 committed by GitHub
commit 2cc809ade2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 101 additions and 37 deletions

View File

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

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.
*/
@ -2801,5 +2882,6 @@ export {
bindEvents,
ColorManager,
CommandManager,
CurrentPointers,
KeyboardManager,
};