Merge pull request #15648 from Snuffleupagus/issue-12232

Prevent interaction with form elements in PresentationMode (issue 12232)
This commit is contained in:
Jonas Jenwald 2022-10-31 11:14:23 +01:00 committed by GitHub
commit 6193537cd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 98 additions and 22 deletions

View File

@ -645,6 +645,10 @@ class LinkAnnotationElement extends AnnotationElement {
return this.container; return this.container;
} }
#setInternalLink() {
this.container.setAttribute("data-internal-link", "");
}
/** /**
* Bind internal links to the link element. * Bind internal links to the link element.
* *
@ -662,7 +666,7 @@ class LinkAnnotationElement extends AnnotationElement {
return false; return false;
}; };
if (destination || destination === /* isTooltipOnly = */ "") { if (destination || destination === /* isTooltipOnly = */ "") {
link.className = "internalLink"; this.#setInternalLink();
} }
} }
@ -680,7 +684,7 @@ class LinkAnnotationElement extends AnnotationElement {
this.linkService.executeNamedAction(action); this.linkService.executeNamedAction(action);
return false; return false;
}; };
link.className = "internalLink"; this.#setInternalLink();
} }
/** /**
@ -698,7 +702,7 @@ class LinkAnnotationElement extends AnnotationElement {
); );
return false; return false;
}; };
link.className = "internalLink"; this.#setInternalLink();
} }
/** /**
@ -712,7 +716,7 @@ class LinkAnnotationElement extends AnnotationElement {
this.linkService.executeSetOCGState(action); this.linkService.executeSetOCGState(action);
return false; return false;
}; };
link.className = "internalLink"; this.#setInternalLink();
} }
/** /**
@ -750,7 +754,7 @@ class LinkAnnotationElement extends AnnotationElement {
if (!link.onclick) { if (!link.onclick) {
link.onclick = () => false; link.onclick = () => false;
} }
link.className = "internalLink"; this.#setInternalLink();
} }
_bindResetFormAction(link, resetForm) { _bindResetFormAction(link, resetForm) {
@ -758,7 +762,7 @@ class LinkAnnotationElement extends AnnotationElement {
if (!otherClickAction) { if (!otherClickAction) {
link.href = this.linkService.getAnchorUrl(""); link.href = this.linkService.getAnchorUrl("");
} }
link.className = "internalLink"; this.#setInternalLink();
if (!this._fieldObjects) { if (!this._fieldObjects) {
warn( warn(

View File

@ -24,6 +24,7 @@
import { AnnotationLayer } from "pdfjs-lib"; import { AnnotationLayer } from "pdfjs-lib";
import { NullL10n } from "./l10n_utils.js"; import { NullL10n } from "./l10n_utils.js";
import { PresentationModeState } from "./ui_utils.js";
/** /**
* @typedef {Object} AnnotationLayerBuilderOptions * @typedef {Object} AnnotationLayerBuilderOptions
@ -46,6 +47,8 @@ import { NullL10n } from "./l10n_utils.js";
*/ */
class AnnotationLayerBuilder { class AnnotationLayerBuilder {
#onPresentationModeChanged = null;
/** /**
* @param {AnnotationLayerBuilderOptions} options * @param {AnnotationLayerBuilderOptions} options
*/ */
@ -82,6 +85,7 @@ class AnnotationLayerBuilder {
this.div = null; this.div = null;
this._cancelled = false; this._cancelled = false;
this._eventBus = linkService.eventBus;
} }
/** /**
@ -134,11 +138,34 @@ class AnnotationLayerBuilder {
AnnotationLayer.render(parameters); AnnotationLayer.render(parameters);
this.l10n.translate(this.div); 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() { cancel() {
this._cancelled = true; this._cancelled = true;
if (this.#onPresentationModeChanged) {
this._eventBus?._off(
"presentationmodechanged",
this.#onPresentationModeChanged
);
this.#onPresentationModeChanged = null;
}
} }
hide() { hide() {
@ -147,6 +174,29 @@ class AnnotationLayerBuilder {
} }
this.div.hidden = true; 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 }; export { AnnotationLayerBuilder };

View File

@ -61,6 +61,11 @@ class IPDFLinkService {
*/ */
set rotation(value) {} set rotation(value) {}
/**
* @type {boolean}
*/
get isInPresentationMode() {}
/** /**
* @type {boolean} * @type {boolean}
*/ */

View File

@ -173,6 +173,13 @@ class PDFLinkService {
this.pdfViewer.pagesRotation = value; this.pdfViewer.pagesRotation = value;
} }
/**
* @type {boolean}
*/
get isInPresentationMode() {
return this.pdfViewer.isInPresentationMode;
}
#goToDestinationHelper(rawDest, namedDest = null, explicitDest) { #goToDestinationHelper(rawDest, namedDest = null, explicitDest) {
// Dest array looks like that: <page-ref> </XYZ|/FitXXX> <args..> // Dest array looks like that: <page-ref> </XYZ|/FitXXX> <args..>
const destRef = explicitDest[0]; const destRef = explicitDest[0];
@ -673,6 +680,13 @@ class SimpleLinkService {
*/ */
set rotation(value) {} set rotation(value) {}
/**
* @type {boolean}
*/
get isInPresentationMode() {
return false;
}
/** /**
* @param {string|Array} dest - The named, or explicit, PDF destination. * @param {string|Array} dest - The named, or explicit, PDF destination.
*/ */

View File

@ -224,21 +224,24 @@ class PDFPresentationMode {
evt.preventDefault(); evt.preventDefault();
return; return;
} }
if (evt.button === 0) { if (evt.button !== 0) {
// Enable clicking of links in presentation mode. Note: only links return;
// pointing to destinations in the current PDF document work. }
const isInternalLink = // Enable clicking of links in presentation mode. Note: only links
evt.target.href && evt.target.classList.contains("internalLink"); // pointing to destinations in the current PDF document work.
if (!isInternalLink) { if (
// Unless an internal link was clicked, advance one page. evt.target.href &&
evt.preventDefault(); evt.target.parentNode?.hasAttribute("data-internal-link")
) {
return;
}
// Unless an internal link was clicked, advance one page.
evt.preventDefault();
if (evt.shiftKey) { if (evt.shiftKey) {
this.pdfViewer.previousPage(); this.pdfViewer.previousPage();
} else { } else {
this.pdfViewer.nextPage(); this.pdfViewer.nextPage();
}
}
} }
} }

View File

@ -222,8 +222,8 @@ body {
user-select: none; user-select: none;
} }
.pdfPresentationMode:fullscreen a:not(.internalLink) { .pdfPresentationMode:fullscreen section:not([data-internal-link]) {
display: none; pointer-events: none;
} }
.pdfPresentationMode:fullscreen .textLayer span { .pdfPresentationMode:fullscreen .textLayer span {