Skip to content

fix(settings): reserve every hardcoded menu shortcut against user rebinding - #2459

Merged
datlechin merged 1 commit into
mainfrom
fix/shortcut-reservation-completeness
Aug 26, 2026
Merged

fix(settings): reserve every hardcoded menu shortcut against user rebinding#2459
datlechin merged 1 commit into
mainfrom
fix/shortcut-reservation-completeness

Conversation

@datlechin

Copy link
Copy Markdown
Member

Two defects found while investigating #2453, both in the same class: a hand-maintained list that has to agree with something else, and nothing forcing it to.

You can silently kill Quit

reservedAppShortcuts held only Zoom In, Zoom Out and Cmd+1 through Cmd+9. Seven other combos are hardcoded by the menu builders and belong to no ShortcutAction, so the recorder had nothing to refuse them with:

Combo Command
Cmd+Q Quit TablePro
Cmd+M Minimize
Cmd+H Hide TablePro
Cmd+Option+H Hide Others
Cmd+, Settings…
Cmd+Option+T Show Toolbar
Ctrl+Cmd+F Enter Full Screen

Reproduction: Settings > Keyboard, bind Toggle Filters to Cmd+Q. All three resolver gates pass, the binding is stored, and MainMenuKeyEquivalentSync puts Cmd+Q on Show Filter Bar. Two menu items now claim it and AppKit blanks one. SystemHotkeyChecker does not catch these, because CopySymbolicHotKeys reports system-wide hotkeys, not per-app menu standards.

Ctrl+Cmd+J was missing from editorBuiltIns

editorBuiltIns is a hand-maintained mirror of the vendored fork's key-binding switch, and it had drifted: TextViewController+Lifecycle.swift:277 handles [command, control], "j" for Jump to Definition, with no matching entry. Bind an editor or global action to Ctrl+Cmd+J and the recorder accepts it, then the fork's local monitor claims the keystroke first and the binding never fires.

The guard

Both lists are hand-maintained, so a fix that only adds today's missing entries buys nothing against tomorrow's. hardcodedKeyEquivalentsAreReserved builds the real menu, subtracts every combo any ShortcutAction resolves to, and asserts the remainder is reserved. A hardcoded item added later without a reservedAppShortcuts entry now fails the build.

It carries an explicit non-vacuity assertion, which earned its place: two earlier drafts of this test passed while checking nothing. The first keyed off NSMenuItem.identifier == nil to spot hardcoded items, but AppKit synthesizes identifiers, so the filter matched zero items. The second used BoundKey.character(_:), which calls assertionFailure for any character with no key code on the active layout, and menu items carry arrow and escape key equivalents, so it crashed the whole suite. The shipped version compares canonical modifiers-character strings and never constructs a BoundKey from menu data.

Verification

Step Result
verify.sh build PASS
verify.sh test (14 menu + keyboard suites) PASS, 93 executed, 93 passed
verify.sh lint TablePro TableProTests 0 violations

Both entries are in a shipped build, so both get a CHANGELOG line.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@datlechin
datlechin merged commit 655b2cc into main Aug 26, 2026
11 of 12 checks passed
@datlechin
datlechin deleted the fix/shortcut-reservation-completeness branch August 26, 2026 13:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant