Skip to content

Hardcoded keybinds in onKeyDown bypass window.registerShortcut #10

Closed
4 of 4 issues completed
Closed

Description

@cchacs

Problem

screen.js's onKeyDown handler (around line 2122) hardcodes keyboard shortcuts (Space, Delete, Backspace, Escape, G, F, K) directly as a document-level key listener, rather than registering them through the core-provided window.registerShortcut() API.

Core's shortcut system (documented in slopsmith's CLAUDE.md under "Keyboard Shortcuts") exists specifically so that:

  • All shortcuts appear in the global ? help panel
  • Shortcuts can be scoped (plugin-{id}) and conditionally active
  • Users have one place to discover every available keybind across the whole app

Because the editor's shortcuts bypass this system entirely, they're invisible to users unless they read the source — despite the Arrangement Editor being arguably the most shortcut-dense screen in the entire plugin ecosystem.

Ask

Migrate the hardcoded key handling in onKeyDown to window.registerShortcut() calls, scoped to plugin-editor (or player/global as appropriate per key), so these shortcuts surface in the ? help panel like every other plugin's shortcuts are expected to.


Migrated from Maestro-Ltd/slopsmith-plugin-editor#21.

Activity

  1. added theissue type on Aug 3, 2026
  2. changed the issue type fromtoon Aug 3, 2026
  3. added and removed on Aug 3, 2026
  4. self-assigned this
    on Aug 4, 2026
  5. cchacs commented on Sep 10, 2026

    @cchacs
    CollaboratorAuthor

    Looked at doing this migration. Flagging a scoping concern before anyone sinks time into it: onKeyDown in src/input.js (~1600-2900) isn't a flat list of independent key bindings — it's a stateful dispatcher with sequenced, mutually-exclusive gates (tab-preview modal, user-guide modal, context-menu Escape ownership, tool-palette open state, tempo-map/drum-edit/parts-view mode checks, an EOF-profile-aware key map, a Select-All policy that has to run before the recording/parts-view read-only guards, etc.), where order between gates is load-bearing, not just per-key logic.

    window.registerShortcut() is built for the "each shortcut is its own independent handler + optional condition() guard" shape (see core's Keyboard Shortcuts docs) — it has no primitive for "this whole block of keys is owned by whichever modal/mode is currently active, checked in a specific priority order." Force-fitting that here would mean either (a) one registerShortcut() call per key with a condition() re-deriving the same modal/mode state onKeyDown already computes once up front — real duplication risk — or (b) keeping the dispatcher and registering a single catch-all shortcut that just calls into it, which satisfies the letter of "use registerShortcut" but not the actual goal (each shortcut discoverable individually in the ? help panel).

    Given the size (a ~3000-line file, arguably the most shortcut-dense screen in the plugin ecosystem, as the issue notes) and how much of the correctness here rides on gate ordering, I don't think this is a safe "Effort: Low" change to make speculatively without a design decision on which of those two shapes (or a third: extend registerShortcut with priority-group/modal-ownership semantics core-side) is wanted. Left it alone rather than risk a regression in the editor's most complex screen. Happy to take a swing at it if someone confirms the intended shape.


    _Generated by Claude Code


    Generated by Claude Code

  6. deleted a comment from pullfrog on Oct 1, 2026
  7. cchacs commented on Oct 2, 2026

    @cchacs
    CollaboratorAuthor

    Split into sub-issues (proposed; adjust freely). The "Keybinds N/4" titles map to issue numbers as shown:

    Order Sub-issue Depends on
    1 #37 1/4 audit the hardcoded keys and decide each key's scope none
    2 #38 2/4 migrate Delete, Backspace, G, F, K #37
    2 #39 3/4 migrate Space and Escape without clobbering host built-ins (riskier) #37
    3 #40 4/4 remove the document-level listener; verify the ? help panel #38, #39

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions