From 1305a5280cd34cc04118218dbc880f745a902c45 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Wed, 16 Sep 2026 17:23:59 -0400 Subject: [PATCH] Ignore small height-only viewport resizes in the fx renderer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mobile browser toolbar transitions change the viewport height by a fraction mid-gesture; re-rendering the PDF for that races with active text selections and can blank the canvas (the old canvas is cleared for the re-render, and the async pdf.js render can fail or get interrupted by the next resize). Only re-render for real layout changes — same threshold as the paginator. --- fixed-layout.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/fixed-layout.js b/fixed-layout.js index ba9666e..94585e3 100644 --- a/fixed-layout.js +++ b/fixed-layout.js @@ -25,7 +25,24 @@ const getViewport = (doc, viewport) => { export class FixedLayout extends HTMLElement { static observedAttributes = ["zoom", "interaction-mode", "spread"]; #root = this.attachShadow({ mode: "closed" }); - #observer = new ResizeObserver(() => this.#onResize()); + #observer = new ResizeObserver((entries) => { + // Mobile browsers grow/shrink the viewport by ~7-17% when the + // toolbar hides/shows mid-gesture; re-rendering the PDF for that + // races with active selections and can blank the canvas. Only + // re-render for real layout changes: any width change, or a + // height change large enough to be a rotation, keyboard, or + // split-screen. + const rect = entries?.[entries.length - 1]?.contentRect; + if (rect && rect.width && rect.height && this.#lastSize) { + const [w, h] = this.#lastSize; + if (Math.abs(rect.width - w) < 1 && Math.abs(rect.height - h) / h < 0.25) + return; + } + if (rect && rect.width && rect.height) + this.#lastSize = [rect.width, rect.height]; + this.#onResize(); + }); + #lastSize; #spreads; #index = -1; defaultViewport;