diff --git a/apps/effectcraft-web/js/host.js b/apps/effectcraft-web/js/host.js index 41a4c7200..c8e91a260 100644 --- a/apps/effectcraft-web/js/host.js +++ b/apps/effectcraft-web/js/host.js @@ -10,12 +10,15 @@ // ------------------------------------------------------------------ shortcuts /// Keep Duplicate on the app canvas instead of also opening the browser's bookmarks. +/// The physical D key counts on layouts where it types no ASCII letter (e.g. Cyrillic), because +/// eframe falls back to the key code there; it does not on Dvorak, where it types E. /// eframe still receives the key; other chords and HTML inputs keep their browser behavior. export function installCanvasShortcuts(canvas) { canvas.addEventListener("keydown", (event) => { if (event.target === canvas && (event.ctrlKey || event.metaKey) && !event.shiftKey && !event.altKey && !event.isComposing - && event.key.toLowerCase() === "d") { + && (event.key.toLowerCase() === "d" + || (event.code === "KeyD" && !/^[a-z]$/i.test(event.key)))) { event.preventDefault(); } }, { capture: true }); diff --git a/apps/effectcraft-web/tests/page.mjs b/apps/effectcraft-web/tests/page.mjs index 606dbeceb..3728e59e2 100644 --- a/apps/effectcraft-web/tests/page.mjs +++ b/apps/effectcraft-web/tests/page.mjs @@ -77,7 +77,11 @@ assert.equal(key(canvas, { metaKey: true, key: "D" }), true); for (const properties of [{}, { ctrlKey: true, shiftKey: true }, { ctrlKey: true, altKey: true }, { ctrlKey: true, isComposing: true }, { ctrlKey: true, key: "r" }]) { assert.equal(key(canvas, properties), false); } -assert.equal(delivered, 7, "all keys still reach the app"); +// Non-Latin layouts: the physical D key types "в", and eframe still reads it as D. +assert.equal(key(canvas, { ctrlKey: true, key: "в", code: "KeyD" }), true); +// Dvorak: the physical D key types "e", which is not Duplicate. +assert.equal(key(canvas, { ctrlKey: true, key: "e", code: "KeyD" }), false); +assert.equal(delivered, 9, "all keys still reach the app"); assert.equal(key(input, { ctrlKey: true }), false, "an external HTML input keeps its shortcut"); // #226: one readable and one unreadable file.