From 9ae7ad0fa6ffa44c9652297525ace053bb87f870 Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Wed, 9 Aug 2023 12:09:11 +0200 Subject: [PATCH] [Editor] Avoid to unselect some editors when the main window is focused When several editors are selected and the window loses and then gets back its focus, the previously focused editor is triggering its focus callback making it the only selected one. This patch aims to avoid triggering the focus callback called when the main window gets its focus back. --- src/display/editor/tools.js | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/display/editor/tools.js b/src/display/editor/tools.js index 8fe5b175d..637d0645a 100644 --- a/src/display/editor/tools.js +++ b/src/display/editor/tools.js @@ -544,12 +544,18 @@ class AnnotationEditorUIManager { #isEnabled = false; + #lastActiveElement = null; + #mode = AnnotationEditorType.NONE; #selectedEditors = new Set(); #pageColors = null; + #boundBlur = this.blur.bind(this); + + #boundFocus = this.focus.bind(this); + #boundCopy = this.copy.bind(this); #boundCut = this.cut.bind(this); @@ -701,6 +707,7 @@ class AnnotationEditorUIManager { destroy() { this.#removeKeyboardManager(); + this.#removeFocusManager(); this.#eventBus._off("editingaction", this.#boundOnEditingAction); this.#eventBus._off("pagechanging", this.#boundOnPageChanging); this.#eventBus._off("scalechanging", this.#boundOnScaleChanging); @@ -796,6 +803,50 @@ class AnnotationEditorUIManager { } } + #addFocusManager() { + window.addEventListener("focus", this.#boundFocus); + window.addEventListener("blur", this.#boundBlur); + } + + #removeFocusManager() { + window.removeEventListener("focus", this.#boundFocus); + window.removeEventListener("blur", this.#boundBlur); + } + + blur() { + if (!this.hasSelection) { + return; + } + // When several editors are selected and the window loses focus, we want to + // keep the last active element in order to be able to focus it again when + // the window gets the focus back but we don't want to trigger any focus + // callbacks else only one editor will be selected. + const { activeElement } = document; + for (const editor of this.#selectedEditors) { + if (editor.div.contains(activeElement)) { + this.#lastActiveElement = [editor, activeElement]; + editor._focusEventsAllowed = false; + break; + } + } + } + + focus() { + if (!this.#lastActiveElement) { + return; + } + const [lastEditor, lastActiveElement] = this.#lastActiveElement; + this.#lastActiveElement = null; + lastActiveElement.addEventListener( + "focusin", + () => { + lastEditor._focusEventsAllowed = true; + }, + { once: true } + ); + lastActiveElement.focus(); + } + #addKeyboardManager() { // The keyboard events are caught at the container level in order to be able // to execute some callbacks even if the current page doesn't have focus. @@ -967,6 +1018,7 @@ class AnnotationEditorUIManager { */ setEditingState(isEditing) { if (isEditing) { + this.#addFocusManager(); this.#addKeyboardManager(); this.#addCopyPasteListeners(); this.#dispatchUpdateStates({ @@ -977,6 +1029,7 @@ class AnnotationEditorUIManager { hasSelectedEditor: false, }); } else { + this.#removeFocusManager(); this.#removeKeyboardManager(); this.#removeCopyPasteListeners(); this.#dispatchUpdateStates({