refactor: table-driven keymap dispatch + auto-derived help list

Replace the global key handling scattered through the main loop with a single
KEYMAP table (key, gate, action, help text) and a DispatchKeymap() pass. The
About/Help overlay now renders its key list straight from the table, so the
on-screen shortcuts can never drift from the actual bindings.

- Order-sensitive keys (Space, Esc) stay inline where their frame ordering
  matters; they carry action==NULL and appear in the table for the help list.
- Adds the F11 fullscreen binding the sidebar button already advertised but
  that was never actually wired up.
- Fix About title em-dash rendering as '?' (font is ASCII-only); use a hyphen.

Launch render verified pixel-identical (AE=0); keys verified via injected input.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 09:05:37 -07:00
parent 53f7fa6047
commit 99c7d43637
3 changed files with 105 additions and 43 deletions
+26
View File
@@ -233,6 +233,32 @@ static inline bool UiModalOpen(void)
return app.showFileBrowser || app.showAbout;
}
// ============================================================================
// Keymap — single source of truth for global key bindings.
// The dispatcher (DispatchKeymap in spectrogram.c) runs every entry whose
// `action` is non-NULL and whose gate passes; the About/Help overlay renders
// the whole table so the on-screen key list can never drift from the bindings.
// Order-sensitive keys (Space, Esc) carry action==NULL and are handled inline
// where their frame ordering matters; they appear here for documentation only.
// ============================================================================
typedef void (*KeyActionFn)(void);
#define KEYGATE_NONE 0u
#define KEYGATE_MODAL 1u // skip while a modal overlay is open (!UiModalOpen())
#define KEYGATE_LOADED 2u // require a loaded signal
#define KEYGATE_STFT 4u // require a computed STFT
typedef struct {
int key; // raylib key code
unsigned gate; // KEYGATE_* bitmask
KeyActionFn action; // NULL = handled inline / documentation-only
const char* label; // shown in the help overlay, e.g. "O", "Home"
const char* help; // description for the help overlay
} KeyBinding;
// Returns the keymap table and its entry count (defined in spectrogram.c).
const KeyBinding* GetKeymap(int* count);
// ============================================================================
// Small math helpers (header-inline so every module can use them)
// ============================================================================