From ed657a0eafa89e26088408ca7cb2ecccf7849d88 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 10 May 2019 14:03:07 -0500 Subject: [PATCH 01/10] Add support for serializing keybindings --- src/cascadia/TerminalApp/AppKeyBindings.cpp | 335 ++++++++++++------ src/cascadia/TerminalApp/AppKeyBindings.h | 3 + src/cascadia/TerminalApp/AppKeyBindings.idl | 3 + .../CascadiaSettingsSerialization.cpp | 3 + .../TerminalApp/GlobalAppSettings.cpp | 3 + src/cascadia/TerminalSettings/KeyChord.cpp | 160 +++++++++ src/cascadia/TerminalSettings/KeyChord.h | 13 + src/cascadia/TerminalSettings/KeyChord.idl | 3 + 8 files changed, 406 insertions(+), 117 deletions(-) diff --git a/src/cascadia/TerminalApp/AppKeyBindings.cpp b/src/cascadia/TerminalApp/AppKeyBindings.cpp index 85fee19a373..9b935f86c67 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindings.cpp @@ -1,117 +1,218 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#include "pch.h" -#include "AppKeyBindings.h" - -using namespace winrt::Microsoft::Terminal; - -namespace winrt::TerminalApp::implementation -{ - void AppKeyBindings::SetKeyBinding(TerminalApp::ShortcutAction const& action, - Settings::KeyChord const& chord) - { - _keyShortcuts[chord] = action; - } - - bool AppKeyBindings::TryKeyChord(Settings::KeyChord const& kc) - { - const auto keyIter = _keyShortcuts.find(kc); - if (keyIter != _keyShortcuts.end()) - { - const auto action = keyIter->second; - return _DoAction(action); - } - return false; - } - - bool AppKeyBindings::_DoAction(ShortcutAction action) - { - switch (action) - { - case ShortcutAction::CopyText: - _CopyTextHandlers(); - return true; - case ShortcutAction::PasteText: - _PasteTextHandlers(); - return true; - case ShortcutAction::NewTab: - _NewTabHandlers(); - return true; - - case ShortcutAction::NewTabProfile0: - _NewTabWithProfileHandlers(0); - return true; - case ShortcutAction::NewTabProfile1: - _NewTabWithProfileHandlers(1); - return true; - case ShortcutAction::NewTabProfile2: - _NewTabWithProfileHandlers(2); - return true; - case ShortcutAction::NewTabProfile3: - _NewTabWithProfileHandlers(3); - return true; - case ShortcutAction::NewTabProfile4: - _NewTabWithProfileHandlers(4); - return true; - case ShortcutAction::NewTabProfile5: - _NewTabWithProfileHandlers(5); - return true; - case ShortcutAction::NewTabProfile6: - _NewTabWithProfileHandlers(6); - return true; - case ShortcutAction::NewTabProfile7: - _NewTabWithProfileHandlers(7); - return true; - case ShortcutAction::NewTabProfile8: - _NewTabWithProfileHandlers(8); - return true; - case ShortcutAction::NewTabProfile9: - _NewTabWithProfileHandlers(9); - return true; - - case ShortcutAction::NewWindow: - _NewWindowHandlers(); - return true; - case ShortcutAction::CloseWindow: - _CloseWindowHandlers(); - return true; - case ShortcutAction::CloseTab: - _CloseTabHandlers(); - return true; - - case ShortcutAction::ScrollUp: - _ScrollUpHandlers(); - return true; - case ShortcutAction::ScrollDown: - _ScrollDownHandlers(); - return true; - - case ShortcutAction::NextTab: - _NextTabHandlers(); - return true; - case ShortcutAction::PrevTab: - _PrevTabHandlers(); - return true; - } - return false; - } - - // -------------------------------- Events --------------------------------- - DEFINE_EVENT(AppKeyBindings, CopyText, _CopyTextHandlers, TerminalApp::CopyTextEventArgs); - DEFINE_EVENT(AppKeyBindings, PasteText, _PasteTextHandlers, TerminalApp::PasteTextEventArgs); - DEFINE_EVENT(AppKeyBindings, NewTab, _NewTabHandlers, TerminalApp::NewTabEventArgs); - DEFINE_EVENT(AppKeyBindings, NewTabWithProfile, _NewTabWithProfileHandlers, TerminalApp::NewTabWithProfileEventArgs); - DEFINE_EVENT(AppKeyBindings, NewWindow, _NewWindowHandlers, TerminalApp::NewWindowEventArgs); - DEFINE_EVENT(AppKeyBindings, CloseWindow, _CloseWindowHandlers, TerminalApp::CloseWindowEventArgs); - DEFINE_EVENT(AppKeyBindings, CloseTab, _CloseTabHandlers, TerminalApp::CloseTabEventArgs); - DEFINE_EVENT(AppKeyBindings, SwitchToTab, _SwitchToTabHandlers, TerminalApp::SwitchToTabEventArgs); - DEFINE_EVENT(AppKeyBindings, NextTab, _NextTabHandlers, TerminalApp::NextTabEventArgs); - DEFINE_EVENT(AppKeyBindings, PrevTab, _PrevTabHandlers, TerminalApp::PrevTabEventArgs); - DEFINE_EVENT(AppKeyBindings, IncreaseFontSize, _IncreaseFontSizeHandlers, TerminalApp::IncreaseFontSizeEventArgs); - DEFINE_EVENT(AppKeyBindings, DecreaseFontSize, _DecreaseFontSizeHandlers, TerminalApp::DecreaseFontSizeEventArgs); - DEFINE_EVENT(AppKeyBindings, ScrollUp, _ScrollUpHandlers, TerminalApp::ScrollUpEventArgs); - DEFINE_EVENT(AppKeyBindings, ScrollDown, _ScrollDownHandlers, TerminalApp::ScrollDownEventArgs); - - -} +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "AppKeyBindings.h" + +using namespace winrt::Microsoft::Terminal; +using namespace winrt::TerminalApp; +using namespace winrt::Windows::Data::Json; + +static const std::wstring KEYS_KEY{ L"keys" }; +static const std::wstring COMMAND_KEY{ L"command" }; + +static const std::wstring COPYTEXT_KEY{ L"copy" }; +static const std::wstring PASTETEXT_KEY{ L"paste" }; +static const std::wstring NEWTAB_KEY{ L"newTab" }; +static const std::wstring NEWTABWITHPROFILE0_KEY{ L"newTabProfile0" }; +static const std::wstring NEWTABWITHPROFILE1_KEY{ L"newTabProfile1" }; +static const std::wstring NEWTABWITHPROFILE2_KEY{ L"newTabProfile2" }; +static const std::wstring NEWTABWITHPROFILE3_KEY{ L"newTabProfile3" }; +static const std::wstring NEWTABWITHPROFILE4_KEY{ L"newTabProfile4" }; +static const std::wstring NEWTABWITHPROFILE5_KEY{ L"newTabProfile5" }; +static const std::wstring NEWTABWITHPROFILE6_KEY{ L"newTabProfile6" }; +static const std::wstring NEWTABWITHPROFILE7_KEY{ L"newTabProfile7" }; +static const std::wstring NEWTABWITHPROFILE8_KEY{ L"newTabProfile8" }; +static const std::wstring NEWTABWITHPROFILE9_KEY{ L"newTabProfile9" }; +static const std::wstring NEWWINDOW_KEY{ L"newWindow" }; +static const std::wstring CLOSEWINDOW_KEY{ L"closeWindow" }; +static const std::wstring CLOSETAB_KEY{ L"closeTab" }; +static const std::wstring SWITCHTOTAB_KEY{ L"switchToTab" }; +static const std::wstring NEXTTAB_KEY{ L"nextTab" }; +static const std::wstring PREVTAB_KEY{ L"prevTab" }; +static const std::wstring INCREASEFONTSIZE_KEY{ L"increaseFontSize" }; +static const std::wstring DECREASEFONTSIZE_KEY{ L"decreaseFontSize" }; +static const std::wstring SCROLLUP_KEY{ L"scrollUp" }; +static const std::wstring SCROLLDOWN_KEY{ L"scrollDown" }; + +static const std::vector> commandNames { + { ShortcutAction::CopyText, COPYTEXT_KEY }, + { ShortcutAction::PasteText, PASTETEXT_KEY }, + { ShortcutAction::NewTab, NEWTAB_KEY }, + { ShortcutAction::NewTabProfile0, NEWTABWITHPROFILE0_KEY }, + { ShortcutAction::NewTabProfile1, NEWTABWITHPROFILE1_KEY }, + { ShortcutAction::NewTabProfile2, NEWTABWITHPROFILE2_KEY }, + { ShortcutAction::NewTabProfile3, NEWTABWITHPROFILE3_KEY }, + { ShortcutAction::NewTabProfile4, NEWTABWITHPROFILE4_KEY }, + { ShortcutAction::NewTabProfile5, NEWTABWITHPROFILE5_KEY }, + { ShortcutAction::NewTabProfile6, NEWTABWITHPROFILE6_KEY }, + { ShortcutAction::NewTabProfile7, NEWTABWITHPROFILE7_KEY }, + { ShortcutAction::NewTabProfile8, NEWTABWITHPROFILE8_KEY }, + { ShortcutAction::NewTabProfile9, NEWTABWITHPROFILE9_KEY }, + { ShortcutAction::NewWindow, NEWWINDOW_KEY }, + { ShortcutAction::CloseWindow, CLOSEWINDOW_KEY }, + { ShortcutAction::CloseTab, CLOSETAB_KEY }, + { ShortcutAction::SwitchToTab, SWITCHTOTAB_KEY }, + { ShortcutAction::NextTab, NEXTTAB_KEY }, + { ShortcutAction::PrevTab, PREVTAB_KEY }, + { ShortcutAction::IncreaseFontSize, INCREASEFONTSIZE_KEY }, + { ShortcutAction::DecreaseFontSize, DECREASEFONTSIZE_KEY }, + { ShortcutAction::ScrollUp, SCROLLUP_KEY }, + { ShortcutAction::ScrollDown, SCROLLDOWN_KEY }, +}; + +namespace winrt::TerminalApp::implementation +{ + void AppKeyBindings::SetKeyBinding(TerminalApp::ShortcutAction const& action, + Settings::KeyChord const& chord) + { + _keyShortcuts[chord] = action; + } + + bool AppKeyBindings::TryKeyChord(Settings::KeyChord const& kc) + { + const auto keyIter = _keyShortcuts.find(kc); + if (keyIter != _keyShortcuts.end()) + { + const auto action = keyIter->second; + return _DoAction(action); + } + return false; + } + + bool AppKeyBindings::_DoAction(ShortcutAction action) + { + switch (action) + { + case ShortcutAction::CopyText: + _CopyTextHandlers(); + return true; + case ShortcutAction::PasteText: + _PasteTextHandlers(); + return true; + case ShortcutAction::NewTab: + _NewTabHandlers(); + return true; + + case ShortcutAction::NewTabProfile0: + _NewTabWithProfileHandlers(0); + return true; + case ShortcutAction::NewTabProfile1: + _NewTabWithProfileHandlers(1); + return true; + case ShortcutAction::NewTabProfile2: + _NewTabWithProfileHandlers(2); + return true; + case ShortcutAction::NewTabProfile3: + _NewTabWithProfileHandlers(3); + return true; + case ShortcutAction::NewTabProfile4: + _NewTabWithProfileHandlers(4); + return true; + case ShortcutAction::NewTabProfile5: + _NewTabWithProfileHandlers(5); + return true; + case ShortcutAction::NewTabProfile6: + _NewTabWithProfileHandlers(6); + return true; + case ShortcutAction::NewTabProfile7: + _NewTabWithProfileHandlers(7); + return true; + case ShortcutAction::NewTabProfile8: + _NewTabWithProfileHandlers(8); + return true; + case ShortcutAction::NewTabProfile9: + _NewTabWithProfileHandlers(9); + return true; + + case ShortcutAction::NewWindow: + _NewWindowHandlers(); + return true; + case ShortcutAction::CloseWindow: + _CloseWindowHandlers(); + return true; + case ShortcutAction::CloseTab: + _CloseTabHandlers(); + return true; + + case ShortcutAction::ScrollUp: + _ScrollUpHandlers(); + return true; + case ShortcutAction::ScrollDown: + _ScrollDownHandlers(); + return true; + + case ShortcutAction::NextTab: + _NextTabHandlers(); + return true; + case ShortcutAction::PrevTab: + _PrevTabHandlers(); + return true; + } + return false; + } + + // -------------------------------- Events --------------------------------- + DEFINE_EVENT(AppKeyBindings, CopyText, _CopyTextHandlers, TerminalApp::CopyTextEventArgs); + DEFINE_EVENT(AppKeyBindings, PasteText, _PasteTextHandlers, TerminalApp::PasteTextEventArgs); + DEFINE_EVENT(AppKeyBindings, NewTab, _NewTabHandlers, TerminalApp::NewTabEventArgs); + DEFINE_EVENT(AppKeyBindings, NewTabWithProfile, _NewTabWithProfileHandlers, TerminalApp::NewTabWithProfileEventArgs); + DEFINE_EVENT(AppKeyBindings, NewWindow, _NewWindowHandlers, TerminalApp::NewWindowEventArgs); + DEFINE_EVENT(AppKeyBindings, CloseWindow, _CloseWindowHandlers, TerminalApp::CloseWindowEventArgs); + DEFINE_EVENT(AppKeyBindings, CloseTab, _CloseTabHandlers, TerminalApp::CloseTabEventArgs); + DEFINE_EVENT(AppKeyBindings, SwitchToTab, _SwitchToTabHandlers, TerminalApp::SwitchToTabEventArgs); + DEFINE_EVENT(AppKeyBindings, NextTab, _NextTabHandlers, TerminalApp::NextTabEventArgs); + DEFINE_EVENT(AppKeyBindings, PrevTab, _PrevTabHandlers, TerminalApp::PrevTabEventArgs); + DEFINE_EVENT(AppKeyBindings, IncreaseFontSize, _IncreaseFontSizeHandlers, TerminalApp::IncreaseFontSizeEventArgs); + DEFINE_EVENT(AppKeyBindings, DecreaseFontSize, _DecreaseFontSizeHandlers, TerminalApp::DecreaseFontSizeEventArgs); + DEFINE_EVENT(AppKeyBindings, ScrollUp, _ScrollUpHandlers, TerminalApp::ScrollUpEventArgs); + DEFINE_EVENT(AppKeyBindings, ScrollDown, _ScrollDownHandlers, TerminalApp::ScrollDownEventArgs); + + + TerminalApp::AppKeyBindings AppKeyBindings::FromJson(Windows::Data::Json::JsonArray const& json) + { + throw hresult_not_implemented(); + } + Windows::Data::Json::JsonArray AppKeyBindings::ToJson() + { + winrt::Windows::Data::Json::JsonArray bindingsArray; + + for (const auto& kv : _keyShortcuts) + { + const auto chord = kv.first; + const auto command = kv.second; + + const auto keyString = chord.ToString(); + if (keyString == L"") + { + continue; + } + + std::wstring commandName{ L"" }; + for (const auto& pair : commandNames) + { + if (pair.first == command) + { + commandName = pair.second; + } + } + if (commandName == L"") + { + continue; + } + + + winrt::Windows::Data::Json::JsonObject jsonObject; + winrt::Windows::Data::Json::JsonArray keysArray; + keysArray.Append(JsonValue::CreateStringValue(keyString)); + jsonObject.Insert(KEYS_KEY, keysArray); + jsonObject.Insert(COMMAND_KEY, JsonValue::CreateStringValue(commandName)); + + bindingsArray.Append(jsonObject); + } + + return bindingsArray; + } + + +} diff --git a/src/cascadia/TerminalApp/AppKeyBindings.h b/src/cascadia/TerminalApp/AppKeyBindings.h index 800a72ea56d..17c3344b0b4 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.h +++ b/src/cascadia/TerminalApp/AppKeyBindings.h @@ -32,6 +32,9 @@ namespace winrt::TerminalApp::implementation { AppKeyBindings() = default; + static TerminalApp::AppKeyBindings FromJson(Windows::Data::Json::JsonArray const& json); + Windows::Data::Json::JsonArray ToJson(); + bool TryKeyChord(winrt::Microsoft::Terminal::Settings::KeyChord const& kc); void SetKeyBinding(TerminalApp::ShortcutAction const& action, winrt::Microsoft::Terminal::Settings::KeyChord const& chord); diff --git a/src/cascadia/TerminalApp/AppKeyBindings.idl b/src/cascadia/TerminalApp/AppKeyBindings.idl index 00212eda60d..70429ace160 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.idl +++ b/src/cascadia/TerminalApp/AppKeyBindings.idl @@ -50,6 +50,9 @@ namespace TerminalApp { AppKeyBindings(); + Windows.Data.Json.JsonArray ToJson(); + static AppKeyBindings FromJson(Windows.Data.Json.JsonArray json); + void SetKeyBinding(ShortcutAction action, Microsoft.Terminal.Settings.KeyChord chord); event CopyTextEventArgs CopyText; diff --git a/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp b/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp index 5adc4b38d5a..6ff30c40955 100644 --- a/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp +++ b/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp @@ -137,6 +137,9 @@ JsonObject CascadiaSettings::ToJson() const jsonObject.Insert(PROFILES_KEY, profilesArray); jsonObject.Insert(SCHEMES_KEY, schemesArray); + jsonObject.Insert(KEYBINDINGS_KEY, + _globals.GetKeybindings().ToJson()); + return jsonObject; } diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.cpp b/src/cascadia/TerminalApp/GlobalAppSettings.cpp index 365049f6be8..7cd8e37ddc6 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalApp/GlobalAppSettings.cpp @@ -153,6 +153,9 @@ JsonObject GlobalAppSettings::ToJson() const JsonValue::CreateStringValue(_SerializeTheme(_requestedTheme))); } + // We'll add the keybindings later in CascadiaSettings, because if we do it + // here, they'll appear before the profiles. + return jsonObject; } diff --git a/src/cascadia/TerminalSettings/KeyChord.cpp b/src/cascadia/TerminalSettings/KeyChord.cpp index 96e771acbcc..0a2162cef73 100644 --- a/src/cascadia/TerminalSettings/KeyChord.cpp +++ b/src/cascadia/TerminalSettings/KeyChord.cpp @@ -4,6 +4,83 @@ #include "pch.h" #include "KeyChord.h" +static const std::wstring CTRL_KEY{ L"ctrl" }; +static const std::wstring SHIFT_KEY{ L"shift" }; +static const std::wstring ALT_KEY{ L"alt" }; + +static const std::vector> vkeyNamePairs{ + { VK_BACK , L"backspace"}, + { VK_TAB , L"tab"}, + { VK_RETURN , L"enter" }, + { VK_ESCAPE , L"esc" }, + { VK_SPACE , L"space" }, + { VK_PRIOR , L"pgup" }, + { VK_NEXT , L"pgdn" }, + { VK_END , L"end" }, + { VK_HOME , L"home" }, + { VK_LEFT , L"left" }, + { VK_UP , L"up" }, + { VK_RIGHT , L"right" }, + { VK_DOWN , L"down" }, + { VK_INSERT , L"insert" }, + { VK_DELETE , L"delete" }, + { VK_NUMPAD0 , L"numpad_0" }, + { VK_NUMPAD1 , L"numpad_1" }, + { VK_NUMPAD2 , L"numpad_2" }, + { VK_NUMPAD3 , L"numpad_3" }, + { VK_NUMPAD4 , L"numpad_4" }, + { VK_NUMPAD5 , L"numpad_5" }, + { VK_NUMPAD6 , L"numpad_6" }, + { VK_NUMPAD7 , L"numpad_7" }, + { VK_NUMPAD8 , L"numpad_8" }, + { VK_NUMPAD9 , L"numpad_9" }, + { VK_MULTIPLY , L"*" }, + { VK_ADD , L"+" }, + { VK_SUBTRACT , L"-" }, + { VK_DECIMAL , L"." }, + { VK_DIVIDE , L"/" }, + { VK_F1 , L"f1" }, + { VK_F2 , L"f2" }, + { VK_F3 , L"f3" }, + { VK_F4 , L"f4" }, + { VK_F5 , L"f5" }, + { VK_F6 , L"f6" }, + { VK_F7 , L"f7" }, + { VK_F8 , L"f8" }, + { VK_F9 , L"f9" }, + { VK_F10 , L"f10" }, + { VK_F11 , L"f11" }, + { VK_F12 , L"f12" }, + { VK_F13 , L"f13" }, + { VK_F14 , L"f14" }, + { VK_F15 , L"f15" }, + { VK_F16 , L"f16" }, + { VK_F17 , L"f17" }, + { VK_F18 , L"f18" }, + { VK_F19 , L"f19" }, + { VK_F20 , L"f20" }, + { VK_F21 , L"f21" }, + { VK_F22 , L"f22" }, + { VK_F23 , L"f23" }, + { VK_F24 , L"f24" }, + { VK_OEM_PLUS , L"+" }, + { VK_OEM_COMMA , L"," }, + { VK_OEM_MINUS , L"-" }, + { VK_OEM_PERIOD , L"." } + +// TODO: +// #define VK_OEM_NEC_EQUAL 0x92 // '=' key on numpad +// #define VK_OEM_1 0xBA // ';:' for US +// #define VK_OEM_2 0xBF // '/?' for US +// #define VK_OEM_3 0xC0 // '`~' for US +// #define VK_OEM_4 0xDB // '[{' for US +// #define VK_OEM_5 0xDC // '\|' for US +// #define VK_OEM_6 0xDD // ']}' for US +// #define VK_OEM_7 0xDE // ''"' for US +}; + + + namespace winrt::Microsoft::Terminal::Settings::implementation { KeyChord::KeyChord(bool ctrl, bool alt, bool shift, int32_t vkey) : @@ -39,4 +116,87 @@ namespace winrt::Microsoft::Terminal::Settings::implementation { _vkey = value; } + + winrt::Microsoft::Terminal::Settings::KeyChord KeyChord::FromString(const hstring& str) + { + // Split the string on '+' + + // If we have > 4, something's wrong. + + // Look for ctrl, shift, alt. Anything else might be a key + // For potential keys, look through the pairs of strings and vkeys + throw hresult_not_implemented(); + } + + hstring KeyChord::ToString() + { + + bool serializedSuccessfully = false; + + std::wstring buffer{ L"" }; + if (WI_IsFlagSet(_modifiers, Settings::KeyModifiers::Ctrl)) + { + buffer += CTRL_KEY; + buffer += L"+"; + } + if (WI_IsFlagSet(_modifiers, Settings::KeyModifiers::Alt)) + { + buffer += ALT_KEY; + buffer += L"+"; + } + if (WI_IsFlagSet(_modifiers, Settings::KeyModifiers::Shift)) + { + buffer += SHIFT_KEY; + buffer += L"+"; + } + + // Quick lookup: ranges of vkeys that correlate directly to a key. + if (_vkey >= L'0' && _vkey <= L'9') + { + buffer += std::wstring(1, static_cast(_vkey)); + serializedSuccessfully = true; + } + else if (_vkey >= L'A' && _vkey <= L'Z') + { + // add 0x20 to shift to lowercase + buffer += std::wstring(1, static_cast(_vkey + 0x20)); + serializedSuccessfully = true; + } + else + { + for (const auto& pair : vkeyNamePairs) + { + if (pair.first == _vkey) + { + buffer += pair.second; + serializedSuccessfully = true; + } + } + } + + if (!serializedSuccessfully) + { + buffer = L""; + } + + return winrt::hstring{ buffer }; + } + } + + +// #define VK_OEM_NEC_EQUAL 0x92 // '=' key on numpad +// #define VK_OEM_1 0xBA // ';:' for US +// #define VK_OEM_PLUS 0xBB // '+' any country +// #define VK_OEM_COMMA 0xBC // ',' any country +// #define VK_OEM_MINUS 0xBD // '-' any country +// #define VK_OEM_PERIOD 0xBE // '.' any country +// #define VK_OEM_2 0xBF // '/?' for US +// #define VK_OEM_3 0xC0 // '`~' for US +// #define VK_OEM_4 0xDB // '[{' for US +// #define VK_OEM_5 0xDC // '\|' for US +// #define VK_OEM_6 0xDD // ']}' for US +// #define VK_OEM_7 0xDE // ''"' for US +// #define VK_OEM_8 0xDF +// #define VK_OEM_AX 0xE1 // 'AX' key on Japanese AX kbd +// #define VK_OEM_102 0xE2 // "<>" or "\|" on RT 102-key kbd. diff --git a/src/cascadia/TerminalSettings/KeyChord.h b/src/cascadia/TerminalSettings/KeyChord.h index 61456b25726..efc03d6a92d 100644 --- a/src/cascadia/TerminalSettings/KeyChord.h +++ b/src/cascadia/TerminalSettings/KeyChord.h @@ -13,6 +13,9 @@ namespace winrt::Microsoft::Terminal::Settings::implementation KeyChord(Settings::KeyModifiers const& modifiers, int32_t vkey); KeyChord(bool ctrl, bool alt, bool shift, int32_t vkey); + static Terminal::Settings::KeyChord FromString(const winrt::hstring& str); + winrt::hstring ToString(); + Settings::KeyModifiers Modifiers(); void Modifiers(Settings::KeyModifiers const& value); int32_t Vkey(); @@ -21,6 +24,16 @@ namespace winrt::Microsoft::Terminal::Settings::implementation private: Settings::KeyModifiers _modifiers; int32_t _vkey; + + // struct VkeyStringMap + // { + // const int32_t vkey; + // const std::wstring name; + // VkeyStringMap(const int32_t key, const std::wstring name) : + // vkey(vkey), + // name(name) {}; + // } + }; } diff --git a/src/cascadia/TerminalSettings/KeyChord.idl b/src/cascadia/TerminalSettings/KeyChord.idl index c02459144b3..89ae5a15b15 100644 --- a/src/cascadia/TerminalSettings/KeyChord.idl +++ b/src/cascadia/TerminalSettings/KeyChord.idl @@ -19,6 +19,9 @@ namespace Microsoft.Terminal.Settings KeyChord(KeyModifiers modifiers, Int32 vkey); KeyChord(Boolean ctrl, Boolean alt, Boolean shift, Int32 vkey); + String ToString(); + static KeyChord FromString(String str); + KeyModifiers Modifiers; Int32 Vkey; } From d3b9fa10d1a6371ebfe9991c15f996321a092989 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 10 May 2019 14:52:46 -0500 Subject: [PATCH 02/10] This is close, but at some point we lose the keybindings when they get reloaded --- src/cascadia/TerminalApp/AppKeyBindings.cpp | 59 ++++++++++++- .../CascadiaSettingsSerialization.cpp | 13 ++- src/cascadia/TerminalSettings/KeyChord.cpp | 84 ++++++++++++++++++- 3 files changed, 148 insertions(+), 8 deletions(-) diff --git a/src/cascadia/TerminalApp/AppKeyBindings.cpp b/src/cascadia/TerminalApp/AppKeyBindings.cpp index 9b935f86c67..f1edaf37d0e 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindings.cpp @@ -168,15 +168,68 @@ namespace winrt::TerminalApp::implementation DEFINE_EVENT(AppKeyBindings, ScrollUp, _ScrollUpHandlers, TerminalApp::ScrollUpEventArgs); DEFINE_EVENT(AppKeyBindings, ScrollDown, _ScrollDownHandlers, TerminalApp::ScrollDownEventArgs); - TerminalApp::AppKeyBindings AppKeyBindings::FromJson(Windows::Data::Json::JsonArray const& json) { - throw hresult_not_implemented(); + TerminalApp::AppKeyBindings newBindings{}; + + for (const auto& value : json) + { + if (value.ValueType() == JsonValueType::Object) + { + JsonObject obj = value.GetObjectW(); + if (obj.HasKey(COMMAND_KEY) && obj.HasKey(KEYS_KEY)) + { + const auto commandString = obj.GetNamedString(COMMAND_KEY); + const auto keys = obj.GetNamedArray(KEYS_KEY); + if (keys.Size() != 1) + { + continue; + } + const auto keyChordString = keys.GetAt(0).GetString(); + ShortcutAction action; + bool parsedSuccessfully = false; + // Try matching the command to one we have + for (const auto& pair : commandNames) + { + if (pair.second == commandString) + { + action = pair.first; + parsedSuccessfully = true; + break; + } + } + if (!parsedSuccessfully) + { + continue; + } + // Try parsing the chord + Settings::KeyChord chord{ false, false, false, 0 }; + parsedSuccessfully = false; + try + { + chord = Settings::KeyChord::FromString(keyChordString); + parsedSuccessfully = true; + } + catch (...) + { + continue; + } + if (parsedSuccessfully) + { + newBindings.SetKeyBinding(action, chord); + } + } + } + } + return newBindings; } + Windows::Data::Json::JsonArray AppKeyBindings::ToJson() { winrt::Windows::Data::Json::JsonArray bindingsArray; - + // TODO: Don't iterate this way, they'll be in random order. Instead + // iterate over all the possible actions in the names list, and see if + // it has a binding. for (const auto& kv : _keyShortcuts) { const auto chord = kv.first; diff --git a/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp b/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp index 6ff30c40955..4cbf83656fe 100644 --- a/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp +++ b/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp @@ -193,9 +193,18 @@ std::unique_ptr CascadiaSettings::FromJson(JsonObject json) } } - // TODO:MSFT:20700157 // Load the keybindings from the file as well - resultPtr->_CreateDefaultKeybindings(); + if (json.HasKey(KEYBINDINGS_KEY)) + { + const auto keybindingsObj = json.GetNamedArray(KEYBINDINGS_KEY); + auto loadedBindings = AppKeyBindings::FromJson(keybindingsObj); + resultPtr->_globals.GetKeybindings() = loadedBindings; + } + else + { + // Create the default keybindings if we couldn't find any keybindings. + resultPtr->_CreateDefaultKeybindings(); + } return resultPtr; } diff --git a/src/cascadia/TerminalSettings/KeyChord.cpp b/src/cascadia/TerminalSettings/KeyChord.cpp index 0a2162cef73..2b085b45b4a 100644 --- a/src/cascadia/TerminalSettings/KeyChord.cpp +++ b/src/cascadia/TerminalSettings/KeyChord.cpp @@ -117,15 +117,92 @@ namespace winrt::Microsoft::Terminal::Settings::implementation _vkey = value; } - winrt::Microsoft::Terminal::Settings::KeyChord KeyChord::FromString(const hstring& str) + winrt::Microsoft::Terminal::Settings::KeyChord KeyChord::FromString(const hstring& hstr) { + std::wstring wstr{ hstr }; + // Split the string on '+' + std::wstring temp; + std::vector parts; + std::wstringstream wss(wstr); + + while(std::getline(wss, temp, L'+')) + { + parts.push_back(temp); + } // If we have > 4, something's wrong. + if (parts.size() > 4) + { + throw hresult_invalid_argument(); + } + + // winrt::Microsoft::Terminal::Settings::KeyChord kc{ false, false, false, 0 }; + KeyModifiers modifiers = KeyModifiers::None; + int32_t vkey = 0; // Look for ctrl, shift, alt. Anything else might be a key - // For potential keys, look through the pairs of strings and vkeys - throw hresult_not_implemented(); + for (const auto& part : parts) + { + if (part == CTRL_KEY) + { + modifiers |= KeyModifiers::Ctrl; + } + else if (part == ALT_KEY) + { + modifiers |= KeyModifiers::Alt; + } + else if (part == SHIFT_KEY) + { + modifiers |= KeyModifiers::Shift; + } + else + { + bool foundKey = false; + // For potential keys, look through the pairs of strings and vkeys + if (part.size() == 1) + { + const wchar_t wch = part[0]; + // Quick lookup: ranges of vkeys that correlate directly to a key. + if (wch >= L'0' && wch <= L'9') + { + vkey = static_cast(wch); + foundKey = true; + } + else if (wch >= L'a' && wch <= L'z') + { + // subtract 0x20 to shift to uppercase + vkey = static_cast(wch - 0x20); + foundKey = true; + } + else if (wch >= L'A' && wch <= L'Z') + { + vkey = static_cast(wch); + foundKey = true; + } + } + + if (!foundKey) + { + for (const auto& pair : vkeyNamePairs) + { + if (pair.second == part) + { + vkey = pair.first; + foundKey = true; + break; + } + } + } + + if (!foundKey) + { + throw hresult_invalid_argument(); + } + } + } + + return winrt::Microsoft::Terminal::Settings::KeyChord{ modifiers, vkey }; } hstring KeyChord::ToString() @@ -170,6 +247,7 @@ namespace winrt::Microsoft::Terminal::Settings::implementation { buffer += pair.second; serializedSuccessfully = true; + break; } } } From 82f4fff1238788b50b20cbbfc2d570cd0e82c8cb Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 13 May 2019 11:15:04 -0500 Subject: [PATCH 03/10] Fix actually loading the keys --- src/cascadia/TerminalApp/App.cpp | 2 +- src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp | 2 +- src/cascadia/TerminalApp/GlobalAppSettings.cpp | 5 +++++ src/cascadia/TerminalApp/GlobalAppSettings.h | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalApp/App.cpp b/src/cascadia/TerminalApp/App.cpp index 9086a2bf109..68ee340abf5 100644 --- a/src/cascadia/TerminalApp/App.cpp +++ b/src/cascadia/TerminalApp/App.cpp @@ -403,7 +403,7 @@ namespace winrt::TerminalApp::implementation // - void App::_ReloadSettings() { - _settings = CascadiaSettings::LoadAll(); + _settings = CascadiaSettings::LoadAll(false); // Re-wire the keybindings to their handlers, as we'll have created a // new AppKeyBindings object. _HookupKeyBindings(_settings->GetKeybindings()); diff --git a/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp b/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp index 4cbf83656fe..49dcd04b10a 100644 --- a/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp +++ b/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp @@ -198,7 +198,7 @@ std::unique_ptr CascadiaSettings::FromJson(JsonObject json) { const auto keybindingsObj = json.GetNamedArray(KEYBINDINGS_KEY); auto loadedBindings = AppKeyBindings::FromJson(keybindingsObj); - resultPtr->_globals.GetKeybindings() = loadedBindings; + resultPtr->_globals.SetKeybindings(loadedBindings); } else { diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.cpp b/src/cascadia/TerminalApp/GlobalAppSettings.cpp index 7cd8e37ddc6..b24974c2d86 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalApp/GlobalAppSettings.cpp @@ -71,6 +71,11 @@ AppKeyBindings GlobalAppSettings::GetKeybindings() const noexcept return _keybindings; } +void GlobalAppSettings::SetKeybindings(winrt::TerminalApp::AppKeyBindings newBindings) noexcept +{ + _keybindings = newBindings; +} + bool GlobalAppSettings::GetAlwaysShowTabs() const noexcept { return _alwaysShowTabs; diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.h b/src/cascadia/TerminalApp/GlobalAppSettings.h index 6e20593aaf6..1398c6019bf 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.h +++ b/src/cascadia/TerminalApp/GlobalAppSettings.h @@ -35,6 +35,7 @@ class TerminalApp::GlobalAppSettings final GUID GetDefaultProfile() const noexcept; winrt::TerminalApp::AppKeyBindings GetKeybindings() const noexcept; + void SetKeybindings(winrt::TerminalApp::AppKeyBindings newBindings) noexcept; bool GetAlwaysShowTabs() const noexcept; void SetAlwaysShowTabs(const bool showTabs) noexcept; From 0e3a197bc30dd29c5daca51baaab727a3a1aa128 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 13 May 2019 11:37:41 -0500 Subject: [PATCH 04/10] Don't serialize over the unordered_map Instead iterate over the action names, then serialize in that order, so it's sane. --- src/cascadia/TerminalApp/AppKeyBindings.cpp | 57 +++++++++++---------- src/cascadia/TerminalSettings/KeyChord.cpp | 1 - 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/cascadia/TerminalApp/AppKeyBindings.cpp b/src/cascadia/TerminalApp/AppKeyBindings.cpp index f1edaf37d0e..c7b49af7d20 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindings.cpp @@ -224,44 +224,45 @@ namespace winrt::TerminalApp::implementation return newBindings; } + void _AddShortcutToJsonArray(JsonArray bindingsArray, + const Settings::KeyChord& chord, + const TerminalApp::ShortcutAction& action, + const std::wstring& actionName) + { + const auto keyString = chord.ToString(); + if (keyString == L"") + { + return; + } + + winrt::Windows::Data::Json::JsonObject jsonObject; + winrt::Windows::Data::Json::JsonArray keysArray; + keysArray.Append(JsonValue::CreateStringValue(keyString)); + jsonObject.Insert(KEYS_KEY, keysArray); + jsonObject.Insert(COMMAND_KEY, JsonValue::CreateStringValue(actionName)); + + bindingsArray.Append(jsonObject); + } + Windows::Data::Json::JsonArray AppKeyBindings::ToJson() { winrt::Windows::Data::Json::JsonArray bindingsArray; - // TODO: Don't iterate this way, they'll be in random order. Instead + // iterate over all the possible actions in the names list, and see if // it has a binding. - for (const auto& kv : _keyShortcuts) + for (auto& actionName : commandNames) { - const auto chord = kv.first; - const auto command = kv.second; - - const auto keyString = chord.ToString(); - if (keyString == L"") + const auto searchedForAction = actionName.first; + const auto searchedForName = actionName.second; + for (const auto& kv : _keyShortcuts) { - continue; - } - - std::wstring commandName{ L"" }; - for (const auto& pair : commandNames) - { - if (pair.first == command) + const auto chord = kv.first; + const auto command = kv.second; + if (command == searchedForAction) { - commandName = pair.second; + _AddShortcutToJsonArray(bindingsArray, chord, command, searchedForName); } } - if (commandName == L"") - { - continue; - } - - - winrt::Windows::Data::Json::JsonObject jsonObject; - winrt::Windows::Data::Json::JsonArray keysArray; - keysArray.Append(JsonValue::CreateStringValue(keyString)); - jsonObject.Insert(KEYS_KEY, keysArray); - jsonObject.Insert(COMMAND_KEY, JsonValue::CreateStringValue(commandName)); - - bindingsArray.Append(jsonObject); } return bindingsArray; diff --git a/src/cascadia/TerminalSettings/KeyChord.cpp b/src/cascadia/TerminalSettings/KeyChord.cpp index 2b085b45b4a..a49826d2e7c 100644 --- a/src/cascadia/TerminalSettings/KeyChord.cpp +++ b/src/cascadia/TerminalSettings/KeyChord.cpp @@ -207,7 +207,6 @@ namespace winrt::Microsoft::Terminal::Settings::implementation hstring KeyChord::ToString() { - bool serializedSuccessfully = false; std::wstring buffer{ L"" }; From 66592b5f19db5512cf5647aa36c7bd76f22f5068 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 13 May 2019 15:02:37 -0500 Subject: [PATCH 05/10] Clean up for PR This fixes #537 --- src/cascadia/TerminalApp/AppKeyBindings.cpp | 32 ++++++++++--- src/cascadia/TerminalSettings/KeyChord.cpp | 50 ++++++++++++--------- src/cascadia/TerminalSettings/KeyChord.h | 10 ----- 3 files changed, 55 insertions(+), 37 deletions(-) diff --git a/src/cascadia/TerminalApp/AppKeyBindings.cpp b/src/cascadia/TerminalApp/AppKeyBindings.cpp index c7b49af7d20..b8763e64939 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindings.cpp @@ -168,6 +168,18 @@ namespace winrt::TerminalApp::implementation DEFINE_EVENT(AppKeyBindings, ScrollUp, _ScrollUpHandlers, TerminalApp::ScrollUpEventArgs); DEFINE_EVENT(AppKeyBindings, ScrollDown, _ScrollDownHandlers, TerminalApp::ScrollDownEventArgs); + + // Method Description: + // - Deserialize an AppKeyBindings from the key mappings that are in the + // array `json`. The json array should contain an array of objects with + // both a `command` string and a `keys` array, where `command` i one of + // the names listed in `commandNames`, and `keys` is an array of + // keypresses. Currently, the array should contain a single string, which + // can be deserialized into a KeyChord. + // Arguments: + // - json: and arrayof JsonObject's to deserialize into our _keyShortcuts mapping. + // Return Value: + // - the newly constructed AppKeyBindings object. TerminalApp::AppKeyBindings AppKeyBindings::FromJson(Windows::Data::Json::JsonArray const& json) { TerminalApp::AppKeyBindings newBindings{}; @@ -224,9 +236,15 @@ namespace winrt::TerminalApp::implementation return newBindings; } + // Function Description: + // - Small helper to insert a given KeyChord, ShortcutAction pair into the + // given json array + // Arguments: + // - bindingsArray: The JsonArray to insert the object into. + // - chord: The KeyChord to serailize and place in the json array + // - actionName: the name of the ShortcutAction to use with this KeyChord void _AddShortcutToJsonArray(JsonArray bindingsArray, const Settings::KeyChord& chord, - const TerminalApp::ShortcutAction& action, const std::wstring& actionName) { const auto keyString = chord.ToString(); @@ -244,11 +262,17 @@ namespace winrt::TerminalApp::implementation bindingsArray.Append(jsonObject); } + // Method Description: + // - Serialize this AppKeyBindings to a json array of objects. Each object + // in the array represents a single keybinding, mapping a KeyChord to a + // ShortcutAction. + // Return Value: + // - a JsonArray which is an equivalent serialization of this object. Windows::Data::Json::JsonArray AppKeyBindings::ToJson() { winrt::Windows::Data::Json::JsonArray bindingsArray; - // iterate over all the possible actions in the names list, and see if + // Iterate over all the possible actions in the names list, and see if // it has a binding. for (auto& actionName : commandNames) { @@ -260,13 +284,11 @@ namespace winrt::TerminalApp::implementation const auto command = kv.second; if (command == searchedForAction) { - _AddShortcutToJsonArray(bindingsArray, chord, command, searchedForName); + _AddShortcutToJsonArray(bindingsArray, chord, searchedForName); } } } return bindingsArray; } - - } diff --git a/src/cascadia/TerminalSettings/KeyChord.cpp b/src/cascadia/TerminalSettings/KeyChord.cpp index a49826d2e7c..5de4df957ae 100644 --- a/src/cascadia/TerminalSettings/KeyChord.cpp +++ b/src/cascadia/TerminalSettings/KeyChord.cpp @@ -8,7 +8,7 @@ static const std::wstring CTRL_KEY{ L"ctrl" }; static const std::wstring SHIFT_KEY{ L"shift" }; static const std::wstring ALT_KEY{ L"alt" }; -static const std::vector> vkeyNamePairs{ +static const std::vector> vkeyNamePairs { { VK_BACK , L"backspace"}, { VK_TAB , L"tab"}, { VK_RETURN , L"enter" }, @@ -67,8 +67,9 @@ static const std::vector> vkeyNamePairs{ { VK_OEM_COMMA , L"," }, { VK_OEM_MINUS , L"-" }, { VK_OEM_PERIOD , L"." } - // TODO: +// These all look like they'd be good keybindings, but change based on keyboard +// layout. How do we deal with that? // #define VK_OEM_NEC_EQUAL 0x92 // '=' key on numpad // #define VK_OEM_1 0xBA // ';:' for US // #define VK_OEM_2 0xBF // '/?' for US @@ -79,8 +80,6 @@ static const std::vector> vkeyNamePairs{ // #define VK_OEM_7 0xDE // ''"' for US }; - - namespace winrt::Microsoft::Terminal::Settings::implementation { KeyChord::KeyChord(bool ctrl, bool alt, bool shift, int32_t vkey) : @@ -117,6 +116,17 @@ namespace winrt::Microsoft::Terminal::Settings::implementation _vkey = value; } + // Method Description: + // - Deserializes the given string into a new KeyChord instance. If this + // fails to translate the string into a keychord, it will throw a + // hresult_invalid_argument exception. + // - The string should fit the format "[ctrl+][alt+][shift+]", + // where each modifier is optional, and keyName is either one of the + // names listed in the vkeyNamePairs vector above, or is one of 0-9a-zA-Z. + // Arguments: + // - hstr: the string to parse into a keychord. + // Return Value: + // - a newly constructed KeyChord winrt::Microsoft::Terminal::Settings::KeyChord KeyChord::FromString(const hstring& hstr) { std::wstring wstr{ hstr }; @@ -137,7 +147,6 @@ namespace winrt::Microsoft::Terminal::Settings::implementation throw hresult_invalid_argument(); } - // winrt::Microsoft::Terminal::Settings::KeyChord kc{ false, false, false, 0 }; KeyModifiers modifiers = KeyModifiers::None; int32_t vkey = 0; @@ -182,6 +191,8 @@ namespace winrt::Microsoft::Terminal::Settings::implementation } } + // If we didn't find the key with a quick lookup, search the + // table to see if we have a matching name. if (!foundKey) { for (const auto& pair : vkeyNamePairs) @@ -195,6 +206,7 @@ namespace winrt::Microsoft::Terminal::Settings::implementation } } + // If we weren't able to find a match, throw an exception. if (!foundKey) { throw hresult_invalid_argument(); @@ -205,11 +217,22 @@ namespace winrt::Microsoft::Terminal::Settings::implementation return winrt::Microsoft::Terminal::Settings::KeyChord{ modifiers, vkey }; } + // Method Description: + // - Serialize this keychord into a string represenation. + // - The string will fit the format "[ctrl+][alt+][shift+]", + // where each modifier is optional, and keyName is either one of the + // names listed in the vkeyNamePairs vector above, or is one of 0-9a-z. + // Arguments: + // - + // Return Value: + // - a string which is an equivalent serialization of this object. hstring KeyChord::ToString() { bool serializedSuccessfully = false; std::wstring buffer{ L"" }; + + // Add modifiers if (WI_IsFlagSet(_modifiers, Settings::KeyModifiers::Ctrl)) { buffer += CTRL_KEY; @@ -260,20 +283,3 @@ namespace winrt::Microsoft::Terminal::Settings::implementation } } - - -// #define VK_OEM_NEC_EQUAL 0x92 // '=' key on numpad -// #define VK_OEM_1 0xBA // ';:' for US -// #define VK_OEM_PLUS 0xBB // '+' any country -// #define VK_OEM_COMMA 0xBC // ',' any country -// #define VK_OEM_MINUS 0xBD // '-' any country -// #define VK_OEM_PERIOD 0xBE // '.' any country -// #define VK_OEM_2 0xBF // '/?' for US -// #define VK_OEM_3 0xC0 // '`~' for US -// #define VK_OEM_4 0xDB // '[{' for US -// #define VK_OEM_5 0xDC // '\|' for US -// #define VK_OEM_6 0xDD // ']}' for US -// #define VK_OEM_7 0xDE // ''"' for US -// #define VK_OEM_8 0xDF -// #define VK_OEM_AX 0xE1 // 'AX' key on Japanese AX kbd -// #define VK_OEM_102 0xE2 // "<>" or "\|" on RT 102-key kbd. diff --git a/src/cascadia/TerminalSettings/KeyChord.h b/src/cascadia/TerminalSettings/KeyChord.h index efc03d6a92d..cc32cff6aca 100644 --- a/src/cascadia/TerminalSettings/KeyChord.h +++ b/src/cascadia/TerminalSettings/KeyChord.h @@ -24,16 +24,6 @@ namespace winrt::Microsoft::Terminal::Settings::implementation private: Settings::KeyModifiers _modifiers; int32_t _vkey; - - // struct VkeyStringMap - // { - // const int32_t vkey; - // const std::wstring name; - // VkeyStringMap(const int32_t key, const std::wstring name) : - // vkey(vkey), - // name(name) {}; - // } - }; } From 872708512d109c237c764b25c752b8845833465f Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 15 May 2019 15:03:46 -0500 Subject: [PATCH 06/10] Some PR nits --- src/cascadia/TerminalApp/AppKeyBindings.cpp | 13 ++++---- src/cascadia/TerminalSettings/KeyChord.cpp | 37 +++++++++++---------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/cascadia/TerminalApp/AppKeyBindings.cpp b/src/cascadia/TerminalApp/AppKeyBindings.cpp index 4b8ca3d7c36..7c52cf6a5ac 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindings.cpp @@ -1,4 +1,3 @@ -<<<<<<< HEAD // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. @@ -88,13 +87,13 @@ static const std::vector> commandNames { namespace winrt::TerminalApp::implementation { - void AppKeyBindings::SetKeyBinding(TerminalApp::ShortcutAction const& action, - Settings::KeyChord const& chord) + void AppKeyBindings::SetKeyBinding(const TerminalApp::ShortcutAction& action, + const Settings::KeyChord& chord) { _keyShortcuts[chord] = action; } - bool AppKeyBindings::TryKeyChord(Settings::KeyChord const& kc) + bool AppKeyBindings::TryKeyChord(const Settings::KeyChord& kc) { const auto keyIter = _keyShortcuts.find(kc); if (keyIter != _keyShortcuts.end()) @@ -239,15 +238,15 @@ namespace winrt::TerminalApp::implementation // Method Description: // - Deserialize an AppKeyBindings from the key mappings that are in the // array `json`. The json array should contain an array of objects with - // both a `command` string and a `keys` array, where `command` i one of + // both a `command` string and a `keys` array, where `command` is one of // the names listed in `commandNames`, and `keys` is an array of // keypresses. Currently, the array should contain a single string, which // can be deserialized into a KeyChord. // Arguments: - // - json: and arrayof JsonObject's to deserialize into our _keyShortcuts mapping. + // - json: and array of JsonObject's to deserialize into our _keyShortcuts mapping. // Return Value: // - the newly constructed AppKeyBindings object. - TerminalApp::AppKeyBindings AppKeyBindings::FromJson(Windows::Data::Json::JsonArray const& json) + TerminalApp::AppKeyBindings AppKeyBindings::FromJson(const JsonArray& json) { TerminalApp::AppKeyBindings newBindings{}; diff --git a/src/cascadia/TerminalSettings/KeyChord.cpp b/src/cascadia/TerminalSettings/KeyChord.cpp index 5de4df957ae..43dd8529afa 100644 --- a/src/cascadia/TerminalSettings/KeyChord.cpp +++ b/src/cascadia/TerminalSettings/KeyChord.cpp @@ -4,11 +4,14 @@ #include "pch.h" #include "KeyChord.h" + static const std::wstring CTRL_KEY{ L"ctrl" }; static const std::wstring SHIFT_KEY{ L"shift" }; static const std::wstring ALT_KEY{ L"alt" }; -static const std::vector> vkeyNamePairs { +static constexpr int MAX_CHORD_PARTS = 4; + +static const std::unordered_map vkeyNamePairs { { VK_BACK , L"backspace"}, { VK_TAB , L"tab"}, { VK_RETURN , L"enter" }, @@ -34,11 +37,11 @@ static const std::vector> vkeyNamePairs { { VK_NUMPAD7 , L"numpad_7" }, { VK_NUMPAD8 , L"numpad_8" }, { VK_NUMPAD9 , L"numpad_9" }, - { VK_MULTIPLY , L"*" }, - { VK_ADD , L"+" }, - { VK_SUBTRACT , L"-" }, - { VK_DECIMAL , L"." }, - { VK_DIVIDE , L"/" }, + { VK_MULTIPLY , L"numpad_multiply" }, + { VK_ADD , L"numpad_plus" }, + { VK_SUBTRACT , L"numpad_minus" }, + { VK_DECIMAL , L"numpad_period" }, + { VK_DIVIDE , L"numpad_divide" }, { VK_F1 , L"f1" }, { VK_F2 , L"f2" }, { VK_F3 , L"f3" }, @@ -63,7 +66,7 @@ static const std::vector> vkeyNamePairs { { VK_F22 , L"f22" }, { VK_F23 , L"f23" }, { VK_F24 , L"f24" }, - { VK_OEM_PLUS , L"+" }, + { VK_OEM_PLUS , L"plus" }, { VK_OEM_COMMA , L"," }, { VK_OEM_MINUS , L"-" }, { VK_OEM_PERIOD , L"." } @@ -139,12 +142,12 @@ namespace winrt::Microsoft::Terminal::Settings::implementation while(std::getline(wss, temp, L'+')) { parts.push_back(temp); - } - // If we have > 4, something's wrong. - if (parts.size() > 4) - { - throw hresult_invalid_argument(); + // If we have > 4, something's wrong. + if (parts.size() > MAX_CHORD_PARTS) + { + throw hresult_invalid_argument(); + } } KeyModifiers modifiers = KeyModifiers::None; @@ -153,15 +156,17 @@ namespace winrt::Microsoft::Terminal::Settings::implementation // Look for ctrl, shift, alt. Anything else might be a key for (const auto& part : parts) { - if (part == CTRL_KEY) + std::wstring lowercase = part; + std::transform(lowercase.begin(), lowercase.end(), lowercase.begin(), std::towlower); + if (lowercase == CTRL_KEY) { modifiers |= KeyModifiers::Ctrl; } - else if (part == ALT_KEY) + else if (lowercase == ALT_KEY) { modifiers |= KeyModifiers::Alt; } - else if (part == SHIFT_KEY) + else if (lowercase == SHIFT_KEY) { modifiers |= KeyModifiers::Shift; } @@ -222,8 +227,6 @@ namespace winrt::Microsoft::Terminal::Settings::implementation // - The string will fit the format "[ctrl+][alt+][shift+]", // where each modifier is optional, and keyName is either one of the // names listed in the vkeyNamePairs vector above, or is one of 0-9a-z. - // Arguments: - // - // Return Value: // - a string which is an equivalent serialization of this object. hstring KeyChord::ToString() From 4b75c853379298fe74a952fcf0d1ee9a2b7fb8a9 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 15 May 2019 15:44:41 -0500 Subject: [PATCH 07/10] well that was easier than expected * Update the appkeybindings vector to a map * Update the strings to wchar_t*'s to avoid ctoring a ton on startup --- src/cascadia/TerminalApp/AppKeyBindings.cpp | 80 ++++++++++----------- src/cascadia/TerminalSettings/KeyChord.cpp | 19 ++--- 2 files changed, 47 insertions(+), 52 deletions(-) diff --git a/src/cascadia/TerminalApp/AppKeyBindings.cpp b/src/cascadia/TerminalApp/AppKeyBindings.cpp index 7c52cf6a5ac..abb3ef7d411 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindings.cpp @@ -8,47 +8,47 @@ using namespace winrt::Microsoft::Terminal; using namespace winrt::TerminalApp; using namespace winrt::Windows::Data::Json; -static const std::wstring KEYS_KEY{ L"keys" }; -static const std::wstring COMMAND_KEY{ L"command" }; +static const wchar_t* const KEYS_KEY{ L"keys" }; +static const wchar_t* const COMMAND_KEY{ L"command" }; -static const std::wstring COPYTEXT_KEY{ L"copy" }; -static const std::wstring PASTETEXT_KEY{ L"paste" }; -static const std::wstring NEWTAB_KEY{ L"newTab" }; -static const std::wstring NEWTABWITHPROFILE0_KEY{ L"newTabProfile0" }; -static const std::wstring NEWTABWITHPROFILE1_KEY{ L"newTabProfile1" }; -static const std::wstring NEWTABWITHPROFILE2_KEY{ L"newTabProfile2" }; -static const std::wstring NEWTABWITHPROFILE3_KEY{ L"newTabProfile3" }; -static const std::wstring NEWTABWITHPROFILE4_KEY{ L"newTabProfile4" }; -static const std::wstring NEWTABWITHPROFILE5_KEY{ L"newTabProfile5" }; -static const std::wstring NEWTABWITHPROFILE6_KEY{ L"newTabProfile6" }; -static const std::wstring NEWTABWITHPROFILE7_KEY{ L"newTabProfile7" }; -static const std::wstring NEWTABWITHPROFILE8_KEY{ L"newTabProfile8" }; -static const std::wstring NEWTABWITHPROFILE9_KEY{ L"newTabProfile9" }; -static const std::wstring NEWWINDOW_KEY{ L"newWindow" }; -static const std::wstring CLOSEWINDOW_KEY{ L"closeWindow" }; -static const std::wstring CLOSETAB_KEY{ L"closeTab" }; -static const std::wstring SWITCHTOTAB_KEY{ L"switchToTab" }; -static const std::wstring NEXTTAB_KEY{ L"nextTab" }; -static const std::wstring PREVTAB_KEY{ L"prevTab" }; -static const std::wstring INCREASEFONTSIZE_KEY{ L"increaseFontSize" }; -static const std::wstring DECREASEFONTSIZE_KEY{ L"decreaseFontSize" }; -static const std::wstring SCROLLUP_KEY{ L"scrollUp" }; -static const std::wstring SCROLLDOWN_KEY{ L"scrollDown" }; -static const std::wstring SCROLLUPPAGE_KEY{ L"scrollUpPage" }; -static const std::wstring SCROLLDOWNPAGE_KEY{ L"scrollDownPage" }; -static const std::wstring SWITCHTOTAB0_KEY{ L"switchToTab0" }; -static const std::wstring SWITCHTOTAB1_KEY{ L"switchToTab1" }; -static const std::wstring SWITCHTOTAB2_KEY{ L"switchToTab2" }; -static const std::wstring SWITCHTOTAB3_KEY{ L"switchToTab3" }; -static const std::wstring SWITCHTOTAB4_KEY{ L"switchToTab4" }; -static const std::wstring SWITCHTOTAB5_KEY{ L"switchToTab5" }; -static const std::wstring SWITCHTOTAB6_KEY{ L"switchToTab6" }; -static const std::wstring SWITCHTOTAB7_KEY{ L"switchToTab7" }; -static const std::wstring SWITCHTOTAB8_KEY{ L"switchToTab8" }; -static const std::wstring SWITCHTOTAB9_KEY{ L"switchToTab9" }; -static const std::wstring OPENSETTINGS_KEY{ L"openSettings" }; +static const wchar_t* const COPYTEXT_KEY{ L"copy" }; +static const wchar_t* const PASTETEXT_KEY{ L"paste" }; +static const wchar_t* const NEWTAB_KEY{ L"newTab" }; +static const wchar_t* const NEWTABWITHPROFILE0_KEY{ L"newTabProfile0" }; +static const wchar_t* const NEWTABWITHPROFILE1_KEY{ L"newTabProfile1" }; +static const wchar_t* const NEWTABWITHPROFILE2_KEY{ L"newTabProfile2" }; +static const wchar_t* const NEWTABWITHPROFILE3_KEY{ L"newTabProfile3" }; +static const wchar_t* const NEWTABWITHPROFILE4_KEY{ L"newTabProfile4" }; +static const wchar_t* const NEWTABWITHPROFILE5_KEY{ L"newTabProfile5" }; +static const wchar_t* const NEWTABWITHPROFILE6_KEY{ L"newTabProfile6" }; +static const wchar_t* const NEWTABWITHPROFILE7_KEY{ L"newTabProfile7" }; +static const wchar_t* const NEWTABWITHPROFILE8_KEY{ L"newTabProfile8" }; +static const wchar_t* const NEWTABWITHPROFILE9_KEY{ L"newTabProfile9" }; +static const wchar_t* const NEWWINDOW_KEY{ L"newWindow" }; +static const wchar_t* const CLOSEWINDOW_KEY{ L"closeWindow" }; +static const wchar_t* const CLOSETAB_KEY{ L"closeTab" }; +static const wchar_t* const SWITCHTOTAB_KEY{ L"switchToTab" }; +static const wchar_t* const NEXTTAB_KEY{ L"nextTab" }; +static const wchar_t* const PREVTAB_KEY{ L"prevTab" }; +static const wchar_t* const INCREASEFONTSIZE_KEY{ L"increaseFontSize" }; +static const wchar_t* const DECREASEFONTSIZE_KEY{ L"decreaseFontSize" }; +static const wchar_t* const SCROLLUP_KEY{ L"scrollUp" }; +static const wchar_t* const SCROLLDOWN_KEY{ L"scrollDown" }; +static const wchar_t* const SCROLLUPPAGE_KEY{ L"scrollUpPage" }; +static const wchar_t* const SCROLLDOWNPAGE_KEY{ L"scrollDownPage" }; +static const wchar_t* const SWITCHTOTAB0_KEY{ L"switchToTab0" }; +static const wchar_t* const SWITCHTOTAB1_KEY{ L"switchToTab1" }; +static const wchar_t* const SWITCHTOTAB2_KEY{ L"switchToTab2" }; +static const wchar_t* const SWITCHTOTAB3_KEY{ L"switchToTab3" }; +static const wchar_t* const SWITCHTOTAB4_KEY{ L"switchToTab4" }; +static const wchar_t* const SWITCHTOTAB5_KEY{ L"switchToTab5" }; +static const wchar_t* const SWITCHTOTAB6_KEY{ L"switchToTab6" }; +static const wchar_t* const SWITCHTOTAB7_KEY{ L"switchToTab7" }; +static const wchar_t* const SWITCHTOTAB8_KEY{ L"switchToTab8" }; +static const wchar_t* const SWITCHTOTAB9_KEY{ L"switchToTab9" }; +static const wchar_t* const OPENSETTINGS_KEY{ L"openSettings" }; -static const std::vector> commandNames { +static const std::map commandNames { { ShortcutAction::CopyText, COPYTEXT_KEY }, { ShortcutAction::PasteText, PASTETEXT_KEY }, { ShortcutAction::NewTab, NEWTAB_KEY }, @@ -311,7 +311,7 @@ namespace winrt::TerminalApp::implementation // - actionName: the name of the ShortcutAction to use with this KeyChord void _AddShortcutToJsonArray(JsonArray bindingsArray, const Settings::KeyChord& chord, - const std::wstring& actionName) + const std::wstring_view& actionName) { const auto keyString = chord.ToString(); if (keyString == L"") diff --git a/src/cascadia/TerminalSettings/KeyChord.cpp b/src/cascadia/TerminalSettings/KeyChord.cpp index 43dd8529afa..5447ee677ba 100644 --- a/src/cascadia/TerminalSettings/KeyChord.cpp +++ b/src/cascadia/TerminalSettings/KeyChord.cpp @@ -4,14 +4,13 @@ #include "pch.h" #include "KeyChord.h" - -static const std::wstring CTRL_KEY{ L"ctrl" }; -static const std::wstring SHIFT_KEY{ L"shift" }; -static const std::wstring ALT_KEY{ L"alt" }; +static const wchar_t* const CTRL_KEY{ L"ctrl" }; +static const wchar_t* const SHIFT_KEY{ L"shift" }; +static const wchar_t* const ALT_KEY{ L"alt" }; static constexpr int MAX_CHORD_PARTS = 4; -static const std::unordered_map vkeyNamePairs { +static const std::unordered_map vkeyNamePairs { { VK_BACK , L"backspace"}, { VK_TAB , L"tab"}, { VK_RETURN , L"enter" }, @@ -266,14 +265,10 @@ namespace winrt::Microsoft::Terminal::Settings::implementation } else { - for (const auto& pair : vkeyNamePairs) + if (vkeyNamePairs.find(_vkey) != vkeyNamePairs.end()) { - if (pair.first == _vkey) - { - buffer += pair.second; - serializedSuccessfully = true; - break; - } + buffer += vkeyNamePairs.at(_vkey); + serializedSuccessfully = true; } } From 3eaabfac86f54ef2be4cb6279a97590b0b3b38af Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 15 May 2019 17:16:43 -0500 Subject: [PATCH 08/10] * use a constexpr wstring_view * flip the names, actions map around --- src/cascadia/TerminalApp/AppKeyBindings.cpp | 177 ++++++++++---------- src/cascadia/TerminalSettings/KeyChord.cpp | 163 ------------------ 2 files changed, 84 insertions(+), 256 deletions(-) diff --git a/src/cascadia/TerminalApp/AppKeyBindings.cpp b/src/cascadia/TerminalApp/AppKeyBindings.cpp index abb3ef7d411..194257ad993 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindings.cpp @@ -3,86 +3,87 @@ #include "pch.h" #include "AppKeyBindings.h" +#include "KeyChordSerialization.h" using namespace winrt::Microsoft::Terminal; using namespace winrt::TerminalApp; using namespace winrt::Windows::Data::Json; -static const wchar_t* const KEYS_KEY{ L"keys" }; -static const wchar_t* const COMMAND_KEY{ L"command" }; +static constexpr std::wstring_view KEYS_KEY{ L"keys" }; +static constexpr std::wstring_view COMMAND_KEY{ L"command" }; -static const wchar_t* const COPYTEXT_KEY{ L"copy" }; -static const wchar_t* const PASTETEXT_KEY{ L"paste" }; -static const wchar_t* const NEWTAB_KEY{ L"newTab" }; -static const wchar_t* const NEWTABWITHPROFILE0_KEY{ L"newTabProfile0" }; -static const wchar_t* const NEWTABWITHPROFILE1_KEY{ L"newTabProfile1" }; -static const wchar_t* const NEWTABWITHPROFILE2_KEY{ L"newTabProfile2" }; -static const wchar_t* const NEWTABWITHPROFILE3_KEY{ L"newTabProfile3" }; -static const wchar_t* const NEWTABWITHPROFILE4_KEY{ L"newTabProfile4" }; -static const wchar_t* const NEWTABWITHPROFILE5_KEY{ L"newTabProfile5" }; -static const wchar_t* const NEWTABWITHPROFILE6_KEY{ L"newTabProfile6" }; -static const wchar_t* const NEWTABWITHPROFILE7_KEY{ L"newTabProfile7" }; -static const wchar_t* const NEWTABWITHPROFILE8_KEY{ L"newTabProfile8" }; -static const wchar_t* const NEWTABWITHPROFILE9_KEY{ L"newTabProfile9" }; -static const wchar_t* const NEWWINDOW_KEY{ L"newWindow" }; -static const wchar_t* const CLOSEWINDOW_KEY{ L"closeWindow" }; -static const wchar_t* const CLOSETAB_KEY{ L"closeTab" }; -static const wchar_t* const SWITCHTOTAB_KEY{ L"switchToTab" }; -static const wchar_t* const NEXTTAB_KEY{ L"nextTab" }; -static const wchar_t* const PREVTAB_KEY{ L"prevTab" }; -static const wchar_t* const INCREASEFONTSIZE_KEY{ L"increaseFontSize" }; -static const wchar_t* const DECREASEFONTSIZE_KEY{ L"decreaseFontSize" }; -static const wchar_t* const SCROLLUP_KEY{ L"scrollUp" }; -static const wchar_t* const SCROLLDOWN_KEY{ L"scrollDown" }; -static const wchar_t* const SCROLLUPPAGE_KEY{ L"scrollUpPage" }; -static const wchar_t* const SCROLLDOWNPAGE_KEY{ L"scrollDownPage" }; -static const wchar_t* const SWITCHTOTAB0_KEY{ L"switchToTab0" }; -static const wchar_t* const SWITCHTOTAB1_KEY{ L"switchToTab1" }; -static const wchar_t* const SWITCHTOTAB2_KEY{ L"switchToTab2" }; -static const wchar_t* const SWITCHTOTAB3_KEY{ L"switchToTab3" }; -static const wchar_t* const SWITCHTOTAB4_KEY{ L"switchToTab4" }; -static const wchar_t* const SWITCHTOTAB5_KEY{ L"switchToTab5" }; -static const wchar_t* const SWITCHTOTAB6_KEY{ L"switchToTab6" }; -static const wchar_t* const SWITCHTOTAB7_KEY{ L"switchToTab7" }; -static const wchar_t* const SWITCHTOTAB8_KEY{ L"switchToTab8" }; -static const wchar_t* const SWITCHTOTAB9_KEY{ L"switchToTab9" }; -static const wchar_t* const OPENSETTINGS_KEY{ L"openSettings" }; +static constexpr std::wstring_view COPYTEXT_KEY{ L"copy" }; +static constexpr std::wstring_view PASTETEXT_KEY{ L"paste" }; +static constexpr std::wstring_view NEWTAB_KEY{ L"newTab" }; +static constexpr std::wstring_view NEWTABWITHPROFILE0_KEY{ L"newTabProfile0" }; +static constexpr std::wstring_view NEWTABWITHPROFILE1_KEY{ L"newTabProfile1" }; +static constexpr std::wstring_view NEWTABWITHPROFILE2_KEY{ L"newTabProfile2" }; +static constexpr std::wstring_view NEWTABWITHPROFILE3_KEY{ L"newTabProfile3" }; +static constexpr std::wstring_view NEWTABWITHPROFILE4_KEY{ L"newTabProfile4" }; +static constexpr std::wstring_view NEWTABWITHPROFILE5_KEY{ L"newTabProfile5" }; +static constexpr std::wstring_view NEWTABWITHPROFILE6_KEY{ L"newTabProfile6" }; +static constexpr std::wstring_view NEWTABWITHPROFILE7_KEY{ L"newTabProfile7" }; +static constexpr std::wstring_view NEWTABWITHPROFILE8_KEY{ L"newTabProfile8" }; +static constexpr std::wstring_view NEWTABWITHPROFILE9_KEY{ L"newTabProfile9" }; +static constexpr std::wstring_view NEWWINDOW_KEY{ L"newWindow" }; +static constexpr std::wstring_view CLOSEWINDOW_KEY{ L"closeWindow" }; +static constexpr std::wstring_view CLOSETAB_KEY{ L"closeTab" }; +static constexpr std::wstring_view SWITCHTOTAB_KEY{ L"switchToTab" }; +static constexpr std::wstring_view NEXTTAB_KEY{ L"nextTab" }; +static constexpr std::wstring_view PREVTAB_KEY{ L"prevTab" }; +static constexpr std::wstring_view INCREASEFONTSIZE_KEY{ L"increaseFontSize" }; +static constexpr std::wstring_view DECREASEFONTSIZE_KEY{ L"decreaseFontSize" }; +static constexpr std::wstring_view SCROLLUP_KEY{ L"scrollUp" }; +static constexpr std::wstring_view SCROLLDOWN_KEY{ L"scrollDown" }; +static constexpr std::wstring_view SCROLLUPPAGE_KEY{ L"scrollUpPage" }; +static constexpr std::wstring_view SCROLLDOWNPAGE_KEY{ L"scrollDownPage" }; +static constexpr std::wstring_view SWITCHTOTAB0_KEY{ L"switchToTab0" }; +static constexpr std::wstring_view SWITCHTOTAB1_KEY{ L"switchToTab1" }; +static constexpr std::wstring_view SWITCHTOTAB2_KEY{ L"switchToTab2" }; +static constexpr std::wstring_view SWITCHTOTAB3_KEY{ L"switchToTab3" }; +static constexpr std::wstring_view SWITCHTOTAB4_KEY{ L"switchToTab4" }; +static constexpr std::wstring_view SWITCHTOTAB5_KEY{ L"switchToTab5" }; +static constexpr std::wstring_view SWITCHTOTAB6_KEY{ L"switchToTab6" }; +static constexpr std::wstring_view SWITCHTOTAB7_KEY{ L"switchToTab7" }; +static constexpr std::wstring_view SWITCHTOTAB8_KEY{ L"switchToTab8" }; +static constexpr std::wstring_view SWITCHTOTAB9_KEY{ L"switchToTab9" }; +static constexpr std::wstring_view OPENSETTINGS_KEY{ L"openSettings" }; -static const std::map commandNames { - { ShortcutAction::CopyText, COPYTEXT_KEY }, - { ShortcutAction::PasteText, PASTETEXT_KEY }, - { ShortcutAction::NewTab, NEWTAB_KEY }, - { ShortcutAction::NewTabProfile0, NEWTABWITHPROFILE0_KEY }, - { ShortcutAction::NewTabProfile1, NEWTABWITHPROFILE1_KEY }, - { ShortcutAction::NewTabProfile2, NEWTABWITHPROFILE2_KEY }, - { ShortcutAction::NewTabProfile3, NEWTABWITHPROFILE3_KEY }, - { ShortcutAction::NewTabProfile4, NEWTABWITHPROFILE4_KEY }, - { ShortcutAction::NewTabProfile5, NEWTABWITHPROFILE5_KEY }, - { ShortcutAction::NewTabProfile6, NEWTABWITHPROFILE6_KEY }, - { ShortcutAction::NewTabProfile7, NEWTABWITHPROFILE7_KEY }, - { ShortcutAction::NewTabProfile8, NEWTABWITHPROFILE8_KEY }, - { ShortcutAction::NewTabProfile9, NEWTABWITHPROFILE9_KEY }, - { ShortcutAction::NewWindow, NEWWINDOW_KEY }, - { ShortcutAction::CloseWindow, CLOSEWINDOW_KEY }, - { ShortcutAction::CloseTab, CLOSETAB_KEY }, - { ShortcutAction::NextTab, NEXTTAB_KEY }, - { ShortcutAction::PrevTab, PREVTAB_KEY }, - { ShortcutAction::IncreaseFontSize, INCREASEFONTSIZE_KEY }, - { ShortcutAction::DecreaseFontSize, DECREASEFONTSIZE_KEY }, - { ShortcutAction::ScrollUp, SCROLLUP_KEY }, - { ShortcutAction::ScrollDown, SCROLLDOWN_KEY }, - { ShortcutAction::ScrollUpPage, SCROLLUPPAGE_KEY }, - { ShortcutAction::ScrollDownPage, SCROLLDOWNPAGE_KEY }, - { ShortcutAction::SwitchToTab0, SWITCHTOTAB0_KEY }, - { ShortcutAction::SwitchToTab1, SWITCHTOTAB1_KEY }, - { ShortcutAction::SwitchToTab2, SWITCHTOTAB2_KEY }, - { ShortcutAction::SwitchToTab3, SWITCHTOTAB3_KEY }, - { ShortcutAction::SwitchToTab4, SWITCHTOTAB4_KEY }, - { ShortcutAction::SwitchToTab5, SWITCHTOTAB5_KEY }, - { ShortcutAction::SwitchToTab6, SWITCHTOTAB6_KEY }, - { ShortcutAction::SwitchToTab7, SWITCHTOTAB7_KEY }, - { ShortcutAction::SwitchToTab8, SWITCHTOTAB8_KEY }, - { ShortcutAction::SwitchToTab9, SWITCHTOTAB9_KEY }, +static const std::map commandNames { + { COPYTEXT_KEY, ShortcutAction::CopyText }, + { PASTETEXT_KEY, ShortcutAction::PasteText }, + { NEWTAB_KEY, ShortcutAction::NewTab }, + { NEWTABWITHPROFILE0_KEY, ShortcutAction::NewTabProfile0 }, + { NEWTABWITHPROFILE1_KEY, ShortcutAction::NewTabProfile1 }, + { NEWTABWITHPROFILE2_KEY, ShortcutAction::NewTabProfile2 }, + { NEWTABWITHPROFILE3_KEY, ShortcutAction::NewTabProfile3 }, + { NEWTABWITHPROFILE4_KEY, ShortcutAction::NewTabProfile4 }, + { NEWTABWITHPROFILE5_KEY, ShortcutAction::NewTabProfile5 }, + { NEWTABWITHPROFILE6_KEY, ShortcutAction::NewTabProfile6 }, + { NEWTABWITHPROFILE7_KEY, ShortcutAction::NewTabProfile7 }, + { NEWTABWITHPROFILE8_KEY, ShortcutAction::NewTabProfile8 }, + { NEWTABWITHPROFILE9_KEY, ShortcutAction::NewTabProfile9 }, + { NEWWINDOW_KEY, ShortcutAction::NewWindow }, + { CLOSEWINDOW_KEY, ShortcutAction::CloseWindow }, + { CLOSETAB_KEY, ShortcutAction::CloseTab }, + { NEXTTAB_KEY, ShortcutAction::NextTab }, + { PREVTAB_KEY, ShortcutAction::PrevTab }, + { INCREASEFONTSIZE_KEY, ShortcutAction::IncreaseFontSize }, + { DECREASEFONTSIZE_KEY, ShortcutAction::DecreaseFontSize }, + { SCROLLUP_KEY, ShortcutAction::ScrollUp }, + { SCROLLDOWN_KEY, ShortcutAction::ScrollDown }, + { SCROLLUPPAGE_KEY, ShortcutAction::ScrollUpPage }, + { SCROLLDOWNPAGE_KEY, ShortcutAction::ScrollDownPage }, + { SWITCHTOTAB0_KEY, ShortcutAction::SwitchToTab0 }, + { SWITCHTOTAB1_KEY, ShortcutAction::SwitchToTab1 }, + { SWITCHTOTAB2_KEY, ShortcutAction::SwitchToTab2 }, + { SWITCHTOTAB3_KEY, ShortcutAction::SwitchToTab3 }, + { SWITCHTOTAB4_KEY, ShortcutAction::SwitchToTab4 }, + { SWITCHTOTAB5_KEY, ShortcutAction::SwitchToTab5 }, + { SWITCHTOTAB6_KEY, ShortcutAction::SwitchToTab6 }, + { SWITCHTOTAB7_KEY, ShortcutAction::SwitchToTab7 }, + { SWITCHTOTAB8_KEY, ShortcutAction::SwitchToTab8 }, + { SWITCHTOTAB9_KEY, ShortcutAction::SwitchToTab9 }, }; namespace winrt::TerminalApp::implementation @@ -265,24 +266,18 @@ namespace winrt::TerminalApp::implementation } const auto keyChordString = keys.GetAt(0).GetString(); ShortcutAction action; - bool parsedSuccessfully = false; + // Try matching the command to one we have - for (const auto& pair : commandNames) + if (commandNames.find(commandString) != commandNames.end()) { - if (pair.second == commandString) - { - action = pair.first; - parsedSuccessfully = true; - break; - } + action = commandNames.at(commandString); } - if (!parsedSuccessfully) + else { continue; } + // Try parsing the chord - Settings::KeyChord chord{ false, false, false, 0 }; - parsedSuccessfully = false; try { chord = Settings::KeyChord::FromString(keyChordString); @@ -292,10 +287,6 @@ namespace winrt::TerminalApp::implementation { continue; } - if (parsedSuccessfully) - { - newBindings.SetKeyBinding(action, chord); - } } } } @@ -309,9 +300,9 @@ namespace winrt::TerminalApp::implementation // - bindingsArray: The JsonArray to insert the object into. // - chord: The KeyChord to serailize and place in the json array // - actionName: the name of the ShortcutAction to use with this KeyChord - void _AddShortcutToJsonArray(JsonArray bindingsArray, - const Settings::KeyChord& chord, - const std::wstring_view& actionName) + static void _AddShortcutToJsonArray(const JsonArray& bindingsArray, + const Settings::KeyChord& chord, + const std::wstring_view& actionName) { const auto keyString = chord.ToString(); if (keyString == L"") @@ -342,8 +333,8 @@ namespace winrt::TerminalApp::implementation // it has a binding. for (auto& actionName : commandNames) { - const auto searchedForAction = actionName.first; - const auto searchedForName = actionName.second; + const auto searchedForName = actionName.first; + const auto searchedForAction = actionName.second; for (const auto& kv : _keyShortcuts) { const auto chord = kv.first; diff --git a/src/cascadia/TerminalSettings/KeyChord.cpp b/src/cascadia/TerminalSettings/KeyChord.cpp index 5447ee677ba..2adbc27b82a 100644 --- a/src/cascadia/TerminalSettings/KeyChord.cpp +++ b/src/cascadia/TerminalSettings/KeyChord.cpp @@ -117,167 +117,4 @@ namespace winrt::Microsoft::Terminal::Settings::implementation { _vkey = value; } - - // Method Description: - // - Deserializes the given string into a new KeyChord instance. If this - // fails to translate the string into a keychord, it will throw a - // hresult_invalid_argument exception. - // - The string should fit the format "[ctrl+][alt+][shift+]", - // where each modifier is optional, and keyName is either one of the - // names listed in the vkeyNamePairs vector above, or is one of 0-9a-zA-Z. - // Arguments: - // - hstr: the string to parse into a keychord. - // Return Value: - // - a newly constructed KeyChord - winrt::Microsoft::Terminal::Settings::KeyChord KeyChord::FromString(const hstring& hstr) - { - std::wstring wstr{ hstr }; - - // Split the string on '+' - std::wstring temp; - std::vector parts; - std::wstringstream wss(wstr); - - while(std::getline(wss, temp, L'+')) - { - parts.push_back(temp); - - // If we have > 4, something's wrong. - if (parts.size() > MAX_CHORD_PARTS) - { - throw hresult_invalid_argument(); - } - } - - KeyModifiers modifiers = KeyModifiers::None; - int32_t vkey = 0; - - // Look for ctrl, shift, alt. Anything else might be a key - for (const auto& part : parts) - { - std::wstring lowercase = part; - std::transform(lowercase.begin(), lowercase.end(), lowercase.begin(), std::towlower); - if (lowercase == CTRL_KEY) - { - modifiers |= KeyModifiers::Ctrl; - } - else if (lowercase == ALT_KEY) - { - modifiers |= KeyModifiers::Alt; - } - else if (lowercase == SHIFT_KEY) - { - modifiers |= KeyModifiers::Shift; - } - else - { - bool foundKey = false; - // For potential keys, look through the pairs of strings and vkeys - if (part.size() == 1) - { - const wchar_t wch = part[0]; - // Quick lookup: ranges of vkeys that correlate directly to a key. - if (wch >= L'0' && wch <= L'9') - { - vkey = static_cast(wch); - foundKey = true; - } - else if (wch >= L'a' && wch <= L'z') - { - // subtract 0x20 to shift to uppercase - vkey = static_cast(wch - 0x20); - foundKey = true; - } - else if (wch >= L'A' && wch <= L'Z') - { - vkey = static_cast(wch); - foundKey = true; - } - } - - // If we didn't find the key with a quick lookup, search the - // table to see if we have a matching name. - if (!foundKey) - { - for (const auto& pair : vkeyNamePairs) - { - if (pair.second == part) - { - vkey = pair.first; - foundKey = true; - break; - } - } - } - - // If we weren't able to find a match, throw an exception. - if (!foundKey) - { - throw hresult_invalid_argument(); - } - } - } - - return winrt::Microsoft::Terminal::Settings::KeyChord{ modifiers, vkey }; - } - - // Method Description: - // - Serialize this keychord into a string represenation. - // - The string will fit the format "[ctrl+][alt+][shift+]", - // where each modifier is optional, and keyName is either one of the - // names listed in the vkeyNamePairs vector above, or is one of 0-9a-z. - // Return Value: - // - a string which is an equivalent serialization of this object. - hstring KeyChord::ToString() - { - bool serializedSuccessfully = false; - - std::wstring buffer{ L"" }; - - // Add modifiers - if (WI_IsFlagSet(_modifiers, Settings::KeyModifiers::Ctrl)) - { - buffer += CTRL_KEY; - buffer += L"+"; - } - if (WI_IsFlagSet(_modifiers, Settings::KeyModifiers::Alt)) - { - buffer += ALT_KEY; - buffer += L"+"; - } - if (WI_IsFlagSet(_modifiers, Settings::KeyModifiers::Shift)) - { - buffer += SHIFT_KEY; - buffer += L"+"; - } - - // Quick lookup: ranges of vkeys that correlate directly to a key. - if (_vkey >= L'0' && _vkey <= L'9') - { - buffer += std::wstring(1, static_cast(_vkey)); - serializedSuccessfully = true; - } - else if (_vkey >= L'A' && _vkey <= L'Z') - { - // add 0x20 to shift to lowercase - buffer += std::wstring(1, static_cast(_vkey + 0x20)); - serializedSuccessfully = true; - } - else - { - if (vkeyNamePairs.find(_vkey) != vkeyNamePairs.end()) - { - buffer += vkeyNamePairs.at(_vkey); - serializedSuccessfully = true; - } - } - - if (!serializedSuccessfully) - { - buffer = L""; - } - - return winrt::hstring{ buffer }; - } - } From 7aee31a44f42683c6f4a4b67207f1d9e298e86e5 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 15 May 2019 17:16:58 -0500 Subject: [PATCH 09/10] Move the serialization of keychords into a seperate file. --- src/cascadia/TerminalApp/AppKeyBindings.cpp | 6 +- .../TerminalApp/KeyChordSerialization.cpp | 249 ++++++++++++++++++ .../TerminalApp/KeyChordSerialization.h | 12 + src/cascadia/TerminalApp/TerminalApp.vcxproj | 4 +- src/cascadia/TerminalSettings/KeyChord.cpp | 78 ------ src/cascadia/TerminalSettings/KeyChord.h | 3 - src/cascadia/TerminalSettings/KeyChord.idl | 3 - 7 files changed, 267 insertions(+), 88 deletions(-) create mode 100644 src/cascadia/TerminalApp/KeyChordSerialization.cpp create mode 100644 src/cascadia/TerminalApp/KeyChordSerialization.h diff --git a/src/cascadia/TerminalApp/AppKeyBindings.cpp b/src/cascadia/TerminalApp/AppKeyBindings.cpp index 194257ad993..0aa93166c93 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindings.cpp @@ -280,8 +280,8 @@ namespace winrt::TerminalApp::implementation // Try parsing the chord try { - chord = Settings::KeyChord::FromString(keyChordString); - parsedSuccessfully = true; + auto chord = KeyChordSerialization::FromString(keyChordString); + newBindings.SetKeyBinding(action, chord); } catch (...) { @@ -304,7 +304,7 @@ namespace winrt::TerminalApp::implementation const Settings::KeyChord& chord, const std::wstring_view& actionName) { - const auto keyString = chord.ToString(); + const auto keyString = KeyChordSerialization::ToString(chord); if (keyString == L"") { return; diff --git a/src/cascadia/TerminalApp/KeyChordSerialization.cpp b/src/cascadia/TerminalApp/KeyChordSerialization.cpp new file mode 100644 index 00000000000..8cf7ecc509d --- /dev/null +++ b/src/cascadia/TerminalApp/KeyChordSerialization.cpp @@ -0,0 +1,249 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "KeyChordSerialization.h" + +using namespace winrt::Microsoft::Terminal::Settings; + +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 int MAX_CHORD_PARTS = 4; + +static const std::unordered_map vkeyNamePairs { + { VK_BACK , L"backspace"}, + { VK_TAB , L"tab"}, + { VK_RETURN , L"enter" }, + { VK_ESCAPE , L"esc" }, + { VK_SPACE , L"space" }, + { VK_PRIOR , L"pgup" }, + { VK_NEXT , L"pgdn" }, + { VK_END , L"end" }, + { VK_HOME , L"home" }, + { VK_LEFT , L"left" }, + { VK_UP , L"up" }, + { VK_RIGHT , L"right" }, + { VK_DOWN , L"down" }, + { VK_INSERT , L"insert" }, + { VK_DELETE , L"delete" }, + { VK_NUMPAD0 , L"numpad_0" }, + { VK_NUMPAD1 , L"numpad_1" }, + { VK_NUMPAD2 , L"numpad_2" }, + { VK_NUMPAD3 , L"numpad_3" }, + { VK_NUMPAD4 , L"numpad_4" }, + { VK_NUMPAD5 , L"numpad_5" }, + { VK_NUMPAD6 , L"numpad_6" }, + { VK_NUMPAD7 , L"numpad_7" }, + { VK_NUMPAD8 , L"numpad_8" }, + { VK_NUMPAD9 , L"numpad_9" }, + { VK_MULTIPLY , L"numpad_multiply" }, + { VK_ADD , L"numpad_plus" }, + { VK_SUBTRACT , L"numpad_minus" }, + { VK_DECIMAL , L"numpad_period" }, + { VK_DIVIDE , L"numpad_divide" }, + { VK_F1 , L"f1" }, + { VK_F2 , L"f2" }, + { VK_F3 , L"f3" }, + { VK_F4 , L"f4" }, + { VK_F5 , L"f5" }, + { VK_F6 , L"f6" }, + { VK_F7 , L"f7" }, + { VK_F8 , L"f8" }, + { VK_F9 , L"f9" }, + { VK_F10 , L"f10" }, + { VK_F11 , L"f11" }, + { VK_F12 , L"f12" }, + { VK_F13 , L"f13" }, + { VK_F14 , L"f14" }, + { VK_F15 , L"f15" }, + { VK_F16 , L"f16" }, + { VK_F17 , L"f17" }, + { VK_F18 , L"f18" }, + { VK_F19 , L"f19" }, + { VK_F20 , L"f20" }, + { VK_F21 , L"f21" }, + { VK_F22 , L"f22" }, + { VK_F23 , L"f23" }, + { VK_F24 , L"f24" }, + { VK_OEM_PLUS , L"plus" }, + { VK_OEM_COMMA , L"," }, + { VK_OEM_MINUS , L"-" }, + { VK_OEM_PERIOD , L"." } +// TODO: +// These all look like they'd be good keybindings, but change based on keyboard +// layout. How do we deal with that? +// #define VK_OEM_NEC_EQUAL 0x92 // '=' key on numpad +// #define VK_OEM_1 0xBA // ';:' for US +// #define VK_OEM_2 0xBF // '/?' for US +// #define VK_OEM_3 0xC0 // '`~' for US +// #define VK_OEM_4 0xDB // '[{' for US +// #define VK_OEM_5 0xDC // '\|' for US +// #define VK_OEM_6 0xDD // ']}' for US +// #define VK_OEM_7 0xDE // ''"' for US +}; + +// Function Description: +// - Deserializes the given string into a new KeyChord instance. If this +// fails to translate the string into a keychord, it will throw a +// hresult_invalid_argument exception. +// - The string should fit the format "[ctrl+][alt+][shift+]", +// where each modifier is optional, and keyName is either one of the +// names listed in the vkeyNamePairs vector above, or is one of 0-9a-zA-Z. +// Arguments: +// - hstr: the string to parse into a keychord. +// Return Value: +// - a newly constructed KeyChord +winrt::Microsoft::Terminal::Settings::KeyChord KeyChordSerialization::FromString(const winrt::hstring& hstr) +{ + std::wstring wstr{ hstr }; + + // Split the string on '+' + std::wstring temp; + std::vector parts; + std::wstringstream wss(wstr); + + while(std::getline(wss, temp, L'+')) + { + parts.push_back(temp); + + // If we have > 4, something's wrong. + if (parts.size() > MAX_CHORD_PARTS) + { + throw winrt::hresult_invalid_argument(); + } + } + + KeyModifiers modifiers = KeyModifiers::None; + int32_t vkey = 0; + + // Look for ctrl, shift, alt. Anything else might be a key + for (const auto& part : parts) + { + std::wstring lowercase = part; + std::transform(lowercase.begin(), lowercase.end(), lowercase.begin(), std::towlower); + if (lowercase == CTRL_KEY) + { + modifiers |= KeyModifiers::Ctrl; + } + else if (lowercase == ALT_KEY) + { + modifiers |= KeyModifiers::Alt; + } + else if (lowercase == SHIFT_KEY) + { + modifiers |= KeyModifiers::Shift; + } + else + { + bool foundKey = false; + // For potential keys, look through the pairs of strings and vkeys + if (part.size() == 1) + { + const wchar_t wch = part[0]; + // Quick lookup: ranges of vkeys that correlate directly to a key. + if (wch >= L'0' && wch <= L'9') + { + vkey = static_cast(wch); + foundKey = true; + } + else if (wch >= L'a' && wch <= L'z') + { + // subtract 0x20 to shift to uppercase + vkey = static_cast(wch - 0x20); + foundKey = true; + } + else if (wch >= L'A' && wch <= L'Z') + { + vkey = static_cast(wch); + foundKey = true; + } + } + + // If we didn't find the key with a quick lookup, search the + // table to see if we have a matching name. + if (!foundKey) + { + for (const auto& pair : vkeyNamePairs) + { + if (pair.second == part) + { + vkey = pair.first; + foundKey = true; + break; + } + } + } + + // If we weren't able to find a match, throw an exception. + if (!foundKey) + { + throw winrt::hresult_invalid_argument(); + } + } + } + + return winrt::Microsoft::Terminal::Settings::KeyChord{ modifiers, vkey }; +} + +// Function Description: +// - Serialize this keychord into a string represenation. +// - The string will fit the format "[ctrl+][alt+][shift+]", +// where each modifier is optional, and keyName is either one of the +// names listed in the vkeyNamePairs vector above, or is one of 0-9a-z. +// Return Value: +// - a string which is an equivalent serialization of this object. +winrt::hstring KeyChordSerialization::ToString(const KeyChord& chord) +{ + bool serializedSuccessfully = false; + const auto modifiers = chord.Modifiers(); + const auto vkey = chord.Vkey(); + + std::wstring buffer{ L"" }; + + // Add modifiers + if (WI_IsFlagSet(modifiers, KeyModifiers::Ctrl)) + { + buffer += CTRL_KEY; + buffer += L"+"; + } + if (WI_IsFlagSet(modifiers, KeyModifiers::Alt)) + { + buffer += ALT_KEY; + buffer += L"+"; + } + if (WI_IsFlagSet(modifiers, KeyModifiers::Shift)) + { + buffer += SHIFT_KEY; + buffer += L"+"; + } + + // Quick lookup: ranges of vkeys that correlate directly to a key. + if (vkey >= L'0' && vkey <= L'9') + { + buffer += std::wstring(1, static_cast(vkey)); + serializedSuccessfully = true; + } + else if (vkey >= L'A' && vkey <= L'Z') + { + // add 0x20 to shift to lowercase + buffer += std::wstring(1, static_cast(vkey + 0x20)); + serializedSuccessfully = true; + } + else + { + if (vkeyNamePairs.find(vkey) != vkeyNamePairs.end()) + { + buffer += vkeyNamePairs.at(vkey); + serializedSuccessfully = true; + } + } + + if (!serializedSuccessfully) + { + buffer = L""; + } + + return winrt::hstring{ buffer }; +} diff --git a/src/cascadia/TerminalApp/KeyChordSerialization.h b/src/cascadia/TerminalApp/KeyChordSerialization.h new file mode 100644 index 00000000000..8f9cf4f26ee --- /dev/null +++ b/src/cascadia/TerminalApp/KeyChordSerialization.h @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once +#include + +class KeyChordSerialization final +{ +public: + static winrt::Microsoft::Terminal::Settings::KeyChord FromString(const winrt::hstring& str); + static winrt::hstring ToString(const winrt::Microsoft::Terminal::Settings::KeyChord& chord); +}; diff --git a/src/cascadia/TerminalApp/TerminalApp.vcxproj b/src/cascadia/TerminalApp/TerminalApp.vcxproj index 6a70d00dda9..0aa7e8fb1f8 100644 --- a/src/cascadia/TerminalApp/TerminalApp.vcxproj +++ b/src/cascadia/TerminalApp/TerminalApp.vcxproj @@ -41,6 +41,7 @@ + AppKeyBindings.idl @@ -58,6 +59,7 @@ + Create @@ -128,4 +130,4 @@ - \ No newline at end of file + diff --git a/src/cascadia/TerminalSettings/KeyChord.cpp b/src/cascadia/TerminalSettings/KeyChord.cpp index 2adbc27b82a..96e771acbcc 100644 --- a/src/cascadia/TerminalSettings/KeyChord.cpp +++ b/src/cascadia/TerminalSettings/KeyChord.cpp @@ -4,84 +4,6 @@ #include "pch.h" #include "KeyChord.h" -static const wchar_t* const CTRL_KEY{ L"ctrl" }; -static const wchar_t* const SHIFT_KEY{ L"shift" }; -static const wchar_t* const ALT_KEY{ L"alt" }; - -static constexpr int MAX_CHORD_PARTS = 4; - -static const std::unordered_map vkeyNamePairs { - { VK_BACK , L"backspace"}, - { VK_TAB , L"tab"}, - { VK_RETURN , L"enter" }, - { VK_ESCAPE , L"esc" }, - { VK_SPACE , L"space" }, - { VK_PRIOR , L"pgup" }, - { VK_NEXT , L"pgdn" }, - { VK_END , L"end" }, - { VK_HOME , L"home" }, - { VK_LEFT , L"left" }, - { VK_UP , L"up" }, - { VK_RIGHT , L"right" }, - { VK_DOWN , L"down" }, - { VK_INSERT , L"insert" }, - { VK_DELETE , L"delete" }, - { VK_NUMPAD0 , L"numpad_0" }, - { VK_NUMPAD1 , L"numpad_1" }, - { VK_NUMPAD2 , L"numpad_2" }, - { VK_NUMPAD3 , L"numpad_3" }, - { VK_NUMPAD4 , L"numpad_4" }, - { VK_NUMPAD5 , L"numpad_5" }, - { VK_NUMPAD6 , L"numpad_6" }, - { VK_NUMPAD7 , L"numpad_7" }, - { VK_NUMPAD8 , L"numpad_8" }, - { VK_NUMPAD9 , L"numpad_9" }, - { VK_MULTIPLY , L"numpad_multiply" }, - { VK_ADD , L"numpad_plus" }, - { VK_SUBTRACT , L"numpad_minus" }, - { VK_DECIMAL , L"numpad_period" }, - { VK_DIVIDE , L"numpad_divide" }, - { VK_F1 , L"f1" }, - { VK_F2 , L"f2" }, - { VK_F3 , L"f3" }, - { VK_F4 , L"f4" }, - { VK_F5 , L"f5" }, - { VK_F6 , L"f6" }, - { VK_F7 , L"f7" }, - { VK_F8 , L"f8" }, - { VK_F9 , L"f9" }, - { VK_F10 , L"f10" }, - { VK_F11 , L"f11" }, - { VK_F12 , L"f12" }, - { VK_F13 , L"f13" }, - { VK_F14 , L"f14" }, - { VK_F15 , L"f15" }, - { VK_F16 , L"f16" }, - { VK_F17 , L"f17" }, - { VK_F18 , L"f18" }, - { VK_F19 , L"f19" }, - { VK_F20 , L"f20" }, - { VK_F21 , L"f21" }, - { VK_F22 , L"f22" }, - { VK_F23 , L"f23" }, - { VK_F24 , L"f24" }, - { VK_OEM_PLUS , L"plus" }, - { VK_OEM_COMMA , L"," }, - { VK_OEM_MINUS , L"-" }, - { VK_OEM_PERIOD , L"." } -// TODO: -// These all look like they'd be good keybindings, but change based on keyboard -// layout. How do we deal with that? -// #define VK_OEM_NEC_EQUAL 0x92 // '=' key on numpad -// #define VK_OEM_1 0xBA // ';:' for US -// #define VK_OEM_2 0xBF // '/?' for US -// #define VK_OEM_3 0xC0 // '`~' for US -// #define VK_OEM_4 0xDB // '[{' for US -// #define VK_OEM_5 0xDC // '\|' for US -// #define VK_OEM_6 0xDD // ']}' for US -// #define VK_OEM_7 0xDE // ''"' for US -}; - namespace winrt::Microsoft::Terminal::Settings::implementation { KeyChord::KeyChord(bool ctrl, bool alt, bool shift, int32_t vkey) : diff --git a/src/cascadia/TerminalSettings/KeyChord.h b/src/cascadia/TerminalSettings/KeyChord.h index cc32cff6aca..61456b25726 100644 --- a/src/cascadia/TerminalSettings/KeyChord.h +++ b/src/cascadia/TerminalSettings/KeyChord.h @@ -13,9 +13,6 @@ namespace winrt::Microsoft::Terminal::Settings::implementation KeyChord(Settings::KeyModifiers const& modifiers, int32_t vkey); KeyChord(bool ctrl, bool alt, bool shift, int32_t vkey); - static Terminal::Settings::KeyChord FromString(const winrt::hstring& str); - winrt::hstring ToString(); - Settings::KeyModifiers Modifiers(); void Modifiers(Settings::KeyModifiers const& value); int32_t Vkey(); diff --git a/src/cascadia/TerminalSettings/KeyChord.idl b/src/cascadia/TerminalSettings/KeyChord.idl index 89ae5a15b15..c02459144b3 100644 --- a/src/cascadia/TerminalSettings/KeyChord.idl +++ b/src/cascadia/TerminalSettings/KeyChord.idl @@ -19,9 +19,6 @@ namespace Microsoft.Terminal.Settings KeyChord(KeyModifiers modifiers, Int32 vkey); KeyChord(Boolean ctrl, Boolean alt, Boolean shift, Int32 vkey); - String ToString(); - static KeyChord FromString(String str); - KeyModifiers Modifiers; Int32 Vkey; } From f13d343419042b9b1b01831ded4126787f5470f4 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 20 May 2019 14:28:45 -0500 Subject: [PATCH 10/10] Some minor PR nits --- src/cascadia/TerminalApp/AppKeyBindings.cpp | 10 ++++++++-- src/cascadia/TerminalApp/KeyChordSerialization.cpp | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/cascadia/TerminalApp/AppKeyBindings.cpp b/src/cascadia/TerminalApp/AppKeyBindings.cpp index 0aa93166c93..c181ea3902f 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindings.cpp @@ -49,6 +49,8 @@ static constexpr std::wstring_view SWITCHTOTAB8_KEY{ L"switchToTab8" }; static constexpr std::wstring_view SWITCHTOTAB9_KEY{ L"switchToTab9" }; static constexpr std::wstring_view OPENSETTINGS_KEY{ L"openSettings" }; +// Specifically use a map here over an unordered_map. We want to be able to +// iterate over these entries in-order when we're serializing the keybindings. static const std::map commandNames { { COPYTEXT_KEY, ShortcutAction::CopyText }, { PASTETEXT_KEY, ShortcutAction::PasteText }, @@ -213,6 +215,9 @@ namespace winrt::TerminalApp::implementation case ShortcutAction::SwitchToTab9: _SwitchToTabHandlers(9); return true; + + default: + return false; } return false; } @@ -268,9 +273,10 @@ namespace winrt::TerminalApp::implementation ShortcutAction action; // Try matching the command to one we have - if (commandNames.find(commandString) != commandNames.end()) + auto found = commandNames.find(commandString); + if (found != commandNames.end()) { - action = commandNames.at(commandString); + action = found->second; } else { diff --git a/src/cascadia/TerminalApp/KeyChordSerialization.cpp b/src/cascadia/TerminalApp/KeyChordSerialization.cpp index 8cf7ecc509d..20816066a62 100644 --- a/src/cascadia/TerminalApp/KeyChordSerialization.cpp +++ b/src/cascadia/TerminalApp/KeyChordSerialization.cpp @@ -141,7 +141,7 @@ winrt::Microsoft::Terminal::Settings::KeyChord KeyChordSerialization::FromString // For potential keys, look through the pairs of strings and vkeys if (part.size() == 1) { - const wchar_t wch = part[0]; + const wchar_t wch = part.at(0); // Quick lookup: ranges of vkeys that correlate directly to a key. if (wch >= L'0' && wch <= L'9') {