Conversation
Collaborator
|
Definitely support this, but not in its current form which is dependent on a separate PR. I would like to see it be a free standing PR. Then I would gladly approve. |
Rebinding a key means closing the editor, opening settings/shortcuts.txt in a text editor, working out the name of the action and the notation for the key, and starting the program again. The file is the only way in, and Help -> Shortcuts is read only. Options -> Key bindings... lists every action that can be bound, with its current binding in a column of its own and a filter box above. "Rebind" waits for a key press or a mouse scroll, Escape cancels the wait, and "Clear" removes the binding. "Save" writes the file, "Reload" reads it back, and "Defaults" restores the bindings the program ships with. Those defaults live in a new settings/shortcuts_default.txt, a copy of the shipped shortcuts file that saving never touches, so "Defaults" always has something to restore. Shortcuts grows the functions the dialog needs: walking the list of bindable actions, setting and clearing a binding, and reading the file again. Loading moves out of the constructor into LoadFile, which the reload and the defaults both use. A key combination can only trigger one action, so binding one that is already taken takes it away from its previous owner and says so in the message area. WgSelectList gains left aligned items and a second text drawn against the right edge, which is what puts the bindings in a column. Both are off by default, so every other list looks the way it did.
MAX-WiRED
force-pushed
the
feat/key-bindings-dialog
branch
from
September 6, 2026 17:27
1319f12 to
acfab0e
Compare
Contributor
Author
|
*Updated |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changing a key binding means closing the editor, opening
settings/shortcuts.txtin a text editor, working out both the name of theaction and the notation the parser expects, and starting the program again.
The file is the only way in -
Help → Shortcutsshows the bindings but cannotchange them.
The dialog
Edit → Key bindings… lists every action that can be bound, with its
current binding in a column against the right edge and a filter box above the
list.
binding. Escape cancels the wait.
settings/shortcuts.txt, Reload reads it back, andDefaults restores the bindings the program ships with.
Nothing is written until Save, so Reload undoes a session of changes.
A key combination can only ever trigger one action, so binding one that is
already taken removes it from its previous owner and says which action lost it
in the message area.
Where the defaults come from
"Defaults" needs a copy of the shipped bindings that saving never overwrites,
so this adds
bin/settings/shortcuts_default.txt- the currentshortcuts.txtwith a two line header.bin/is in.gitignorewhilebin/settings/shortcuts.txtis tracked, so the new file neededgit add -fto go in beside it.
Keeping two copies means they can drift. Compiling the defaults into the binary
would avoid that; a data file was chosen because it keeps the two readable side
by side and uses the parser that already exists. Happy to switch if you would
rather not carry the duplicate.
Shortcuts
The interface grows what the dialog needs: walking the list of bindable actions
(
getNumActions,getActionName,getActionCode), changing one(
setBinding,setScrollBinding,clearBindings), and the file operations(
saveToFile,reloadFromFile,restoreDefaults).Reading the file moves out of the constructor into
LoadFile(path), which theconstructor, the reload and the defaults all call.
saveToFilewrites keynames rather than the display notation, because the parser splits on
+andlooks names up - a character like
-would not survive the round trip.Saving writes next to the executable, which is where the file is read from
today. On a packaged install that directory may not be writable; the failure is
reported rather than silent. Routing both through a per-user settings directory
would be a better answer, but that is a change to where every setting lives and
does not belong here.
WgSelectList
Two additions, both off unless asked for, so every other list looks the way it
did:
alignItemsLeft()- draws item text against the left edge instead ofcentred, which is what a long list of names wants;
addItem(text, rightText)- a second text drawn against the right edge. Theright hand text is drawn first, so a long name is cut off by the ellipsis
rather than running over the binding.
Testing
Built on Windows with clang-tidy and clang-format enforced, as the build does.
Walked the whole cycle: picked an unbound action, pressed Rebind, pressed F9 -
the row shows
F9. Save wroteBACKGROUND_HIDE = F9intosettings/shortcuts.txtin the format the parser reads back. Defaults droppedit from the list, Reload brought it back from the saved file. Filtering narrows
the list as you type, and the bindings stay in their column.
Standalone now
This was one commit on top of the frame rate PR, which is where the Options
menu came from. That PR is closed, so the branch is rebased onto
betawiththat commit dropped and the entry moved to the foot of the Edit menu, next
to the editor's other settings. Nothing here depends on anything unmerged.
The rebase turned up one thing worth mentioning:
DialogIdgainedDIALOG_KEY_BINDINGSbutIdStringsinDialog.cppwas never given thematching name, so
getNamereturned a null pointer for it and pinning thedialog would have crashed on the next start. The name is in now. The array is
declared
[NUM_DIALOG_IDS], so a short initializer is filled with nulls ratherthan refused - happy to add a
static_asserton a deduced size if you want thenext person to be told at compile time instead.