From 44f8dcdbe0868357a237cb436094828c7629838f Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 15 Apr 2021 11:52:28 -0500 Subject: [PATCH] Add support for the `win` key in keybindings (#9783) ## Summary of the Pull Request Does what it says on the can. People can now use `win` in a keybinding to indicate that the chord needs win. ## References * Done for #653 * See also #8888 ## PR Checklist * [x] Closes #3184 * [x] I work here * [ ] Tests added/passed * [ ] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments For the record, I hate this. But it's great for quake mode, so _meh_. There's shockingly more win keys claimed then you think - many more than the shortcut guide even shows. * `win+b`: Focus the tray? * `win+t`: Focus the taskbar * `win+p`: Project... * `win+c`: The powertoys color picker * `win+v`: cloud clipboard So the list of valid combos is vanishingly small. It's all about that win+~ ## Validation Steps Performed Bound ```json { "keys": [ "win+`" ], "command": "commandPalette" }, ``` and yea, it works as expected --- doc/cascadia/profiles.schema.json | 4 ++-- src/cascadia/TerminalApp/TerminalPage.cpp | 5 +++++ src/cascadia/TerminalControl/KeyChord.cpp | 9 ++++++++ src/cascadia/TerminalControl/KeyChord.h | 1 + src/cascadia/TerminalControl/KeyChord.idl | 4 +++- src/cascadia/TerminalControl/TermControl.cpp | 5 ++++- .../TerminalCore/ControlKeyStates.hpp | 21 ++++++++++++++++++- .../KeyChordSerialization.cpp | 12 ++++++++++- .../TerminalSettingsModel/KeyMapping.cpp | 4 ++++ 9 files changed, 59 insertions(+), 6 deletions(-) diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index 3db7df482eff..34e138ef62ba 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -4,9 +4,9 @@ "title": "Microsoft's Windows Terminal Settings Profile Schema", "definitions": { "KeyChordSegment": { - "pattern": "^(?(ctrl|alt|shift)(?:\\+(ctrl|alt|shift)(?[^\\s+]|app|menu|backspace|tab|enter|esc|escape|space|pgup|pageup|pgdn|pagedown|end|home|left|up|right|down|insert|delete|(?(?ctrl|alt|shift|win)(?:\\+(?ctrl|alt|shift|win)(?))?(?:\\+(?ctrl|alt|shift|win)(?|\\k))?(?:\\+(?ctrl|alt|shift|win)(?|\\k|\\k))?\\+)?(?[^\\s+]|app|menu|backspace|tab|enter|esc|escape|space|pgup|pageup|pgdn|pagedown|end|home|left|up|right|down|insert|delete|(?\", where each modifier is optional, separated by + symbols, and keyName is either one of the names listed in the table below, or any single key character. The string should be written in full lowercase.\napp, menu\tMENU key\nbackspace\tBACKSPACE key\ntab\tTAB key\nenter\tENTER key\nesc, escape\tESC key\nspace\tSPACEBAR\npgup, pageup\tPAGE UP key\npgdn, pagedown\tPAGE DOWN key\nend\tEND key\nhome\tHOME key\nleft\tLEFT ARROW key\nup\tUP ARROW key\nright\tRIGHT ARROW key\ndown\tDOWN ARROW key\ninsert\tINS key\ndelete\tDEL key\nnumpad_0-numpad_9, numpad0-numpad9\tNumeric keypad keys 0 to 9. Can't be combined with the shift modifier.\nnumpad_multiply\tNumeric keypad MULTIPLY key (*)\nnumpad_plus, numpad_add\tNumeric keypad ADD key (+)\nnumpad_minus, numpad_subtract\tNumeric keypad SUBTRACT key (-)\nnumpad_period, numpad_decimal\tNumeric keypad DECIMAL key (.). Can't be combined with the shift modifier.\nnumpad_divide\tNumeric keypad DIVIDE key (/)\nf1-f24\tF1 to F24 function keys\nplus\tADD key (+)" + "description": "The string should fit the format \"[ctrl+][alt+][shift+][win+]\", where each modifier is optional, separated by + symbols, and keyName is either one of the names listed in the table below, or any single key character. The string should be written in full lowercase.\napp, menu\tMENU key\nbackspace\tBACKSPACE key\ntab\tTAB key\nenter\tENTER key\nesc, escape\tESC key\nspace\tSPACEBAR\npgup, pageup\tPAGE UP key\npgdn, pagedown\tPAGE DOWN key\nend\tEND key\nhome\tHOME key\nleft\tLEFT ARROW key\nup\tUP ARROW key\nright\tRIGHT ARROW key\ndown\tDOWN ARROW key\ninsert\tINS key\ndelete\tDEL key\nnumpad_0-numpad_9, numpad0-numpad9\tNumeric keypad keys 0 to 9. Can't be combined with the shift modifier.\nnumpad_multiply\tNumeric keypad MULTIPLY key (*)\nnumpad_plus, numpad_add\tNumeric keypad ADD key (+)\nnumpad_minus, numpad_subtract\tNumeric keypad SUBTRACT key (-)\nnumpad_period, numpad_decimal\tNumeric keypad DECIMAL key (.). Can't be combined with the shift modifier.\nnumpad_divide\tNumeric keypad DIVIDE key (/)\nf1-f24\tF1 to F24 function keys\nplus\tADD key (+)" }, "Color": { "default": "#", diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 2ce671f309fd..554e82bf2c41 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -1360,6 +1360,11 @@ namespace winrt::TerminalApp::implementation buffer += L"Alt+"; } + if (WI_IsFlagSet(modifiers, KeyModifiers::Windows)) + { + buffer += L"Win+"; + } + return buffer; } diff --git a/src/cascadia/TerminalControl/KeyChord.cpp b/src/cascadia/TerminalControl/KeyChord.cpp index 4c068890e35f..adf24d0aa4c0 100644 --- a/src/cascadia/TerminalControl/KeyChord.cpp +++ b/src/cascadia/TerminalControl/KeyChord.cpp @@ -22,6 +22,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation { } + KeyChord::KeyChord(bool ctrl, bool alt, bool shift, bool win, int32_t vkey) noexcept : + _modifiers{ (ctrl ? Control::KeyModifiers::Ctrl : Control::KeyModifiers::None) | + (alt ? Control::KeyModifiers::Alt : Control::KeyModifiers::None) | + (shift ? Control::KeyModifiers::Shift : Control::KeyModifiers::None) | + (win ? Control::KeyModifiers::Windows : Control::KeyModifiers::None) }, + _vkey{ vkey } + { + } + KeyChord::KeyChord(Control::KeyModifiers const& modifiers, int32_t vkey) noexcept : _modifiers{ modifiers }, _vkey{ vkey } diff --git a/src/cascadia/TerminalControl/KeyChord.h b/src/cascadia/TerminalControl/KeyChord.h index 9324a8113212..2b5f0d80fb41 100644 --- a/src/cascadia/TerminalControl/KeyChord.h +++ b/src/cascadia/TerminalControl/KeyChord.h @@ -12,6 +12,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation KeyChord() noexcept; KeyChord(Control::KeyModifiers const& modifiers, int32_t vkey) noexcept; KeyChord(bool ctrl, bool alt, bool shift, int32_t vkey) noexcept; + KeyChord(bool ctrl, bool alt, bool shift, bool win, int32_t vkey) noexcept; Control::KeyModifiers Modifiers() noexcept; void Modifiers(Control::KeyModifiers const& value) noexcept; diff --git a/src/cascadia/TerminalControl/KeyChord.idl b/src/cascadia/TerminalControl/KeyChord.idl index 65107d8d9d3a..25e10bd01b5c 100644 --- a/src/cascadia/TerminalControl/KeyChord.idl +++ b/src/cascadia/TerminalControl/KeyChord.idl @@ -9,7 +9,8 @@ namespace Microsoft.Terminal.Control None = 0x0000, Alt = 0x0001, Ctrl = 0x0002, - Shift = 0x0004 + Shift = 0x0004, + Windows = 0x0008 }; [default_interface] @@ -18,6 +19,7 @@ namespace Microsoft.Terminal.Control KeyChord(); KeyChord(KeyModifiers modifiers, Int32 vkey); KeyChord(Boolean ctrl, Boolean alt, Boolean shift, Int32 vkey); + KeyChord(Boolean ctrl, Boolean alt, Boolean shift, Boolean win, Int32 vkey); KeyModifiers Modifiers; Int32 Vkey; diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index f34d7013c02e..79dab5af89b5 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1128,6 +1128,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation modifiers.IsCtrlPressed(), modifiers.IsAltPressed(), modifiers.IsShiftPressed(), + modifiers.IsWinPressed(), vkey, }); if (!success) @@ -3010,12 +3011,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation ControlKeyStates flags; }; - constexpr std::array modifiers{ { + constexpr std::array modifiers{ { { VirtualKey::RightMenu, ControlKeyStates::RightAltPressed }, { VirtualKey::LeftMenu, ControlKeyStates::LeftAltPressed }, { VirtualKey::RightControl, ControlKeyStates::RightCtrlPressed }, { VirtualKey::LeftControl, ControlKeyStates::LeftCtrlPressed }, { VirtualKey::Shift, ControlKeyStates::ShiftPressed }, + { VirtualKey::RightWindows, ControlKeyStates::RightWinPressed }, + { VirtualKey::LeftWindows, ControlKeyStates::LeftWinPressed }, } }; ControlKeyStates flags; diff --git a/src/cascadia/TerminalCore/ControlKeyStates.hpp b/src/cascadia/TerminalCore/ControlKeyStates.hpp index 16d6daa02cb8..9b88c71a3eb3 100644 --- a/src/cascadia/TerminalCore/ControlKeyStates.hpp +++ b/src/cascadia/TerminalCore/ControlKeyStates.hpp @@ -3,6 +3,14 @@ #pragma once +// All the modifiers in this file EXCEPT the win key come from +// https://docs.microsoft.com/en-us/windows/console/key-event-record-str +// +// Since we also want to be able to encode win-key info in this structure, we'll +// add those values manually here +constexpr DWORD RIGHT_WIN_PRESSED = 0x0200; +constexpr DWORD LEFT_WIN_PRESSED = 0x0400; + namespace Microsoft::Terminal::Core { class ControlKeyStates; @@ -31,6 +39,8 @@ class Microsoft::Terminal::Core::ControlKeyStates static constexpr StaticValue ScrolllockOn{ SCROLLLOCK_ON }; static constexpr StaticValue CapslockOn{ CAPSLOCK_ON }; static constexpr StaticValue EnhancedKey{ ENHANCED_KEY }; + static constexpr StaticValue RightWinPressed{ RIGHT_WIN_PRESSED }; + static constexpr StaticValue LeftWinPressed{ LEFT_WIN_PRESSED }; constexpr ControlKeyStates() noexcept : _value(0) {} @@ -58,13 +68,17 @@ class Microsoft::Terminal::Core::ControlKeyStates SHIFT_PRESSED : 0; - // Since we can't differentiate between the left & right versions of Ctrl & Alt in a VirtualKeyModifiers + // Since we can't differentiate between the left & right versions of + // Ctrl, Alt and Win in a VirtualKeyModifiers _value |= WI_IsFlagSet(m, static_cast(winrt::Windows::System::VirtualKeyModifiers::Menu)) ? LEFT_ALT_PRESSED : 0; _value |= WI_IsFlagSet(m, static_cast(winrt::Windows::System::VirtualKeyModifiers::Control)) ? LEFT_CTRL_PRESSED : 0; + _value |= WI_IsFlagSet(m, static_cast(winrt::Windows::System::VirtualKeyModifiers::Windows)) ? + LEFT_WIN_PRESSED : + 0; } #endif @@ -88,6 +102,11 @@ class Microsoft::Terminal::Core::ControlKeyStates return IsAnyFlagSet(RightCtrlPressed | LeftCtrlPressed); } + constexpr bool IsWinPressed() const noexcept + { + return IsAnyFlagSet(RightWinPressed | LeftWinPressed); + } + constexpr bool IsAltGrPressed() const noexcept { return AreAllFlagsSet(RightAltPressed | LeftCtrlPressed); diff --git a/src/cascadia/TerminalSettingsModel/KeyChordSerialization.cpp b/src/cascadia/TerminalSettingsModel/KeyChordSerialization.cpp index 8c0fd6322359..b240b8d2802c 100644 --- a/src/cascadia/TerminalSettingsModel/KeyChordSerialization.cpp +++ b/src/cascadia/TerminalSettingsModel/KeyChordSerialization.cpp @@ -11,8 +11,9 @@ using namespace winrt::Microsoft::Terminal::Settings::Model::implementation; static constexpr std::wstring_view CTRL_KEY{ L"ctrl" }; static constexpr std::wstring_view SHIFT_KEY{ L"shift" }; static constexpr std::wstring_view ALT_KEY{ L"alt" }; +static constexpr std::wstring_view WIN_KEY{ L"win" }; -static constexpr int MAX_CHORD_PARTS = 4; +static constexpr int MAX_CHORD_PARTS = 5; // win+ctrl+alt+shift+key // clang-format off static const std::unordered_map vkeyNamePairs { @@ -143,6 +144,10 @@ KeyChord KeyChordSerialization::FromString(const winrt::hstring& hstr) { modifiers |= KeyModifiers::Shift; } + else if (lowercase == WIN_KEY) + { + modifiers |= KeyModifiers::Windows; + } else { bool foundKey = false; @@ -224,6 +229,11 @@ winrt::hstring KeyChordSerialization::ToString(const KeyChord& chord) std::wstring buffer{ L"" }; // Add modifiers + if (WI_IsFlagSet(modifiers, KeyModifiers::Windows)) + { + buffer += WIN_KEY; + buffer += L"+"; + } if (WI_IsFlagSet(modifiers, KeyModifiers::Ctrl)) { buffer += CTRL_KEY; diff --git a/src/cascadia/TerminalSettingsModel/KeyMapping.cpp b/src/cascadia/TerminalSettingsModel/KeyMapping.cpp index a5dd04891c4b..880a6b34d4a8 100644 --- a/src/cascadia/TerminalSettingsModel/KeyMapping.cpp +++ b/src/cascadia/TerminalSettingsModel/KeyMapping.cpp @@ -134,6 +134,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation // note: Menu is the Alt VK_MENU keyModifiers |= Windows::System::VirtualKeyModifiers::Menu; } + if (WI_IsFlagSet(modifiers, KeyModifiers::Windows)) + { + keyModifiers |= Windows::System::VirtualKeyModifiers::Windows; + } return keyModifiers; }