marktext / marktext/marktext

[Bug] Keybindings recorder silently drops Shift for digit/punctuation combos (⌘⇧7 records as Cmd+7)

Open
#4,863 0 comments 0 reactions 0 assignees View on GitHub

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
  1. Open Preferences → Key Bindings.
  2. Rebind any command (e.g. Bold) and press ⌘⇧7.
  3. The dialog shows Cmd+7; saving registers Cmd+7.
  4. 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.shiftKey was held, the accelerator contains no Shift, and the recorded key equals the layout's unshifted base character for event.code (the native-keymap layout info is already available to the configurator), append Shift. 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.