From 9fce0112e275d859ae2bcfb5bc63377b13b1c416 Mon Sep 17 00:00:00 2001 From: Nils Pukropp Date: Tue, 20 Oct 2026 15:38:36 +0200 Subject: [PATCH] file pane: the PDF viewer gives the keys back Once clicked, the browser's PDF viewer keeps every key, and nothing it is sent reaches the page. The page sees the window lose the focus to the frame, and now says so over it: the viewer has the keys, moving the pointer off it takes them back, and `gx` opens it in a tab. The first pointer movement outside the frame hands the focus back to the workspace, where before only a click outside did. --- web/src/lib/FilePane.svelte | 50 ++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/web/src/lib/FilePane.svelte b/web/src/lib/FilePane.svelte index b80f3bb..0ddcdfb 100644 --- a/web/src/lib/FilePane.svelte +++ b/web/src/lib/FilePane.svelte @@ -112,6 +112,33 @@ } }) + /* + * The browser's PDF viewer keeps every key once it has been clicked, and + * nothing it is sent reaches the page. The page only sees the window lose + * the focus to the frame; it says so, and takes the keys back as soon as + * the pointer leaves the frame — the one move that still reaches it. + */ + let pdf = $state() + let pdfHasKeys = $state(false) + $effect(() => { + const frame = pdf + if (!frame) return + const blur = () => setTimeout(() => (pdfHasKeys = document.activeElement === frame)) + // The viewer keeps the pointer's events to itself too, so any of them + // reaching the page means the pointer is off the frame. + const leave = () => { + if (!pdfHasKeys) return + if (document.activeElement === frame) hooks.focusList() + pdfHasKeys = false + } + window.addEventListener('blur', blur) + document.addEventListener('pointermove', leave) + return () => { + window.removeEventListener('blur', blur) + document.removeEventListener('pointermove', leave) + } + }) + // Markdown read rendered has headings to jump between, as a document does. let article = $state() $effect(() => { @@ -190,7 +217,12 @@ {:else if kind === 'audio'} {:else if kind === 'pdf'} - +
+ + {#if pdfHasKeys} +

the pdf viewer has the keys — move the pointer off it to take them back · gx opens it in a tab

+ {/if} +
{:else if kind === 'cert'} {:else if text !== null} @@ -327,6 +359,22 @@ text-align: right; user-select: none; } + .pdfbox { position: relative; } + .pdfkeys { + position: absolute; + left: 50%; + bottom: 12px; + margin: 0; + padding: 6px 12px; + transform: translateX(-50%); + border: 1px solid var(--light-dim); + border-radius: var(--radius-s); + background: var(--hull); + color: var(--light); + font-size: 10px; + white-space: nowrap; + pointer-events: none; + } .pdf { display: block; width: 100%;