From 94bb38453d17405c6626eef99bbfe164fdcc6b63 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Wed, 16 Sep 2026 10:40:24 -0400 Subject: [PATCH] Don't classify selection-extension drags as swipe/pan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gesture classifier only checked whether the touch STARTED on a .textLayer span. Chromium's long-press selects the nearest word even when the finger landed between spans (on the .textLayer div, not a span inside it), so the classifier saw a non-selectable target and classified the drag as swipe/pan — preventDefault on the iframe's touchmove then cancelled the native selection extension mid-drag and could blank the PDF canvas. If any frame already has a non-collapsed selection, the drag is extending it. --- fixed-layout.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/fixed-layout.js b/fixed-layout.js index 716941d..ba9666e 100644 --- a/fixed-layout.js +++ b/fixed-layout.js @@ -686,6 +686,19 @@ export class FixedLayout extends HTMLElement { st.mode = "native"; // let the text layer handle selection return; } + // The long-press may have already engaged a native selection + // (Chromium selects the nearest word even when the finger + // landed between spans) — a drag with a live selection is + // extending it regardless of where the finger started. + // Classifying it as swipe/pan would preventDefault the + // touchmove and cancel the selection mid-drag. + for (const { doc } of this.getContents()) { + const sel = doc?.getSelection?.(); + if (sel && !sel.isCollapsed) { + st.mode = "native"; + return; + } + } if (this.#atFitScale()) { st.mode = "swipe"; // page-turn gesture } else {