[Bug] Keybindings recorder silently drops Shift for digit/punctuation combos (⌘⇧7 records as Cmd+7)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 61.6k
- Forks
- 4.6k
- Avg merge
- 23h 49m
- Merged PRs (30d)
- 89
Description
Description
In Preferences → Key Bindings, recording a shortcut that combines Shift with a digit or punctuation key silently loses the Shift modifier: pressing ⌘⇧7 shows — and saves — Cmd+7. The stored binding differs from what the user physically pressed, with no feedback. Letter keys are unaffected (⌘⇧B records Cmd+Shift+B correctly).
Root cause (code-level)
The key-input dialog (prefComponents/keybindings/key-input-dialog.vue) delegates recording to getAcceleratorFromKeyboardEvent from @hfelix/electron-localshortcut@4.0.1. Its atom-keymap port only keeps shift as a modifier when the key is a non-character key (F-keys, arrows, …) or an uppercase Latin letter:
// @hfelix/electron-localshortcut src/atom-keymap/helpers.js
if (key === 'shift' || (shiftKey && (isNonCharacterKey || (isLatinCharacter(key) && isUpperCaseCharacter(key))))) {
keyInputEvent.shift = true
}
This follows Atom's keystroke philosophy: for shifted digits/punctuation, the shifted character is supposed to be recorded instead (Shift+7 → & on a US layout). But on macOS with ⌘ held, KeyboardEvent.key reports the base character (7), so neither the Shift modifier nor the shifted character survives — the recorded accelerator collapses to plain Cmd+7.
Steps to Reproduce
- Open Preferences → Key Bindings.
- Rebind any command (e.g. Bold) and press ⌘⇧7.
- The dialog shows
Cmd+7; saving registersCmd+7. - Afterwards ⌘7 triggers the command and ⌘⇧7 does not.
Expected Behavior
Either record CmdOrCtrl+Shift+7 (a combination Electron accelerators support — the menu would render it as ⇧⌘7), or visibly reject the keystroke — anything but silently saving a different combination than the one pressed.
Actual Behavior
Cmd+7 is saved without any indication that Shift was dropped.
Operating System
Found on macOS (develop, 0.20.0-dev). The shift-recording rule itself is platform-independent, but the exact outcome may vary per OS/layout because it depends on what KeyboardEvent.key reports under a held primary modifier.
Notes
- Found while hand-verifying #4862 (the #4687 fix); this bug is unrelated to that change and reproduces on
develop. - A possible marktext-side fix that avoids touching the library: post-process the recorded accelerator in the key-input dialog — when
event.shiftKeywas held, the accelerator contains noShift, and the recorded key equals the layout's unshifted base character forevent.code(the native-keymap layout info is already available to the configurator), appendShift. I'm happy to attempt this as a PR if that direction sounds right — or an upstream fix in@hfelix/electron-localshortcut, whichever you prefer.
Reproducibility
- I can reliably reproduce this issue
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in prefComponents/keybindings/key-input-dialog.vue and trace its use of getAcceleratorFromKeyboardEvent from @hfelix/electron-localshortcut, especially src/atom-keymap/helpers.js. Reproduce the macOS Cmd+Shift+7 case and compare the recorded accelerator with the pressed keys. Done means Shift is preserved for digit and punctuation combinations, or the dialog visibly rejects unsupported input instead of saving a different binding.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- electron, typescript
- Domain
- desktop, frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 64/100