What's wrong
KeybindingService.ExecuteChord (Keybinding/Services/KeybindingService.cs, ~line 227) resolves the chord with FindCommandByChord (~line 280), which takes FirstOrDefault over the active profile's bindings. Only after picking that single match does it check whether the command is registered. Two things make that first match stale:
BindChord does no conflict check, so two commands can share a chord.
CommandRegistry.UnregisterCommand leaves the command's bindings in profiles.
Repro
registry.RegisterCommand(a); registry.RegisterCommand(b);
service.BindChord("a", Chord.Parse("Ctrl+S")); // true
service.BindChord("b", Chord.Parse("Ctrl+S")); // true
service.FindCommandByChord(Chord.Parse("Ctrl+S")); // "a"
registry.UnregisterCommand("a");
service.ExecuteChord(Chord.Parse("Ctrl+S")); // null
service.FindCommandByChord(Chord.Parse("Ctrl+S")); // still "a"
Expected: ExecuteChord runs b, the only registered command bound to the chord.
Reproduced against the current main build.
Why it matters
Apps that unregister commands (plugins unloading, context-specific commands) end up with shortcuts that silently do nothing, even though another live command is bound to the same keys. There is no error or log to explain why the key stopped working.
Suggested fix
- In
ExecuteChord, filter matching bindings by IsCommandRegistered before choosing one.
- Separately, and optionally: remove a command's bindings when it is unregistered, and/or report conflicts from
BindChord (reject, or expose a GetConflicts API).
Acceptance criteria
- The repro executes
b.
- A regression test covering an unregistered command sharing a chord with a registered one.
What's wrong
KeybindingService.ExecuteChord(Keybinding/Services/KeybindingService.cs, ~line 227) resolves the chord withFindCommandByChord(~line 280), which takesFirstOrDefaultover the active profile's bindings. Only after picking that single match does it check whether the command is registered. Two things make that first match stale:BindChorddoes no conflict check, so two commands can share a chord.CommandRegistry.UnregisterCommandleaves the command's bindings in profiles.Repro
Expected:
ExecuteChordrunsb, the only registered command bound to the chord.Reproduced against the current
mainbuild.Why it matters
Apps that unregister commands (plugins unloading, context-specific commands) end up with shortcuts that silently do nothing, even though another live command is bound to the same keys. There is no error or log to explain why the key stopped working.
Suggested fix
ExecuteChord, filter matching bindings byIsCommandRegisteredbefore choosing one.BindChord(reject, or expose aGetConflictsAPI).Acceptance criteria
b.