diff --git a/js/app.js b/js/app.js index 00bb14d..28a98cb 100644 --- a/js/app.js +++ b/js/app.js @@ -207,6 +207,7 @@ const Bridge = (() => { } let tp = ''; if (combos.totp) { + // (see suspendHotkeys below for why vk=0 matters) const t = autofillComboToWin32(combos.totp); tp = '&totp_mods=' + t.mods + '&totp_vk=' + t.vk; } @@ -215,9 +216,18 @@ const Bridge = (() => { '&pwd_mods=' + p.mods + '&pwd_vk=' + p.vk + qs + ne + tp); }, - // Called by Delphi after a setAutofillHotkeys request, with true if - // BOTH combos registered successfully, false otherwise (clash with - // another app holding a global hotkey). Surfaces a toast. + // Release ALL five global hotkeys while the Settings capture is armed. + // A RegisterHotKey combo never reaches the WebView — Windows delivers + // it to the owning window — so a combo we hold can't be captured, and + // pressing it would FIRE that hotkey mid-capture. vk=0 unregisters a + // slot without re-registering it (and is excluded from the failure + // report). autofillPushHotkeys() restores everything afterwards. + suspendHotkeys() { + if (!active) return; + cmd('cmd://autofill/hotkeys?enabled=0' + + '&qs_mods=0&qs_vk=0&ne_mods=0&ne_vk=0'); + }, + // `failed` = comma-separated SLOT IDS Windows refused (another app // already owns them); empty string = all registered. A clashing hotkey // is otherwise indistinguishable from a broken feature — it silently @@ -7707,6 +7717,10 @@ async function init() { btn.classList.add('is-capturing'); const original = btn.textContent; btn.textContent = 'Press combo… (Esc to cancel)'; + // Free our own combos so they reach this listener instead of + // firing their hotkey. Restored by finish() / the success path. + hotkeyPushSilent = true; + Bridge.suspendHotkeys(); // A combo already owned by another app via RegisterHotKey is // swallowed by Windows — it is delivered to that app, never to us, @@ -7725,7 +7739,12 @@ async function init() { btn.dataset.capturing = ''; btn.classList.remove('is-capturing'); document.removeEventListener('keydown', onKey, true); - if (restore) btn.textContent = original; + if (restore) { + btn.textContent = original; + // Cancelled / timed out: nothing changed, so re-register the + // combos we suspended — quietly, it's not a user action. + autofillPushHotkeys(true); + } } function onKey(e) {