diff --git a/src/shared/util.js b/src/shared/util.js index 9757d441d..34784ee00 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -711,6 +711,14 @@ class FeatureTest { input.value !== "#ff0000" ); } + + static get isBackdropFilterSupported() { + return shadow( + this, + "isBackdropFilterSupported", + typeof CSS !== "undefined" && CSS.supports("backdrop-filter", "blur(1px)") + ); + } } class Util { diff --git a/test/integration/text_layer_spec.mjs b/test/integration/text_layer_spec.mjs index 1bb8099fe..50e9c54da 100644 --- a/test/integration/text_layer_spec.mjs +++ b/test/integration/text_layer_spec.mjs @@ -1082,6 +1082,72 @@ describe("Text layer", () => { ); }); }); + + describe("when `backdrop-filter` is unsupported", () => { + let pages; + + beforeEach(async () => { + pages = await loadAndWait( + "tracemonkey.pdf", + `.page[data-page-number = "1"] .endOfContent`, + undefined, + { + prePageSetup: page => + page.evaluateOnNewDocument(() => { + const { supports } = CSS; + CSS.supports = (property, value) => + property === "backdrop-filter" + ? false + : supports.call(CSS, property, value); + }), + }, + (_page, browserName) => ({ + imagesRightClickMinSize: browserName === "firefox" ? 16 : -1, + }) + ); + }); + + afterEach(async () => { + await closePages(pages); + }); + + it("does not render a selection overlay in the draw layer", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + const [positionStart, positionEnd] = await Promise.all([ + getSpanRectFromText( + page, + 1, + "(frequently executed) bytecode sequences, records" + ).then(middlePosition), + getSpanRectFromText( + page, + 1, + "them, and compiles them to fast native code. We call such a se-" + ).then(belowEndPosition), + ]); + + await page.mouse.move(positionStart.x, positionStart.y); + await page.mouse.down(); + await moveInSteps(page, positionStart, positionEnd, 20); + await page.mouse.up(); + + // Text should still be selectable. + const selectedText = await getSelectionText(page); + expect(selectedText.length) + .withContext(`In ${browserName}, text is still selectable`) + .toBeGreaterThan(0); + + // But no selection overlay should appear in the draw layer. + expect(await hasDrawnSelection(page)) + .withContext( + `In ${browserName}, no selection drawn without backdrop-filter` + ) + .toBeFalse(); + }) + ); + }); + }); }); describe("using selection carets", () => { diff --git a/web/base_pdf_page_view.js b/web/base_pdf_page_view.js index 9f9488471..d85cac82e 100644 --- a/web/base_pdf_page_view.js +++ b/web/base_pdf_page_view.js @@ -13,8 +13,8 @@ * limitations under the License. */ +import { FeatureTest, RenderingCancelledException } from "pdfjs-lib"; import { RenderableView, RenderingStates } from "./renderable_view.js"; -import { RenderingCancelledException } from "pdfjs-lib"; class BasePDFPageView extends RenderableView { #loadingId = null; @@ -60,7 +60,9 @@ class BasePDFPageView extends RenderableView { this.renderingQueue = options.renderingQueue; this.enableOptimizedPartialRendering = options.enableOptimizedPartialRendering ?? false; - this.enableSelectionRendering = options.enableSelectionRendering !== false; + this.enableSelectionRendering = + options.enableSelectionRendering !== false && + FeatureTest.isBackdropFilterSupported; this.imagesRightClickMinSize = options.imagesRightClickMinSize ?? -1; this.minDurationToUpdateCanvas = options.minDurationToUpdateCanvas ?? 500; }