fix hotkeys on dvorak (closes #298, closes #733);

apparently the convention is that hotkeys should follow the letters
according to the layout, and not remain in the qwerty position

this breaks apart the cluster of media controls (uiojkl),
but that's the intended and expected behavior so it should be fine
This commit is contained in:
ed 2025-09-03 19:33:48 +00:00
parent 09e3018bf9
commit e798a9a53a
6 changed files with 128 additions and 98 deletions

View file

@ -101,10 +101,10 @@
function our_hotkey_handler(e) { function our_hotkey_handler(e) {
// bail if either ALT, CTRL, or SHIFT is pressed // bail if either ALT, CTRL, or SHIFT is pressed
if (e.altKey || e.shiftKey || e.isComposing || ctrl(e)) if (anymod(e))
return main_hotkey_handler(e); // let copyparty handle this keystroke return main_hotkey_handler(e); // let copyparty handle this keystroke
var key_name = (e.code || e.key) + '', var keycode = (e.key || e.code) + '',
ae = document.activeElement, ae = document.activeElement,
aet = ae && ae != document.body ? ae.nodeName.toLowerCase() : ''; aet = ae && ae != document.body ? ae.nodeName.toLowerCase() : '';
@ -114,7 +114,7 @@
if (aet && !/^(a|button|tr|td|div|pre)$/.test(aet)) if (aet && !/^(a|button|tr|td|div|pre)$/.test(aet))
return main_hotkey_handler(e); // let copyparty handle this keystroke return main_hotkey_handler(e); // let copyparty handle this keystroke
if (key_name == 'KeyW') { if (keycode == 'w' || keycode == 'KeyW') {
// okay, this one's for us... do the thing // okay, this one's for us... do the thing
action_to_perform(); action_to_perform();
return ev(e); return ev(e);

View file

@ -278,23 +278,30 @@ window.baguetteBox = (function () {
if (modal.busy) if (modal.busy)
return; return;
if (e.key == '?')
return halp();
if (anymod(e, true)) if (anymod(e, true))
return; return;
var k = (e.code || e.key) + '', v = vid(), pos = -1; var k = (e.key || e.code) + '', v = vid();
if (k == "BracketLeft") if (k.startsWith('Key'))
k = k.slice(3);
else if (k.startsWith('Digit'))
k = k.slice(5);
var kl = k.toLowerCase();
if (k == '?')
return halp();
if (k == "[" || k == "BracketLeft")
setloop(1); setloop(1);
else if (k == "BracketRight") else if (k == "]" || k == "BracketRight")
setloop(2); setloop(2);
else if (e.shiftKey && k != "KeyR" && k != "R") else if (e.shiftKey && kl != "r")
return; return;
else if (k == "ArrowLeft" || k == "KeyJ" || k == "Left" || k == "j") else if (k == "ArrowLeft" || k == "Left" || kl == "j")
showPreviousImage(); showPreviousImage();
else if (k == "ArrowRight" || k == "KeyL" || k == "Right" || k == "l") else if (k == "ArrowRight" || k == "Right" || kl == "l")
showNextImage(); showNextImage();
else if (k == "Escape" || k == "Esc") else if (k == "Escape" || k == "Esc")
hideOverlay(); hideOverlay();
@ -302,33 +309,33 @@ window.baguetteBox = (function () {
showFirstImage(e); showFirstImage(e);
else if (k == "End") else if (k == "End")
showLastImage(e); showLastImage(e);
else if (k == "Space" || k == "KeyP" || k == "KeyK") else if (k == "Space" || k == "Spacebar" || kl == " " || kl == "p" || kl == "k")
playpause(); playpause();
else if (k == "KeyU" || k == "KeyO") else if (kl == "u" || kl == "o")
relseek(k == "KeyU" ? -10 : 10); relseek(kl == "u" ? -10 : 10);
else if (k.indexOf('Digit') === 0 && v) else if (v && /^[0-9]$/.test(k))
v.currentTime = v.duration * parseInt(k.slice(-1)) * 0.1; v.currentTime = v.duration * parseInt(k) * 0.1;
else if (k == "KeyM" && v) { else if (kl == "m" && v) {
v.muted = vmute = !vmute; v.muted = vmute = !vmute;
mp_ctl(); mp_ctl();
} }
else if (k == "KeyV" && v) { else if (kl == "v" && v) {
vloop = !vloop; vloop = !vloop;
vnext = vnext && !vloop; vnext = vnext && !vloop;
setVmode(); setVmode();
} }
else if (k == "KeyC" && v) { else if (kl == "c" && v) {
vnext = !vnext; vnext = !vnext;
vloop = vloop && !vnext; vloop = vloop && !vnext;
setVmode(); setVmode();
} }
else if (k == "KeyF") else if (kl == "f")
tglfull(); tglfull();
else if (k == "KeyS" || k == "s") else if (kl == "s")
tglsel(); tglsel();
else if (k == "KeyR" || k == "r" || k == "R") else if (kl == "r")
rotn(e.shiftKey ? -1 : 1); rotn(e.shiftKey ? -1 : 1);
else if (k == "KeyY") else if (kl == "y")
dlpic(); dlpic();
} }
@ -450,10 +457,11 @@ window.baguetteBox = (function () {
if (anymod(e)) if (anymod(e))
return; return;
var k = e.code + ''; var k = (e.key || e.code) + '';
if (k == "Space") if (k == "Space" || k == "Spacebar" || k == " ") {
ev(e); return ev(e);
}
} }
var passiveSupp = false; var passiveSupp = false;

View file

@ -11787,6 +11787,7 @@ var ACtx = !IPHONE && (window.AudioContext || window.webkitAudioContext),
hash0 = location.hash, hash0 = location.hash,
sloc0 = '' + location, sloc0 = '' + location,
noih = /[?&]v\b/.exec(sloc0), noih = /[?&]v\b/.exec(sloc0),
dbg_kbd = /[?&]dbgkbd\b/.exec(sloc0),
abrt_key = "", abrt_key = "",
rtt = null, rtt = null,
ldks = [], ldks = [],
@ -14528,7 +14529,7 @@ var fileman = (function () {
exm.onkeydown = exh.onkeydown = exd.onkeydown = exm.onkeydown = exh.onkeydown = exd.onkeydown =
sh_k.onkeydown = sh_pw.onkeydown = function (e) { sh_k.onkeydown = sh_pw.onkeydown = function (e) {
var kc = (e.code || e.key) + ''; var kc = (e.key || e.code) + '';
if (kc.endsWith('Enter')) if (kc.endsWith('Enter'))
sh_apply.click(); sh_apply.click();
}; };
@ -14737,7 +14738,7 @@ var fileman = (function () {
(function (a) { (function (a) {
f[a].inew.onkeydown = function (e) { f[a].inew.onkeydown = function (e) {
rn_ok(a, true); rn_ok(a, true);
var kc = (e.code || e.key) + ''; var kc = (e.key || e.code) + '';
if (kc.endsWith('Enter')) if (kc.endsWith('Enter'))
return rn_apply(); return rn_apply();
}; };
@ -14835,7 +14836,7 @@ var fileman = (function () {
spresets(); spresets();
ire.onkeydown = ifmt.onkeydown = function (e) { ire.onkeydown = ifmt.onkeydown = function (e) {
var k = (e.code || e.key) + ''; var k = (e.key || e.code) + '';
if (k == 'Escape' || k == 'Esc') if (k == 'Escape' || k == 'Esc')
return rn_cancel(); return rn_cancel();
@ -15307,7 +15308,7 @@ var fileman = (function () {
(function (a) { (function (a) {
var inew = ebi('rn_new_' + a); var inew = ebi('rn_new_' + a);
inew.onkeydown = function (e) { inew.onkeydown = function (e) {
if (((e.code || e.key) + '').endsWith('Enter')) if (((e.key || e.code) + '').endsWith('Enter'))
return rn_apply(); return rn_apply();
}; };
inew.oninput = function (e) { inew.oninput = function (e) {
@ -16493,10 +16494,20 @@ var ahotkeys = function (e) {
if (QS('#bbox-overlay.visible') || modal.busy) if (QS('#bbox-overlay.visible') || modal.busy)
return; return;
var k = (e.code || e.key) + '', pos = -1, n, var k = (e.key || e.code) + '', pos = -1, n,
ae = document.activeElement, ae = document.activeElement,
aet = ae && ae != document.body ? ae.nodeName.toLowerCase() : ''; aet = ae && ae != document.body ? ae.nodeName.toLowerCase() : '';
if (k.startsWith('Key'))
k = k.slice(3);
else if (k.startsWith('Digit'))
k = k.slice(5);
var kl = k.toLowerCase();
if (dbg_kbd)
console.log('KBD', k, kl, e.key, e.code, e.keyCode, e.which);
if (k == 'Escape' || k == 'Esc') { if (k == 'Escape' || k == 'Esc') {
ae && ae.blur(); ae && ae.blur();
tt.hide(); tt.hide();
@ -16544,7 +16555,7 @@ var ahotkeys = function (e) {
fselfunw(e, ae, d, rem); fselfunw(e, ae, d, rem);
return ev(e); return ev(e);
} }
if (k == 'Space' || k == 'Spacebar') { if (k == 'Space' || k == 'Spacebar' || k == ' ') {
clmod(ae, 'sel', 't'); clmod(ae, 'sel', 't');
msel.origin_tr(ae); msel.origin_tr(ae);
msel.selui(); msel.selui();
@ -16552,7 +16563,7 @@ var ahotkeys = function (e) {
} }
} }
if (in_ftab || !aet || (ae && ae.closest('#ggrid'))) { if (in_ftab || !aet || (ae && ae.closest('#ggrid'))) {
if ((k == 'KeyA' || k == 'a') && ctrl(e)) { if ((kl == 'a') && ctrl(e)) {
var ntot = treectl.lsc.files.length + treectl.lsc.dirs.length, var ntot = treectl.lsc.files.length + treectl.lsc.dirs.length,
sel = msel.getsel(), sel = msel.getsel(),
all = msel.getall(); all = msel.getall();
@ -16568,7 +16579,7 @@ var ahotkeys = function (e) {
} }
if (ae && ae.closest('pre')) { if (ae && ae.closest('pre')) {
if ((k == 'KeyA' || k == 'a') && ctrl(e)) { if ((kl == 'a') && ctrl(e)) {
var sel = document.getSelection(), var sel = document.getSelection(),
ran = document.createRange(); ran = document.createRange();
@ -16585,107 +16596,105 @@ var ahotkeys = function (e) {
if (aet && aet != 'a' && aet != 'tr' && aet != 'td' && aet != 'div' && aet != 'pre') if (aet && aet != 'a' && aet != 'tr' && aet != 'td' && aet != 'div' && aet != 'pre')
return; return;
if (e.key == '?') if (k == '?')
return hkhelp(); return hkhelp();
if (!e.shiftKey && ctrl(e)) { if (!e.shiftKey && ctrl(e)) {
var sel = window.getSelection && window.getSelection() || {}; var sel = window.getSelection && window.getSelection() || {};
sel = sel && !sel.isCollapsed && sel.direction != 'none'; sel = sel && !sel.isCollapsed && sel.direction != 'none';
if (k == 'KeyX' || k == 'x') if (kl == 'x')
return fileman.cut(e); return fileman.cut(e);
if ((k == 'KeyC' || k == 'c') && !sel) if (kl == 'c' && !sel)
return fileman.cpy(e); return fileman.cpy(e);
if (k == 'KeyV' || k == 'v') if (kl == 'v')
return fileman.d_paste(e); return fileman.d_paste(e);
if (k == 'KeyK' || k == 'k') if (kl == 'k')
return fileman.delete(e); return fileman.delete(e);
return; return;
} }
if (e.shiftKey && k != 'KeyA' && k != 'KeyD' && k != 'A' && k != 'D') if (e.shiftKey && kl != 'a' && kl != 'd')
return; return;
if (k.indexOf('Digit') === 0) if (/^[0-9]$/.test(k))
pos = parseInt(k.slice(-1)) * 0.1; pos = parseInt(k) * 0.1;
if (pos !== -1) if (pos !== -1)
return seek_au_mul(pos) || true; return seek_au_mul(pos) || true;
if (k == 'KeyJ' || k == 'j') if (kl == 'j')
return prev_song() || true; return prev_song() || true;
if (k == 'KeyL' || k == 'l') if (kl == 'l')
return next_song() || true; return next_song() || true;
if (k == 'KeyP' || k == 'p') if (kl == 'p')
return playpause() || true; return playpause() || true;
n = (k == 'KeyU' || k == 'u') ? -10 : n = kl == 'u' ? -10 : kl == 'o' ? 10 : 0;
(k == 'KeyO' || k == 'o') ? 10 : 0;
if (n !== 0) if (n !== 0)
return seek_au_rel(n) || true; return seek_au_rel(n) || true;
if (k == 'KeyY') if (kl == 'y')
return msel.getsel().length ? ebi('seldl').click() : return msel.getsel().length ? ebi('seldl').click() :
showfile.active() ? ebi('dldoc').click() : showfile.active() ? ebi('dldoc').click() :
dl_song(); dl_song();
n = (k == 'KeyI' || k == 'i') ? -1 : n = kl == 'i' ? -1 : kl == 'k' ? 1 : 0;
(k == 'KeyK' || k == 'k') ? 1 : 0;
if (n !== 0) if (n !== 0)
return tree_neigh(n, 1); return tree_neigh(n, 1);
if (k == 'KeyM' || k == 'm') if (kl == 'm')
return tree_up(); return tree_up();
if (k == 'KeyB' || k == 'b') if (kl == 'b')
return treectl.hidden ? treectl.entree() : treectl.detree(); return treectl.hidden ? treectl.entree() : treectl.detree();
if (k == 'KeyG' || k == 'g') if (kl == 'g')
return ebi('griden').click(); return ebi('griden').click();
if (k == 'KeyT' || k == 't') if (kl == 't')
return ebi('thumbs').click(); return ebi('thumbs').click();
if (k == 'KeyV' || k == 'v') if (kl == 'v')
return ebi('filetree').click(); return ebi('filetree').click();
if (k == 'F2') if (k == 'F2')
return fileman.rename(); return fileman.rename();
if (!treectl.hidden && (!e.shiftKey || !thegrid.en)) { if (!treectl.hidden && (!e.shiftKey || !thegrid.en)) {
if (k == 'KeyA' || k == 'a') if (kl == 'a')
return QS('#twig').click(); return QS('#twig').click();
if (k == 'KeyD' || k == 'd') if (kl == 'd')
return QS('#twobytwo').click(); return QS('#twobytwo').click();
} }
if (showfile.active()) { if (showfile.active()) {
if (k == 'KeyS' || k == 's') if (kl == 's')
showfile.tglsel(); showfile.tglsel();
if ((k == 'KeyE' || k == 'e') && ebi('editdoc').style.display != 'none') if (kl == 'e' && ebi('editdoc').style.display != 'none')
ebi('editdoc').click(); ebi('editdoc').click();
} }
if (mp && mp.au && !mp.au.paused) { if (mp && mp.au && !mp.au.paused) {
if (k == 'KeyS') if (kl == 's')
return sel_song(); return sel_song();
} }
if (thegrid.en) { if (thegrid.en) {
if (k == 'KeyS' || k == 's') if (kl == 's')
return ebi('gridsel').click(); return ebi('gridsel').click();
if (k == 'KeyA' || k == 'a') if (kl == 'a')
return QSA('#ghead a[z]')[0].click(); return QSA('#ghead a[z]')[0].click();
if (k == 'KeyD' || k == 'd') if (kl == 'd')
return QSA('#ghead a[z]')[1].click(); return QSA('#ghead a[z]')[1].click();
} }
}; };

View file

@ -1,6 +1,10 @@
"use strict"; "use strict";
var sloc0 = '' + location,
dbg_kbd = /[?&]dbgkbd\b/.exec(sloc0);
// server state // server state
var server_md = dom_src.value; var server_md = dom_src.value;
@ -936,23 +940,30 @@ var set_lno = (function () {
// hotkeys / toolbar // hotkeys / toolbar
(function () { (function () {
var keydown = function (ev) { var keydown = function (e) {
if (!ev && window.event) { if (!e && window.event) {
ev = window.event; e = window.event;
if (dev_fbw == 1) { if (dev_fbw == 1) {
toast.warn(10, 'hello from fallback code ;_;\ncheck console trace'); toast.warn(10, 'hello from fallback code ;_;\ncheck console trace');
console.error('using window.event'); console.error('using window.event');
} }
} }
var kc = ev.code || ev.keyCode || ev.which, var k = (e.key || e.code) + '',
editing = document.activeElement == dom_src; editing = document.activeElement == dom_src;
//console.log(ev.key, ev.code, ev.keyCode, ev.which); if (k.startsWith('Key'))
if (ctrl(ev) && (ev.code == "KeyS" || kc == 83)) { k = k.slice(3);
var kl = k.toLowerCase();
if (dbg_kbd)
console.log('KBD', k, kl, e.key, e.code, e.keyCode, e.which);
if (ctrl(e) && kl == "s") {
save(); save();
return false; return false;
} }
if (ev.code == "Escape" || kc == 27) { if (k == "Escape" || k == "Esc") {
var d = ebi('helpclose'); var d = ebi('helpclose');
if (d) if (d)
d.click(); d.click();
@ -960,46 +971,44 @@ var set_lno = (function () {
if (editing) if (editing)
set_lno(); set_lno();
if (ctrl(ev)) { if (ctrl(e)) {
if (ev.code == "KeyE") { if (kl == "e") {
dom_nsbs.click(); dom_nsbs.click();
return false; return false;
} }
if (!editing) if (!editing)
return true; return true;
if (ev.code == "KeyH" || kc == 72) { if (kl == "h") {
md_header(ev.shiftKey); md_header(e.shiftKey);
return false; return false;
} }
if (ev.code == "KeyZ" || kc == 90) { if (kl == "z") {
if (ev.shiftKey) if (e.shiftKey)
action_stack.redo(); action_stack.redo();
else else
action_stack.undo(); action_stack.undo();
return false; return false;
} }
if (ev.code == "KeyY" || kc == 89) { if (kl == "y") {
action_stack.redo(); action_stack.redo();
return false; return false;
} }
if (ev.code == "KeyK") { if (kl == "k") {
fmt_table(); fmt_table();
return false; return false;
} }
if (ev.code == "KeyU") { if (kl == "u") {
iter_uni(); iter_uni();
return false; return false;
} }
var up = ev.code == "ArrowUp" || kc == 38; if (k == "ArrowUp" || k == "ArrowDown") {
var dn = ev.code == "ArrowDown" || kc == 40; md_p_jump(k == "ArrowDown");
if (up || dn) {
md_p_jump(dn);
return false; return false;
} }
if (ev.code == "KeyX" || ev.code == "KeyC") { if (kl == "x" || kl == "c") {
md_cut(ev.code == "KeyX"); md_cut(kl == "x");
return true; //sic return true; //sic
} }
} }
@ -1007,18 +1016,18 @@ var set_lno = (function () {
if (!editing) if (!editing)
return true; return true;
if (ev.code == "Tab" || kc == 9) { if (k == "Tab") {
md_indent(ev.shiftKey); md_indent(e.shiftKey);
return false; return false;
} }
if (ev.code == "Home" || kc == 36) { if (k == "Home") {
md_home(ev.shiftKey); md_home(e.shiftKey);
return false; return false;
} }
if (!ev.shiftKey && ((ev.code + '').endsWith("Enter") || kc == 13)) { if (!e.shiftKey && k.endsWith("Enter")) {
return md_newline(); return md_newline();
} }
if (!ev.shiftKey && kc == 8) { if (!e.shiftKey && k == "Backspace") {
return md_backspace(); return md_backspace();
} }
} }

View file

@ -3037,10 +3037,12 @@ function up2k_init(subtle) {
if (anymod(e)) if (anymod(e))
return; return;
if (e.code == 'ArrowUp') var k = e.key || e.code;
if (k == 'ArrowUp')
bumpthread(1); bumpthread(1);
if (e.code == 'ArrowDown') if (k == 'ArrowDown')
bumpthread(-1); bumpthread(-1);
} }
@ -3103,7 +3105,8 @@ function up2k_init(subtle) {
ebi('u2szg').addEventListener('blur', read_u2sz); ebi('u2szg').addEventListener('blur', read_u2sz);
ebi('u2szg').onkeydown = function (e) { ebi('u2szg').onkeydown = function (e) {
if (anymod(e)) return; if (anymod(e)) return;
var n = e.code == 'ArrowUp' ? 1 : e.code == 'ArrowDown' ? -1 : 0; var k = e.key || e.code,
n = k == 'ArrowUp' ? 1 : k == 'ArrowDown' ? -1 : 0;
if (!n) return; if (!n) return;
this.value = parseInt(this.value) + n; this.value = parseInt(this.value) + n;
read_u2sz(); read_u2sz();
@ -3180,7 +3183,8 @@ function up2k_init(subtle) {
function kd_life(e) { function kd_life(e) {
var el = e.target, var el = e.target,
d = e.code == 'ArrowUp' ? 1 : e.code == 'ArrowDown' ? -1 : 0; k = e.key || e.code,
d = k == 'ArrowUp' ? 1 : k == 'ArrowDown' ? -1 : 0;
if (anymod(e) || !d) if (anymod(e) || !d)
return; return;

View file

@ -1824,12 +1824,12 @@ var modal = (function () {
}; };
var onkey = function (e) { var onkey = function (e) {
var k = (e.code || e.key) + '', var k = (e.key || e.code) + '',
eok = ebi('modal-ok'), eok = ebi('modal-ok'),
eng = ebi('modal-ng'), eng = ebi('modal-ng'),
ae = document.activeElement; ae = document.activeElement;
if (k == 'Space' && ae && (ae === eok || ae === eng)) if ((k == 'Space' || k == 'Spacebar' || k == ' ') && ae && (ae === eok || ae === eng))
k = 'Enter'; k = 'Enter';
if (k.endsWith('Enter')) { if (k.endsWith('Enter')) {