[Editor] Replace mouse events by pointer ones (bug 1779015)

The goal is to be able to edit a pdf on a touchscreen.
This commit is contained in:
Calixte Denizet 2022-07-19 18:20:56 +02:00
parent 185102bd69
commit 7b25b39a17
5 changed files with 77 additions and 61 deletions

View File

@ -43,9 +43,9 @@ import { InkEditor } from "./ink.js";
class AnnotationEditorLayer { class AnnotationEditorLayer {
#allowClick = false; #allowClick = false;
#boundClick; #boundPointerup = this.pointerup.bind(this);
#boundMousedown; #boundPointerdown = this.pointerdown.bind(this);
#editors = new Map(); #editors = new Map();
@ -76,8 +76,6 @@ class AnnotationEditorLayer {
this.annotationStorage = options.annotationStorage; this.annotationStorage = options.annotationStorage;
this.pageIndex = options.pageIndex; this.pageIndex = options.pageIndex;
this.div = options.div; this.div = options.div;
this.#boundClick = this.click.bind(this);
this.#boundMousedown = this.mousedown.bind(this);
this.#uiManager.addLayer(this); this.#uiManager.addLayer(this);
} }
@ -213,13 +211,13 @@ class AnnotationEditorLayer {
} }
enableClick() { enableClick() {
this.div.addEventListener("mousedown", this.#boundMousedown); this.div.addEventListener("pointerdown", this.#boundPointerdown);
this.div.addEventListener("click", this.#boundClick); this.div.addEventListener("pointerup", this.#boundPointerup);
} }
disableClick() { disableClick() {
this.div.removeEventListener("mousedown", this.#boundMousedown); this.div.removeEventListener("pointerdown", this.#boundPointerdown);
this.div.removeEventListener("click", this.#boundClick); this.div.removeEventListener("pointerup", this.#boundPointerup);
} }
attach(editor) { attach(editor) {
@ -524,7 +522,7 @@ class AnnotationEditorLayer {
/** /**
* Create and add a new editor. * Create and add a new editor.
* @param {MouseEvent} event * @param {PointerEvent} event
* @returns {AnnotationEditor} * @returns {AnnotationEditor}
*/ */
#createAndAddNewEditor(event) { #createAndAddNewEditor(event) {
@ -579,10 +577,10 @@ class AnnotationEditorLayer {
} }
/** /**
* Mouseclick callback. * Pointerup callback.
* @param {MouseEvent} event * @param {PointerEvent} event
*/ */
click(event) { pointerup(event) {
if (event.target !== this.div) { if (event.target !== this.div) {
return; return;
} }
@ -596,10 +594,10 @@ class AnnotationEditorLayer {
} }
/** /**
* Mousedown callback. * Pointerdown callback.
* @param {MouseEvent} event * @param {PointerEvent} event
*/ */
mousedown(event) { pointerdown(event) {
if (event.target !== this.div) { if (event.target !== this.div) {
return; return;
} }

View File

@ -251,7 +251,7 @@ class AnnotationEditor {
this.div.setAttribute("data-editor-rotation", (360 - this.rotation) % 360); this.div.setAttribute("data-editor-rotation", (360 - this.rotation) % 360);
this.div.className = this.name; this.div.className = this.name;
this.div.setAttribute("id", this.id); this.div.setAttribute("id", this.id);
this.div.tabIndex = 0; this.div.setAttribute("tabIndex", 0);
this.setInForeground(); this.setInForeground();
@ -261,16 +261,16 @@ class AnnotationEditor {
const [tx, ty] = this.getInitialTranslation(); const [tx, ty] = this.getInitialTranslation();
this.translate(tx, ty); this.translate(tx, ty);
bindEvents(this, this.div, ["dragstart", "mousedown", "mouseup"]); bindEvents(this, this.div, ["dragstart", "pointerdown", "pointerup"]);
return this.div; return this.div;
} }
/** /**
* Onmousedown callback. * Onpointerdown callback.
* @param {MouseEvent} event * @param {PointerEvent} event
*/ */
mousedown(event) { pointerdown(event) {
if (event.button !== 0) { if (event.button !== 0) {
// Avoid to focus this editor because of a non-left click. // Avoid to focus this editor because of a non-left click.
event.preventDefault(); event.preventDefault();
@ -284,9 +284,9 @@ class AnnotationEditor {
/** /**
* Onmouseup callback. * Onmouseup callback.
* @param {MouseEvent} event * @param {PointerEvent} event
*/ */
mouseup(event) { pointerup(event) {
if (this.#wasFocused) { if (this.#wasFocused) {
this.#select(); this.#select();
} }

View File

@ -223,7 +223,6 @@ class FreeTextEditor extends AnnotationEditor {
this.overlayDiv.classList.remove("enabled"); this.overlayDiv.classList.remove("enabled");
this.editorDiv.contentEditable = true; this.editorDiv.contentEditable = true;
this.div.draggable = false; this.div.draggable = false;
this.div.removeAttribute("tabIndex");
this.editorDiv.addEventListener("keydown", this.#boundEditorDivKeydown); this.editorDiv.addEventListener("keydown", this.#boundEditorDivKeydown);
this.editorDiv.addEventListener("focus", this.#boundEditorDivFocus); this.editorDiv.addEventListener("focus", this.#boundEditorDivFocus);
this.editorDiv.addEventListener("blur", this.#boundEditorDivBlur); this.editorDiv.addEventListener("blur", this.#boundEditorDivBlur);
@ -236,17 +235,27 @@ class FreeTextEditor extends AnnotationEditor {
this.overlayDiv.classList.add("enabled"); this.overlayDiv.classList.add("enabled");
this.editorDiv.contentEditable = false; this.editorDiv.contentEditable = false;
this.div.draggable = true; this.div.draggable = true;
this.div.tabIndex = 0;
this.editorDiv.removeEventListener("keydown", this.#boundEditorDivKeydown); this.editorDiv.removeEventListener("keydown", this.#boundEditorDivKeydown);
this.editorDiv.removeEventListener("focus", this.#boundEditorDivFocus); this.editorDiv.removeEventListener("focus", this.#boundEditorDivFocus);
this.editorDiv.removeEventListener("blur", this.#boundEditorDivBlur); this.editorDiv.removeEventListener("blur", this.#boundEditorDivBlur);
// In case the blur callback hasn't been called.
this.isEditing = false;
}
/** @inheritdoc */
focusin(event) {
super.focusin(event);
if (event.target !== this.editorDiv) {
this.editorDiv.focus();
}
} }
/** @inheritdoc */ /** @inheritdoc */
onceAdded() { onceAdded() {
if (this.width) { if (this.width) {
// The editor was created in using ctrl+c. // The editor was created in using ctrl+c.
this.div.focus(); this.parent.setActiveEditor(this);
return; return;
} }
this.enableEditMode(); this.enableEditMode();
@ -330,7 +339,7 @@ class FreeTextEditor extends AnnotationEditor {
/** /**
* onkeydown callback. * onkeydown callback.
* @param {MouseEvent} event * @param {KeyboardEvent} event
*/ */
keydown(event) { keydown(event) {
if (event.target === this.div && event.key === "Enter") { if (event.target === this.div && event.key === "Enter") {
@ -423,6 +432,10 @@ class FreeTextEditor extends AnnotationEditor {
// eslint-disable-next-line no-unsanitized/property // eslint-disable-next-line no-unsanitized/property
this.editorDiv.innerHTML = this.#contentHTML; this.editorDiv.innerHTML = this.#contentHTML;
this.div.draggable = true; this.div.draggable = true;
this.editorDiv.contentEditable = false;
} else {
this.div.draggable = false;
this.editorDiv.contentEditable = true;
} }
return this.div; return this.div;

View File

@ -36,13 +36,13 @@ class InkEditor extends AnnotationEditor {
#baseWidth = 0; #baseWidth = 0;
#boundCanvasMousemove; #boundCanvasPointermove = this.canvasPointermove.bind(this);
#boundCanvasMouseleave; #boundCanvasPointerleave = this.canvasPointerleave.bind(this);
#boundCanvasMouseup; #boundCanvasPointerup = this.canvasPointerup.bind(this);
#boundCanvasMousedown; #boundCanvasPointerdown = this.canvasPointerdown.bind(this);
#disableEditing = false; #disableEditing = false;
@ -71,11 +71,6 @@ class InkEditor extends AnnotationEditor {
this.translationX = this.translationY = 0; this.translationX = this.translationY = 0;
this.x = 0; this.x = 0;
this.y = 0; this.y = 0;
this.#boundCanvasMousemove = this.canvasMousemove.bind(this);
this.#boundCanvasMouseleave = this.canvasMouseleave.bind(this);
this.#boundCanvasMouseup = this.canvasMouseup.bind(this);
this.#boundCanvasMousedown = this.canvasMousedown.bind(this);
} }
static initialize(l10n) { static initialize(l10n) {
@ -230,8 +225,8 @@ class InkEditor extends AnnotationEditor {
super.enableEditMode(); super.enableEditMode();
this.div.draggable = false; this.div.draggable = false;
this.canvas.addEventListener("mousedown", this.#boundCanvasMousedown); this.canvas.addEventListener("pointerdown", this.#boundCanvasPointerdown);
this.canvas.addEventListener("mouseup", this.#boundCanvasMouseup); this.canvas.addEventListener("pointerup", this.#boundCanvasPointerup);
} }
/** @inheritdoc */ /** @inheritdoc */
@ -244,8 +239,11 @@ class InkEditor extends AnnotationEditor {
this.div.draggable = !this.isEmpty(); this.div.draggable = !this.isEmpty();
this.div.classList.remove("editing"); this.div.classList.remove("editing");
this.canvas.removeEventListener("mousedown", this.#boundCanvasMousedown); this.canvas.removeEventListener(
this.canvas.removeEventListener("mouseup", this.#boundCanvasMouseup); "pointerdown",
this.#boundCanvasPointerdown
);
this.canvas.removeEventListener("pointerup", this.#boundCanvasPointerup);
} }
/** @inheritdoc */ /** @inheritdoc */
@ -393,7 +391,6 @@ class InkEditor extends AnnotationEditor {
/** /**
* Commit the curves we have in this editor. * Commit the curves we have in this editor.
* @returns {undefined}
*/ */
commit() { commit() {
if (this.#disableEditing) { if (this.#disableEditing) {
@ -428,11 +425,10 @@ class InkEditor extends AnnotationEditor {
} }
/** /**
* onmousedown callback for the canvas we're drawing on. * onpointerdown callback for the canvas we're drawing on.
* @param {MouseEvent} event * @param {PointerEvent} event
* @returns {undefined}
*/ */
canvasMousedown(event) { canvasPointerdown(event) {
if (event.button !== 0 || !this.isInEditMode() || this.#disableEditing) { if (event.button !== 0 || !this.isInEditMode() || this.#disableEditing) {
return; return;
} }
@ -441,30 +437,32 @@ class InkEditor extends AnnotationEditor {
// Since it's the last child, there's no need to give it a higher z-index. // Since it's the last child, there's no need to give it a higher z-index.
this.setInForeground(); this.setInForeground();
if (event.type !== "mouse") {
this.div.focus();
}
event.stopPropagation(); event.stopPropagation();
this.canvas.addEventListener("mouseleave", this.#boundCanvasMouseleave); this.canvas.addEventListener("pointerleave", this.#boundCanvasPointerleave);
this.canvas.addEventListener("mousemove", this.#boundCanvasMousemove); this.canvas.addEventListener("pointermove", this.#boundCanvasPointermove);
this.#startDrawing(event.offsetX, event.offsetY); this.#startDrawing(event.offsetX, event.offsetY);
} }
/** /**
* onmousemove callback for the canvas we're drawing on. * onpointermove callback for the canvas we're drawing on.
* @param {MouseEvent} event * @param {PointerEvent} event
* @returns {undefined}
*/ */
canvasMousemove(event) { canvasPointermove(event) {
event.stopPropagation(); event.stopPropagation();
this.#draw(event.offsetX, event.offsetY); this.#draw(event.offsetX, event.offsetY);
} }
/** /**
* onmouseup callback for the canvas we're drawing on. * onpointerup callback for the canvas we're drawing on.
* @param {MouseEvent} event * @param {PointerEvent} event
* @returns {undefined}
*/ */
canvasMouseup(event) { canvasPointerup(event) {
if (event.button !== 0) { if (event.button !== 0) {
return; return;
} }
@ -479,24 +477,29 @@ class InkEditor extends AnnotationEditor {
} }
/** /**
* onmouseleave callback for the canvas we're drawing on. * onpointerleave callback for the canvas we're drawing on.
* @param {MouseEvent} event * @param {PointerEvent} event
* @returns {undefined}
*/ */
canvasMouseleave(event) { canvasPointerleave(event) {
this.#endDrawing(event); this.#endDrawing(event);
this.setInBackground(); this.setInBackground();
} }
/** /**
* End the drawing. * End the drawing.
* @param {MouseEvent} event * @param {PointerEvent} event
*/ */
#endDrawing(event) { #endDrawing(event) {
this.#stopDrawing(event.offsetX, event.offsetY); this.#stopDrawing(event.offsetX, event.offsetY);
this.canvas.removeEventListener("mouseleave", this.#boundCanvasMouseleave); this.canvas.removeEventListener(
this.canvas.removeEventListener("mousemove", this.#boundCanvasMousemove); "pointerleave",
this.#boundCanvasPointerleave
);
this.canvas.removeEventListener(
"pointermove",
this.#boundCanvasPointermove
);
} }
/** /**

View File

@ -62,6 +62,7 @@
height: auto; height: auto;
z-index: 1; z-index: 1;
transform-origin: 0 0; transform-origin: 0 0;
touch-action: none;
} }
.annotationEditorLayer .freeTextEditor .internal { .annotationEditorLayer .freeTextEditor .internal {
@ -135,4 +136,5 @@
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
touch-action: none;
} }