Fix keyboard shortcuts broken by NumLock/CapsLock#1918
Merged
christianparpart merged 2 commits intomasterfrom Mar 24, 2026
Merged
Fix keyboard shortcuts broken by NumLock/CapsLock#1918christianparpart merged 2 commits intomasterfrom
christianparpart merged 2 commits intomasterfrom
Conversation
Strip lock modifiers (NumLock, CapsLock) before matching key bindings in config::apply(), so user-configured shortcuts work regardless of lock-key state. Promote LockModifiers constant to InputGenerator.h for shared use across binding matching and legacy input generation. Signed-off-by: Christian Parpart <christian@parpart.family>
4da2aee to
b8f8536
Compare
There was a problem hiding this comment.
Pull request overview
This PR fixes issue #1901 where keyboard shortcuts could fail to match when NumLock/CapsLock were active by stripping lock modifiers from incoming modifier masks before comparing against configured input bindings.
Changes:
- Promote
LockModifierstoInputGenerator.hfor shared reuse. - Strip
LockModifiersincontour::config::apply()before matching bindings. - Add new unit tests intended to cover lock-modifier stripping behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/vtbackend/InputGenerator.h | Exposes LockModifiers as a shared constexpr for reuse across components. |
| src/vtbackend/InputGenerator.cpp | Removes file-local LockModifiers and relies on the shared header constant. |
| src/contour/Config.h | Strips lock modifiers before comparing mapping.modifiers against event modifiers in apply(). |
| src/vtbackend/InputGenerator_test.cpp | Adds new tests around lock-modifier behavior (currently not directly exercising config::apply()). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- InputGenerator_test.cpp: Add CHECK_FALSE assertions with raw (unstripped) lock modifiers to demonstrate the bug alongside the fix (per @Copilot) Signed-off-by: Christian Parpart <christian@parpart.family>
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.
Summary
Fixes #1901.
config::apply()LockModifiersconstant fromInputGenerator.cpp(file-local) toInputGenerator.h(shared) so it can be reused across binding matching and legacy input generationRoot cause
The
Modifierenum includesNumLock=128andCapsLock=64as first-class bit flags. Key binding matching inconfig::apply()used exact equality (mapping.modifiers == modifiers), soShift|Control|NumLock≠Shift|Controland the binding would silently fail. The VT input generator already stripped lock modifiers — this fix applies the same treatment to the shortcut matching path.Risk assessment
Low risk. The change is a single bitwise AND-NOT on a
uint8_tbefore comparison. When no lock keys are active,modifiers.without(LockModifiers)is a no-op. No behavior change for users without lock keys active.Test plan
ctest --preset=clang-debug— 5/5)InputBinding.match_with_NumLock_stripped,InputBinding.match_with_CapsLock_stripped,InputBinding.match_with_NumLock_and_CapsLock_stripped,InputBinding.match_still_requires_real_modifiers