diff --git a/src/cascadia/LocalTests_SettingsModel/KeyBindingsTests.cpp b/src/cascadia/LocalTests_SettingsModel/KeyBindingsTests.cpp index 35fde481b..bc0a21f72 100644 --- a/src/cascadia/LocalTests_SettingsModel/KeyBindingsTests.cpp +++ b/src/cascadia/LocalTests_SettingsModel/KeyBindingsTests.cpp @@ -647,10 +647,12 @@ namespace SettingsModelLocalTests const std::string bindings0String{ R"([ { "command": "closeWindow", "keys": "ctrl+a" } ])" }; const std::string bindings1String{ R"([ { "command": { "action": "copy", "singleLine": true }, "keys": "ctrl+b" } ])" }; const std::string bindings2String{ R"([ { "command": { "action": "newTab", "index": 0 }, "keys": "ctrl+c" } ])" }; + const std::string bindings3String{ R"([ { "command": "commandPalette", "keys": "ctrl+shift+p" } ])" }; const auto bindings0Json = VerifyParseSucceeded(bindings0String); const auto bindings1Json = VerifyParseSucceeded(bindings1String); const auto bindings2Json = VerifyParseSucceeded(bindings2String); + const auto bindings3Json = VerifyParseSucceeded(bindings3String); auto VerifyKeyChordEquality = [](const KeyChord& expected, const KeyChord& actual) { if (expected) @@ -699,5 +701,13 @@ namespace SettingsModelLocalTests const auto& kbd{ actionMap->GetKeyBindingForAction(ShortcutAction::NewTab, *args) }; VerifyKeyChordEquality({ KeyModifiers::Ctrl, static_cast('C') }, kbd); } + { + Log::Comment(L"command with hidden args"); + actionMap->LayerJson(bindings3Json); + VERIFY_ARE_EQUAL(4u, actionMap->_KeyMap.size()); + + const auto& kbd{ actionMap->GetKeyBindingForAction(ShortcutAction::ToggleCommandPalette) }; + VerifyKeyChordEquality({ KeyModifiers::Ctrl | KeyModifiers::Shift, static_cast('P') }, kbd); + } } } diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.h b/src/cascadia/TerminalSettingsModel/ActionArgs.h index 6cf7d8cb5..280ac9ac1 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.h +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.h @@ -68,6 +68,15 @@ constexpr size_t Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(c return gsl::narrow_cast(args.Hash()); } +// Retrieves the hash value for an empty-constructed object. +template +static size_t EmptyHash() +{ + // cache the value of the empty hash + static const size_t cachedHash = winrt::make_self()->Hash(); + return cachedHash; +} + namespace winrt::Microsoft::Terminal::Settings::Model::implementation { using namespace ::Microsoft::Terminal::Settings::Model; diff --git a/src/cascadia/TerminalSettingsModel/ActionMap.cpp b/src/cascadia/TerminalSettingsModel/ActionMap.cpp index a9ab094e7..5decbab3d 100644 --- a/src/cascadia/TerminalSettingsModel/ActionMap.cpp +++ b/src/cascadia/TerminalSettingsModel/ActionMap.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "AllShortcutActions.h" #include "ActionMap.h" #include "ActionMap.g.cpp" @@ -18,12 +19,29 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation size_t hashedArgs{}; if (const auto& args{ actionAndArgs.Args() }) { + // Args are defined, so hash them hashedArgs = gsl::narrow_cast(args.Hash()); } else { - std::hash argsHash; - hashedArgs = argsHash(nullptr); + // Args are not defined. + // Check if the ShortcutAction supports args. + switch (actionAndArgs.Action()) + { +#define ON_ALL_ACTIONS_WITH_ARGS(action) \ + case ShortcutAction::action: \ + /* If it does, hash the default values for the args.*/ \ + hashedArgs = EmptyHash(); \ + break; + ALL_SHORTCUT_ACTIONS_WITH_ARGS +#undef ON_ALL_ACTIONS_WITH_ARGS + default: + { + // Otherwise, hash nullptr. + std::hash argsHash; + hashedArgs = argsHash(nullptr); + } + } } return hashedAction ^ hashedArgs; }