From 86e234d0060c69b0c5045060b88f947fa7261d0a Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Mon, 17 Aug 2026 08:32:02 -0400 Subject: [PATCH] Fix rect hit-test denominator: use the rendered canvas for PDFs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit documentElement's screen rect is devicePixelRatio× smaller than the visible page because pdf.js scales by 1/dpr — using it as the hit-test denominator made click fractions dpr× too large, so clicks landed in the wrong place relative to stored (correct) fractions on any dpr != 1 display. The canvas's post-transform rect is exactly the visible page and shares the textLayer's transform space. --- fixed-layout.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fixed-layout.js b/fixed-layout.js index 29113a9..767089a 100644 --- a/fixed-layout.js +++ b/fixed-layout.js @@ -961,6 +961,9 @@ export class FixedLayout extends HTMLElement { // Click hit-testing for rect annotations (edit popover). Skipped while a // text selection is active so drag-selecting doesn't pop the editor. + // Denominator: the rendered canvas for PDFs (its post-transform rect IS + // the visible page; documentElement is dpr× too small because pdf.js + // scales by 1/devicePixelRatio), the img for comics. doc.addEventListener( "click", (event) => { @@ -968,9 +971,10 @@ export class FixedLayout extends HTMLElement { const sel = doc.getSelection(); if (sel && !sel.isCollapsed) return; const denom = - doc.querySelector("img") || doc.documentElement; - const dr = denom.getBoundingClientRect(); - if (!dr.width || !dr.height) return; + doc.querySelector("#canvas canvas") || + doc.querySelector("img"); + const dr = denom?.getBoundingClientRect(); + if (!dr || !dr.width || !dr.height) return; const fx = (event.clientX - dr.left) / dr.width; const fy = (event.clientY - dr.top) / dr.height; for (const [key, a] of this.#rectAnnotations) {