-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce vk() and sc() key chord specifiers #10666
Conversation
This comment has been minimized.
This comment has been minimized.
KeyChord(Windows.System.VirtualKeyModifiers modifiers, Int32 vkey, Int32 scanCode); | ||
KeyChord(Boolean ctrl, Boolean alt, Boolean shift, Boolean win, Int32 vkey, Int32 scanCode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't want to add a 5th constructor, so I removed 1 instead.
} | ||
|
||
// This key chord is not explicitly bound | ||
return nullptr; | ||
return _GetActionByKeyChordInternal({ modifiers, 0, keys.ScanCode() }).value_or(nullptr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll now have to run _GetActionByKeyChordInternal
twice, since the given keys
might have both a vkey as well as a scan code set, but the internal hashmaps have only key bindings loaded that contain either of the two.
I used to have a comment explaining this here, but I must've lost it at some point. I'll re-add one.
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+plus" }, | ||
{ "command": { "action": "adjustFontSize", "delta": -1 }, "keys": "ctrl+minus" }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fixes zooming for non-US keyboards.
@@ -298,7 +298,7 @@ | |||
{ "command": "commandPalette", "keys":"ctrl+shift+p" }, | |||
{ "command": "identifyWindow" }, | |||
{ "command": "openWindowRenamer" }, | |||
{ "command": "quakeMode", "keys":"win+`" }, | |||
{ "command": "quakeMode", "keys":"win+sc(41)" }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fixes quake mode for non-US keyboards.
{ | ||
if (k != nullptr) | ||
if (auto summonArgs = cmd.ActionAndArgs().Args().try_as<Settings::Model::GlobalSummonArgs>()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By casting the cmd
prematurely, we won't have to cast it again in AppHost::_GlobalHotkeyPressed
.
Additionally we won't have to hold onto the _hotkeyActions
map.
args.SummonBehavior().MoveToCurrentDesktop(summonArgs.Desktop() == Settings::Model::DesktopBehavior::ToCurrent); | ||
args.SummonBehavior().ToggleVisibility(summonArgs.ToggleVisibility()); | ||
args.SummonBehavior().DropdownDuration(summonArgs.DropdownDuration()); | ||
const auto& summonArgs = til::at(_hotkeys, hotkeyIndex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As you can see here, a lot of casting is gone without the _hotkeyActions
map.
Otherwise this code is still the same - just less indented.
(Suppressing white-space changes in GitHub makes this PR less scary.)
winrt::com_ptr<IVirtualDesktopManager> _desktopManager{ nullptr }; | ||
|
||
bool _shouldCreateWindow{ false }; | ||
bool _useNonClientArea{ false }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_useNonClientArea
wasn't initialized during construction. I moved them down so this class uses less padding.
"constexpr std::string_view $($VariableName){", | ||
($jsonData | ForEach-Object { "R`"#($_`n)#`"" }), | ||
"};" | ||
) | Out-File -FilePath $OutPath -Encoding utf8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to add support for "(
and )"
escaping (now it uses R"#(...)#"
instead), and I thought I could clean this file up a bit. 👍
09aa4f4
to
0bb6e34
Compare
// Return Value: | ||
// - <none> | ||
void IslandWindow::SetGlobalHotkeys(const std::vector<winrt::Microsoft::Terminal::Control::KeyChord>& hotkeyList) | ||
void IslandWindow::RegisterHotKey(const int index, const winrt::Microsoft::Terminal::Control::KeyChord& hotkey) noexcept |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By passing the hotkey not as a vector but rather one by one, we can get rid of the std::vector
of key chords in the AppHost.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
meh, these are all nits, but the PR is still in draft, so I'll hold off ✔️-ing until the final version
if (cmd.has_value()) | ||
const auto modifiers = keys.Modifiers(); | ||
|
||
if (auto vkey = keys.Vkey()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be tremendously dumb to oneline this as
return _GetActionByKeyChordInternal({ modifiers, keys.Vkey(), 0 }).value_or( _GetActionByKeyChordInternal({ modifiers, 0, keys.ScanCode() }).value_or(nullptr));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would certainly be nice! But it would also eagerly check both variants, before returning either, and I'm not sure if that's a good idea...
Should this be added to profiles.schema.json too? |
@KalleOlaviNiemitalo Yeah I can do that. 👍 |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Rather than the description, I meant this regular expression
|
@KalleOlaviNiemitalo Oh wow that's a rather... comprehensive regex. 😄 For now I'll just remove the backtracking from the regex and update it with the 5 new key chord types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remaining TODOs:
Add a comment to✔️ActionMap::GetActionByKeyChord
Add a unit test forI can't runvk(nnn)
/sc(nnn)
parsingLocalTests_SettingsModel
tests. 😟
The remaining implementation in this PR is "ready" from my side though.
@@ -4,13 +4,13 @@ | |||
"title": "Microsoft's Windows Terminal Settings Profile Schema", | |||
"definitions": { | |||
"KeyChordSegment": { | |||
"pattern": "^(?<modifier>(?<mod1>ctrl|alt|shift|win)(?:\\+(?<mod2>ctrl|alt|shift|win)(?<!\\k<mod1>))?(?:\\+(?<mod3>ctrl|alt|shift|win)(?<!\\k<mod1>|\\k<mod2>))?(?:\\+(?<mod4>ctrl|alt|shift|win)(?<!\\k<mod1>|\\k<mod2>|\\k<mod3>))?\\+)?(?<key>[^\\s+]|app|menu|backspace|tab|enter|esc|escape|space|pgup|pageup|pgdn|pagedown|end|home|left|up|right|down|insert|delete|(?<!shift.+)(?:numpad_?[0-9]|numpad_(?:period|decimal))|numpad_(?:multiply|plus|add|minus|subtract|divide)|f[1-9]|f1[0-9]|f2[0-4]|plus)$", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there's an actually correct regex for all the things this accepts, I won't be shocked, but I don't think it's valuable to try and optimize this more past this point IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I made it less correct than it was, because the previous regexp was really really hard to understand. 😅
// The below function was used to test from_wchars for unsafety and conformance with clang's strtoul. | ||
// The test was run as: | ||
// clang++ -fsanitize=address,undefined,fuzzer -std=c++17 file.cpp | ||
// and was run for 20min across 16 jobs in parallel. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may want to file a backlog follow-up to add this test to onefuzz after #10431 merges
std::vector<winrt::Microsoft::Terminal::Control::KeyChord> _hotkeys{}; | ||
winrt::Windows::Foundation::Collections::IMapView<winrt::Microsoft::Terminal::Control::KeyChord, winrt::Microsoft::Terminal::Settings::Model::Command> _hotkeyActions{ nullptr }; | ||
|
||
std::vector<winrt::Microsoft::Terminal::Settings::Model::GlobalSummonArgs> _hotkeys; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this does somewhat violate the design where any action could have been promoted to be "global" :/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if @zadjii-msft is okay with this ("YAGNI"), then okay
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we'll need it, at least not for a while. Methinks the event horizon for "slam arbitrary actions into the tray flyout" is decently far away.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just changed it because I found the code hard to read and I applied the YAGNI principle to it. I find it easier to understand now, as less casts/checks are necessary.
But of course I can't know how others about it. If you feel like I should revert it I'll gladly do so!
I'll wait a bit before I merge it. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course we can also convert the type of this vector to be std::vector<Command>
in the future and retain the same advantages (well I mean the advantages as I perceived them). 🙂
Hello @lhecker! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
This commit introduces an alternative to specifying key bindings as a combination of key modifiers and a character. It allows you to specify an explicit virtual key as `vk(nnn)`. Additionally this commit makes it possible to bind actions to scan codes. As scan code 41 appears to be the button below the Escape key on virtually all keyboards, we'll be able to bind the quake mode hotkey to `win+sc(41)` and have it work consistently across most if not all keyboard layouts. ## PR Checklist * [x] Closes microsoft#7539, Closes microsoft#10203 * [x] I work here * [x] Tests added/passed ## Validation Steps Performed The following was tested both on US and DE keyboard layouts: * Ctrl+, opens settings ✔️ * Win+` opens quake mode window ✔️ * Ctrl+plus/minus increase/decrease font size ✔️
`VkKeyScanW` as well as `MapVirtualKeyW` are used throughout the project, but are input method sensitive functions. Since #10666 `win+sc(41)` is used as the quake mode keybinding, which is then mapped to a virtual key in order to call `RegisterHotKey`. This mapping is highly dependent on the input method and the quake mode key binding will fail to work once the input method was changed. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist * [x] Closes #10729 * [x] I work here * [ ] Tests added/passed ## Validation Steps Performed * win+` opens quake window before & after changing keyboard layout ✔️ * keyboard layout changes while WT is minimized trigger reloaded ✔️
## Summary of the Pull Request This isn't a fix for #10875, but it is logging that help identify the root cause here. The logging may additionally be helpful for some of the other issues we're seeing elsewhere in the repo, namely #10340. @lhecker is actually working on the fix for #10875, so hopefully this test will help validate. ## References * Regressed in #10666. * logging for #8888 ## PR Checklist * [x] Closes nothing * [x] I work here * [x] Tests added, and they absolutely fail, but they're localtests, so ¯\\\_(ツ)_/¯ * [n/a] Requires documentation to be updated ## details While I was here, I noticed that `KeyBindingsTests::KeyChords` has been broken for some time now. So I fixed that too.
🎉 Handy links: |
👏 This is a huge win for key bindings in general. I wish all video games switched to scan codes instead of being layout dependent. |
vk(nnn) |
This commit introduces an alternative to specifying key bindings as a combination of key modifiers and a character. It allows you to specify an explicit virtual key as
vk(nnn)
.Additionally this commit makes it possible to bind actions to scan codes. As scan code 41 appears to be the button below the Escape key on virtually all keyboards, we'll be able to bind the quake mode hotkey to
win+sc(41)
and have it work consistently across most if not all keyboard layouts.PR Checklist
Validation Steps Performed
The following was tested both on US and DE keyboard layouts: