Skip to content

ImGui key names aren't canonicalized: LeftCtrl+Key1 shows as Ctrl+KEY1 and ModCtrl+S as MODCTRL+S, so neither equals Ctrl+1 / Ctrl+S #224

Open

Description

@matt-edmondson

What's wrong

The comment above the modifier switch in Note.CanonicalizeKey (Keybinding/Models/MusicalTypes.cs, ~L66–120) says it accepts ImGui names. It only covers ImGui's left/right modifier keys (LeftCtrl, LeftSuper, …). Hexa.NET.ImGui, which ktsu's ImGui stack uses, spells two other groups of keys differently. Neither group is folded.

  • Main-row digits are ImGuiKey.Key0 … Key9.
  • Modifier flags used with ImGui's chord API (IsKeyChordPressed(ImGuiKey.ModCtrl | ImGuiKey.S)) are ModCtrl, ModShift, ModAlt and ModSuper.

These names were confirmed by reflecting over ImGuiKey in Hexa.NET.ImGui 2.2.9.

Repro, using a console app that references Keybinding.csproj at 89f14b9:

static void Show(string a, string b) { Chord x = Chord.Parse(a), y = Chord.Parse(b); Console.WriteLine($"{a} -> {x} equals {b}? {x.Equals(y)}"); }
Show("LeftCtrl+Key1", "Ctrl+1");
Show("ModCtrl+S", "Ctrl+S");
Show("ModShift+ModAlt+S", "Shift+Alt+S");
Show("ModSuper+S", "Meta+S");
LeftCtrl+Key1     -> Ctrl+KEY1          equals Ctrl+1?      False
ModCtrl+S         -> MODCTRL+S          equals Ctrl+S?      False
ModShift+ModAlt+S -> MODALT+MODSHIFT+S  equals Shift+Alt+S? False
ModSuper+S        -> MODSUPER+S         equals Meta+S?      False

GLFW has the same gap. #209 accepted GLFW's snake_case modifier names (LEFT_CONTROL, LEFT_SUPER), but GLFW's other multi-word keys are not folded:

  • LEFT_CONTROL+PAGE_UP shows as Ctrl+PAGE_UP, and Equals(Ctrl+PageUp) is false.
  • CAPS_LOCK and PRINT_SCREEN behave the same way.
  • By reading the code, PAGE_DOWN, NUM_LOCK and SCROLL_LOCK would too.

Why it matters

An ImGui host that builds chords from ImGuiKey.ToString() never matches stored bindings such as Ctrl+1 or Ctrl+S, and it shows unreadable names in the UI. This is the #205/#218 symptom again, reached through a framework the code says it supports.

Relation to #218 / PR #219

#218 covers the browser and Silk.NET spellings (KeyS, Digit1), not these. PR #219's test NoteConstructor_OtherKeyNamesStayDistinct has [DataRow("Key1")], which asserts that Key1 stays KEY1. Merging that test as written would lock this bug in. The fix here should flip that row to expect 1, while Keypad1/Numpad1 stay distinct.

Suggested fix / acceptance criteria

  • Fold KEY<digit> (exactly four characters, last one 0–9) to the digit.
    • LeftCtrl+Key1 equals Ctrl+1.
  • Map the ImGui modifier flags:
    • MODCTRL → CTRL
    • MODSHIFT → SHIFT
    • MODALT → ALT
    • MODSUPER → META
  • Map the GLFW multi-word names to the canonical names already used for other frameworks: PAGE_UP, PAGE_DOWN, CAPS_LOCK, NUM_LOCK, SCROLL_LOCK, PRINT_SCREEN.
  • Add tests for each of the inputs above.

Activity

  1. matt-edmondson commented on Nov 5, 2026

    @matt-edmondson
    ContributorAuthor

    Triage


    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

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions