make hotkey configuration more timing tolerant

This commit is contained in:
Joseph Montanaro 2023-09-12 21:46:25 -07:00
parent e1c2618dc8
commit 1d9132de3b
2 changed files with 32 additions and 25 deletions

View File

@ -7,42 +7,49 @@
const id = Math.random().toString().slice(2);
const dispatch = createEventDispatcher();
const modifierKeys = new Set(['Alt', 'AltGraph', 'Control', 'Fn', 'FnLock', 'Meta', 'Shift', 'Super', ]);
const MODIFIERS = new Set(['Alt', 'AltGraph', 'Control', 'Fn', 'FnLock', 'Meta', 'Shift', 'Super', ]);
let listening = false;
let keysPressed = [];
function addModifiers(event) {
// add modifier key if it isn't already present
if (MODIFIERS.has(event.key) && keysPressed.indexOf(event.key) === -1) {
keysPressed.push(event.key);
}
}
function addMainKey(event) {
if (!MODIFIERS.has(event.key)) {
keysPressed.push(event.key);
value.keys = keysPressed.join('+');
dispatch('update', {value});
event.preventDefault();
event.stopPropagation();
unlisten();
}
}
function listen() {
// don't re-listen if we already are
if (listening) return;
listening = true;
window.addEventListener('keyup', setKeybind, {once: true});
window.addEventListener('keydown', addModifiers);
window.addEventListener('keyup', addMainKey);
// setTimeout avoids reacting to the click event that we are currently processing
setTimeout(() => window.addEventListener('click', cancel, {once: true}), 0);
setTimeout(() => window.addEventListener('click', unlisten), 0);
}
function setKeybind(event) {
// separate events fire for modifier keys, even when they are combined with a regular key
if (modifierKeys.has(event.key)) return;
let keys = [];
if (event.ctrlKey) keys.push('Ctrl');
if (event.altKey) keys.push('Alt');
if (event.metaKey) keys.push('Meta');
if (event.shiftKey) keys.push('Shift');
// capitalize
keys.push(event.key);
value.keys = keys.join('+');
dispatch('update', {value});
function unlisten() {
listening = false;
window.removeEventListener('click', cancel, {once: true});
event.preventDefault();
event.stopPropagation();
}
function cancel() {
listening = false;
window.removeEventListener('keyup', setKeybind, {once: true});
keysPressed = [];
window.removeEventListener('keydown', addModifiers);
window.removeEventListener('keyup', addMainKey);
window.removeEventListener('click', unlisten);
}
</script>