From 547556b5b2940fb26c8d3faed131d1a2005abab2 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sun, 30 Oct 2022 17:36:20 +0100 Subject: [PATCH] Prevent keyboard interaction with form elements in PresentationMode (issue 12232) This uses the relatively new `HTMLElement.inert` property, see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert for additional information. The only "problem" is that this isn't yet available in all Firefox channels, but until https://bugzilla.mozilla.org/show_bug.cgi?id=1764263 is fixed we're no worse off than before. --- web/annotation_layer_builder.js | 50 +++++++++++++++++++++++++++++++++ web/interfaces.js | 5 ++++ web/pdf_link_service.js | 14 +++++++++ 3 files changed, 69 insertions(+) diff --git a/web/annotation_layer_builder.js b/web/annotation_layer_builder.js index 25dd70021..efbf308bf 100644 --- a/web/annotation_layer_builder.js +++ b/web/annotation_layer_builder.js @@ -24,6 +24,7 @@ import { AnnotationLayer } from "pdfjs-lib"; import { NullL10n } from "./l10n_utils.js"; +import { PresentationModeState } from "./ui_utils.js"; /** * @typedef {Object} AnnotationLayerBuilderOptions @@ -46,6 +47,8 @@ import { NullL10n } from "./l10n_utils.js"; */ class AnnotationLayerBuilder { + #onPresentationModeChanged = null; + /** * @param {AnnotationLayerBuilderOptions} options */ @@ -82,6 +85,7 @@ class AnnotationLayerBuilder { this.div = null; this._cancelled = false; + this._eventBus = linkService.eventBus; } /** @@ -134,11 +138,34 @@ class AnnotationLayerBuilder { AnnotationLayer.render(parameters); this.l10n.translate(this.div); + + // Ensure that interactive form elements in the annotationLayer are + // disabled while PresentationMode is active (see issue 12232). + if (this.linkService.isInPresentationMode) { + this.#updatePresentationModeState(PresentationModeState.FULLSCREEN); + } + if (!this.#onPresentationModeChanged) { + this.#onPresentationModeChanged = evt => { + this.#updatePresentationModeState(evt.state); + }; + this._eventBus?._on( + "presentationmodechanged", + this.#onPresentationModeChanged + ); + } } } cancel() { this._cancelled = true; + + if (this.#onPresentationModeChanged) { + this._eventBus?._off( + "presentationmodechanged", + this.#onPresentationModeChanged + ); + this.#onPresentationModeChanged = null; + } } hide() { @@ -147,6 +174,29 @@ class AnnotationLayerBuilder { } this.div.hidden = true; } + + #updatePresentationModeState(state) { + if (!this.div) { + return; + } + let disableFormElements = false; + + switch (state) { + case PresentationModeState.FULLSCREEN: + disableFormElements = true; + break; + case PresentationModeState.NORMAL: + break; + default: + return; + } + for (const section of this.div.childNodes) { + if (section.hasAttribute("data-internal-link")) { + continue; + } + section.inert = disableFormElements; + } + } } export { AnnotationLayerBuilder }; diff --git a/web/interfaces.js b/web/interfaces.js index 7cce362fc..2331511a1 100644 --- a/web/interfaces.js +++ b/web/interfaces.js @@ -61,6 +61,11 @@ class IPDFLinkService { */ set rotation(value) {} + /** + * @type {boolean} + */ + get isInPresentationMode() {} + /** * @type {boolean} */ diff --git a/web/pdf_link_service.js b/web/pdf_link_service.js index 52cba0ec2..de8172e6b 100644 --- a/web/pdf_link_service.js +++ b/web/pdf_link_service.js @@ -173,6 +173,13 @@ class PDFLinkService { this.pdfViewer.pagesRotation = value; } + /** + * @type {boolean} + */ + get isInPresentationMode() { + return this.pdfViewer.isInPresentationMode; + } + #goToDestinationHelper(rawDest, namedDest = null, explicitDest) { // Dest array looks like that: const destRef = explicitDest[0]; @@ -673,6 +680,13 @@ class SimpleLinkService { */ set rotation(value) {} + /** + * @type {boolean} + */ + get isInPresentationMode() { + return false; + } + /** * @param {string|Array} dest - The named, or explicit, PDF destination. */