fix: keyboard shortcuts on non-English layouts (#6009)
Co-authored-by: sahilkhan09k <181699039+sahilkhan09k@users.noreply.github.com> Co-authored-by: 04cb <111667698+04cb@users.noreply.github.com> Co-authored-by: James George <25279263+jamesgeorge007@users.noreply.github.com>
This commit is contained in:
parent
8aac537c7a
commit
ce0fdeccfb
2 changed files with 50 additions and 27 deletions
|
|
@ -307,36 +307,64 @@ function generateKeybindingString(ev: KeyboardEvent): ShortcutKey | null {
|
|||
}
|
||||
|
||||
function getPressedKey(ev: KeyboardEvent): Key | null {
|
||||
// Sometimes the property code is not available on the KeyboardEvent object
|
||||
const key = (ev.key ?? "").toLowerCase()
|
||||
const code = ev.code ?? ""
|
||||
|
||||
// Check arrow keys
|
||||
// Use event.code for letters and digits so shortcuts work regardless of
|
||||
// the active keyboard layout (Cyrillic, CJK, Dvorak, etc). event.key
|
||||
// returns the character produced by the layout, event.code returns the
|
||||
// physical key position.
|
||||
//
|
||||
// TODO: Several component-level keydown handlers still use event.key
|
||||
// (spotlight, EnvInput, SchemaSearch, AI modals). Those need the
|
||||
// same migration but are lower priority since they only check
|
||||
// arrow/Enter/Escape which are layout-stable.
|
||||
|
||||
// Letter keys (KeyA–KeyZ)
|
||||
if (code.startsWith("Key") && code.length === 4) {
|
||||
return code[3].toLowerCase() as Key
|
||||
}
|
||||
|
||||
// ev.code can be empty in synthetic events or older environments. Fall back
|
||||
// to ev.key for ASCII letters so shortcuts don't silently stop working.
|
||||
// This reintroduces layout-dependence for that edge case, but that's better
|
||||
// than dropping the shortcut entirely.
|
||||
if (!code && key.length === 1 && key >= "a" && key <= "z") return key as Key
|
||||
|
||||
// Arrow keys (ArrowUp → up, etc)
|
||||
if (key.startsWith("arrow")) {
|
||||
return key.slice(5) as Key
|
||||
}
|
||||
|
||||
// Check for Tab key
|
||||
if (key === "tab") return "tab"
|
||||
|
||||
// Check for Delete key
|
||||
if (key === "delete") return "delete"
|
||||
|
||||
if (key === "backspace") return "backspace"
|
||||
|
||||
// Check letter keys
|
||||
const isLetter = key.length === 1 && key >= "a" && key <= "z"
|
||||
if (isLetter) return key as Key
|
||||
// Shift+/ produces "?" on most layouts but the shortcut is registered as "/"
|
||||
if (key === "?") return "/"
|
||||
|
||||
// Check if number keys
|
||||
const isDigit = key.length === 1 && key >= "0" && key <= "9"
|
||||
if (isDigit) return key as Key
|
||||
|
||||
// Check if slash, period or enter
|
||||
// Punctuation and special keys checked before digit codes because some
|
||||
// layouts produce these characters from physical digit keys (e.g. AZERTY
|
||||
// produces [ via AltGr+5 which has code "Digit5").
|
||||
if (key === "/" || key === "." || key === "enter") return key
|
||||
|
||||
if (key === "[" || key === "]") return key
|
||||
|
||||
// If no other cases match, this is not a valid key
|
||||
// Digit keys (Digit0–Digit9)
|
||||
if (code.startsWith("Digit") && code.length === 6) {
|
||||
return code[5] as Key
|
||||
}
|
||||
|
||||
// Numpad digits (Numpad0–Numpad9), only when NumLock is on.
|
||||
// When NumLock is off the physical keys act as navigation (Home, End, etc)
|
||||
// but event.code still returns Numpad0-Numpad9.
|
||||
if (
|
||||
code.startsWith("Numpad") &&
|
||||
code.length === 7 &&
|
||||
ev.getModifierState("NumLock")
|
||||
) {
|
||||
return code.slice(6) as Key
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -277,12 +277,7 @@ async function initApp() {
|
|||
const isCtrlOrCmd = e.ctrlKey || e.metaKey
|
||||
let shortcutEvent: string | null = null
|
||||
|
||||
if (
|
||||
isCtrlOrCmd &&
|
||||
!e.shiftKey &&
|
||||
!e.altKey &&
|
||||
e.key.toLowerCase() === "q"
|
||||
) {
|
||||
if (isCtrlOrCmd && !e.shiftKey && !e.altKey && e.code === "KeyQ") {
|
||||
// Ctrl/Cmd + Q - Quit Application
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
|
@ -292,7 +287,7 @@ async function initApp() {
|
|||
isCtrlOrCmd &&
|
||||
!e.shiftKey &&
|
||||
!e.altKey &&
|
||||
e.key.toLowerCase() === "t"
|
||||
e.code === "KeyT"
|
||||
) {
|
||||
// Ctrl/Cmd + T - New Tab
|
||||
e.preventDefault()
|
||||
|
|
@ -303,7 +298,7 @@ async function initApp() {
|
|||
isCtrlOrCmd &&
|
||||
!e.shiftKey &&
|
||||
!e.altKey &&
|
||||
e.key.toLowerCase() === "w"
|
||||
e.code === "KeyW"
|
||||
) {
|
||||
// Ctrl/Cmd + W - Close Tab
|
||||
e.preventDefault()
|
||||
|
|
@ -314,7 +309,7 @@ async function initApp() {
|
|||
isCtrlOrCmd &&
|
||||
e.shiftKey &&
|
||||
!e.altKey &&
|
||||
e.key.toLowerCase() === "t"
|
||||
e.code === "KeyT"
|
||||
) {
|
||||
// Ctrl/Cmd + Shift + T - Reopen Tab
|
||||
e.preventDefault()
|
||||
|
|
@ -347,7 +342,7 @@ async function initApp() {
|
|||
isCtrlOrCmd &&
|
||||
!e.shiftKey &&
|
||||
e.altKey &&
|
||||
(e.key === "9" || e.code === "Digit9")
|
||||
e.code === "Digit9"
|
||||
) {
|
||||
// Ctrl/Cmd + Alt + 9 - First Tab
|
||||
e.preventDefault()
|
||||
|
|
@ -358,7 +353,7 @@ async function initApp() {
|
|||
isCtrlOrCmd &&
|
||||
!e.shiftKey &&
|
||||
e.altKey &&
|
||||
(e.key === "0" || e.code === "Digit0")
|
||||
e.code === "Digit0"
|
||||
) {
|
||||
// Ctrl/Cmd + Alt + 0 - Last Tab
|
||||
e.preventDefault()
|
||||
|
|
|
|||
Loading…
Reference in a new issue