v4 letter-key dispatch breaks Dvorak/Colemak layouts (no opt-out)
Summary
In v4, letter shortcuts no longer fire for users on Latin alt-layouts (Dvorak, Colemak, Workman, …). The new getLayoutIndependentKeyCode path in PR #520 dispatches letter shortcuts based on event.code (physical key position) instead of event.keyCode. That makes Cyrillic/Greek users happy, but for Latin alt-layouts the physical position no longer corresponds to the character the user typed — so a Dvorak user pressing i triggers nothing (Dvorak's i is on KeyC), while pressing the QWERTY-position i key (which on Dvorak produces the character c) fires the i shortcut.
There's no flag, config option, or exported helper to opt out of getLayoutIndependentKeyCode, so applications can't preserve the v3 behavior for users who need it.
Versions
- Affected:
4.0.0and later (introduced by #520) - Last working:
3.13.x
Reproduction
import hotkeys from 'hotkeys-js'
hotkeys('i', () => console.log('fired'))
// Simulate a Dvorak keypress: the user types 'i', but the physical
// key is at the QWERTY 'c' position.
document.dispatchEvent(new KeyboardEvent('keydown', {
key: 'i',
code: 'KeyC', // <-- physical position on Dvorak
keyCode: 73,
bubbles: true,
}))
// v3.13: logs 'fired'
// v4.0+: nothingReal-world repro: switch the OS keyboard layout to Dvorak or Colemak, load any v4 app with letter shortcuts, and try to use them.
Expected behavior
Letter shortcuts should fire on the character the user typed (event.key), at least as an option. The Cyrillic-layout fix from #520 is valuable and shouldn't be reverted, but it shouldn't be the only path.
Proposed fix
Add a way to opt out of layout-independent dispatch. A few options:
- A global
hotkeys.layoutIndependent = falseflag (defaulttrueto preserve current behavior) - A per-binding option, e.g.
hotkeys('i', { layoutIndependent: false }, fn) - Honoring
event.keywhen it's a single Latin letter, falling back toevent.codeonly whenevent.keyisn't usable (covers both cases)
Option 3 is probably the most robust — for non-Latin layouts event.key is the localized character (which wouldn't match a Latin shortcut binding) so the fallback kicks in, and for Latin alt-layouts event.key is the user-typed letter which matches what the application bound. Option 1 is the simplest and unblocks affected users immediately.
Workaround
For now, downstream apps have to pin to ^3.13.x. Happy to send a PR for any of the above approaches if there's a preferred direction.
Source: jaywcjlove/hotkeys-js