// Copyright (c) Microsoft Corporation. // Licensed under the MIT license. #include "pch.h" #include "GlobalAppSettings.h" #include "../../types/inc/Utils.hpp" #include "../../inc/DefaultSettings.h" #include "JsonUtils.h" #include "TerminalSettingsSerializationHelpers.h" #include "KeyChordSerialization.h" #include "GlobalAppSettings.g.cpp" using namespace Microsoft::Terminal::Settings::Model; using namespace winrt::Microsoft::Terminal::Settings::Model::implementation; using namespace winrt::Windows::UI::Xaml; using namespace ::Microsoft::Console; using namespace winrt::Microsoft::UI::Xaml::Controls; static constexpr std::string_view LegacyKeybindingsKey{ "keybindings" }; static constexpr std::string_view ActionsKey{ "actions" }; static constexpr std::string_view DefaultProfileKey{ "defaultProfile" }; static constexpr std::string_view AlwaysShowTabsKey{ "alwaysShowTabs" }; static constexpr std::string_view InitialRowsKey{ "initialRows" }; static constexpr std::string_view InitialColsKey{ "initialCols" }; static constexpr std::string_view InitialPositionKey{ "initialPosition" }; static constexpr std::string_view CenterOnLaunchKey{ "centerOnLaunch" }; static constexpr std::string_view ShowTitleInTitlebarKey{ "showTerminalTitleInTitlebar" }; static constexpr std::string_view LanguageKey{ "language" }; static constexpr std::string_view ThemeKey{ "theme" }; static constexpr std::string_view TabWidthModeKey{ "tabWidthMode" }; static constexpr std::string_view ShowTabsInTitlebarKey{ "showTabsInTitlebar" }; static constexpr std::string_view WordDelimitersKey{ "wordDelimiters" }; static constexpr std::string_view InputServiceWarningKey{ "inputServiceWarning" }; static constexpr std::string_view CopyOnSelectKey{ "copyOnSelect" }; static constexpr std::string_view CopyFormattingKey{ "copyFormatting" }; static constexpr std::string_view WarnAboutLargePasteKey{ "largePasteWarning" }; static constexpr std::string_view WarnAboutMultiLinePasteKey{ "multiLinePasteWarning" }; static constexpr std::string_view LaunchModeKey{ "launchMode" }; static constexpr std::string_view ConfirmCloseAllKey{ "confirmCloseAllTabs" }; static constexpr std::string_view SnapToGridOnResizeKey{ "snapToGridOnResize" }; static constexpr std::string_view EnableStartupTaskKey{ "startOnUserLogin" }; static constexpr std::string_view AlwaysOnTopKey{ "alwaysOnTop" }; static constexpr std::string_view LegacyUseTabSwitcherModeKey{ "useTabSwitcher" }; static constexpr std::string_view TabSwitcherModeKey{ "tabSwitcherMode" }; static constexpr std::string_view DisableAnimationsKey{ "disableAnimations" }; static constexpr std::string_view StartupActionsKey{ "startupActions" }; static constexpr std::string_view FocusFollowMouseKey{ "focusFollowMouse" }; static constexpr std::string_view WindowingBehaviorKey{ "windowingBehavior" }; static constexpr std::string_view TrimBlockSelectionKey{ "trimBlockSelection" }; static constexpr std::string_view DebugFeaturesKey{ "debugFeatures" }; static constexpr std::string_view ForceFullRepaintRenderingKey{ "experimental.rendering.forceFullRepaint" }; static constexpr std::string_view SoftwareRenderingKey{ "experimental.rendering.software" }; static constexpr std::string_view ForceVTInputKey{ "experimental.input.forceVT" }; static constexpr std::string_view DetectURLsKey{ "experimental.detectURLs" }; #ifdef _DEBUG static constexpr bool debugFeaturesDefault{ true }; #else static constexpr bool debugFeaturesDefault{ false }; #endif bool GlobalAppSettings::_getDefaultDebugFeaturesValue() { return debugFeaturesDefault; } GlobalAppSettings::GlobalAppSettings() : _actionMap{ winrt::make_self() }, _keybindingsWarnings{}, _validDefaultProfile{ false }, _defaultProfile{} { _colorSchemes = winrt::single_threaded_map(); } // Method Description: // - Copies any extraneous data from the parent before completing a CreateChild call // Arguments: // - // Return Value: // - void GlobalAppSettings::_FinalizeInheritance() { // Globals only ever has 1 parent FAIL_FAST_IF(_parents.size() > 1); for (auto parent : _parents) { _actionMap->InsertParent(parent->_actionMap); _keybindingsWarnings = std::move(parent->_keybindingsWarnings); _colorSchemes = std::move(parent->_colorSchemes); } } winrt::com_ptr GlobalAppSettings::Copy() const { auto globals{ winrt::make_self() }; globals->_InitialRows = _InitialRows; globals->_InitialCols = _InitialCols; globals->_AlwaysShowTabs = _AlwaysShowTabs; globals->_ShowTitleInTitlebar = _ShowTitleInTitlebar; globals->_ConfirmCloseAllTabs = _ConfirmCloseAllTabs; globals->_Language = _Language; globals->_Theme = _Theme; globals->_TabWidthMode = _TabWidthMode; globals->_ShowTabsInTitlebar = _ShowTabsInTitlebar; globals->_WordDelimiters = _WordDelimiters; globals->_InputServiceWarning = _InputServiceWarning; globals->_CopyOnSelect = _CopyOnSelect; globals->_CopyFormatting = _CopyFormatting; globals->_WarnAboutLargePaste = _WarnAboutLargePaste; globals->_WarnAboutMultiLinePaste = _WarnAboutMultiLinePaste; globals->_InitialPosition = _InitialPosition; globals->_CenterOnLaunch = _CenterOnLaunch; globals->_LaunchMode = _LaunchMode; globals->_SnapToGridOnResize = _SnapToGridOnResize; globals->_ForceFullRepaintRendering = _ForceFullRepaintRendering; globals->_SoftwareRendering = _SoftwareRendering; globals->_ForceVTInput = _ForceVTInput; globals->_DebugFeaturesEnabled = _DebugFeaturesEnabled; globals->_StartOnUserLogin = _StartOnUserLogin; globals->_AlwaysOnTop = _AlwaysOnTop; globals->_TabSwitcherMode = _TabSwitcherMode; globals->_DisableAnimations = _DisableAnimations; globals->_StartupActions = _StartupActions; globals->_FocusFollowMouse = _FocusFollowMouse; globals->_WindowingBehavior = _WindowingBehavior; globals->_TrimBlockSelection = _TrimBlockSelection; globals->_DetectURLs = _DetectURLs; globals->_UnparsedDefaultProfile = _UnparsedDefaultProfile; globals->_validDefaultProfile = _validDefaultProfile; globals->_defaultProfile = _defaultProfile; globals->_actionMap = _actionMap->Copy(); std::copy(_keybindingsWarnings.begin(), _keybindingsWarnings.end(), std::back_inserter(globals->_keybindingsWarnings)); if (_colorSchemes) { for (auto kv : _colorSchemes) { const auto schemeImpl{ winrt::get_self(kv.Value()) }; globals->_colorSchemes.Insert(kv.Key(), *schemeImpl->Copy()); } } // Globals only ever has 1 parent FAIL_FAST_IF(_parents.size() > 1); for (auto parent : _parents) { globals->InsertParent(parent->Copy()); } return globals; } winrt::Windows::Foundation::Collections::IMapView GlobalAppSettings::ColorSchemes() noexcept { return _colorSchemes.GetView(); } #pragma region DefaultProfile void GlobalAppSettings::DefaultProfile(const winrt::guid& defaultProfile) noexcept { _validDefaultProfile = true; _defaultProfile = defaultProfile; _UnparsedDefaultProfile = Utils::GuidToString(defaultProfile); } winrt::guid GlobalAppSettings::DefaultProfile() const { // If we have an unresolved default profile, we should likely explode. THROW_HR_IF(E_INVALIDARG, !_validDefaultProfile); return _defaultProfile; } bool GlobalAppSettings::HasUnparsedDefaultProfile() const { return _UnparsedDefaultProfile.has_value(); } winrt::hstring GlobalAppSettings::UnparsedDefaultProfile() const { const auto val{ _getUnparsedDefaultProfileImpl() }; return val ? *val : hstring{ L"" }; } void GlobalAppSettings::UnparsedDefaultProfile(const hstring& value) { if (_UnparsedDefaultProfile != value) { _UnparsedDefaultProfile = value; _validDefaultProfile = false; } } void GlobalAppSettings::ClearUnparsedDefaultProfile() { if (HasUnparsedDefaultProfile()) { _UnparsedDefaultProfile = std::nullopt; } } std::optional GlobalAppSettings::_getUnparsedDefaultProfileImpl() const { /*return user set value*/ if (_UnparsedDefaultProfile) { return _UnparsedDefaultProfile; } /*user set value was not set*/ /*iterate through parents to find a value*/ for (auto parent : _parents) { if (auto val{ parent->_getUnparsedDefaultProfileImpl() }) { return val; } } /*no value was found*/ return std::nullopt; } #pragma endregion winrt::Microsoft::Terminal::Settings::Model::ActionMap GlobalAppSettings::ActionMap() const noexcept { return *_actionMap; } // Method Description: // - Create a new instance of this class from a serialized JsonObject. // Arguments: // - json: an object which should be a serialization of a GlobalAppSettings object. // Return Value: // - a new GlobalAppSettings instance created from the values in `json` winrt::com_ptr GlobalAppSettings::FromJson(const Json::Value& json) { auto result = winrt::make_self(); result->LayerJson(json); return result; } void GlobalAppSettings::LayerJson(const Json::Value& json) { // _validDefaultProfile keeps track of whether we've verified that DefaultProfile points to something // CascadiaSettings::_ResolveDefaultProfile performs a validation and updates DefaultProfile() with the // resolved value, then making it valid. _validDefaultProfile = false; JsonUtils::GetValueForKey(json, DefaultProfileKey, _UnparsedDefaultProfile); JsonUtils::GetValueForKey(json, AlwaysShowTabsKey, _AlwaysShowTabs); JsonUtils::GetValueForKey(json, ConfirmCloseAllKey, _ConfirmCloseAllTabs); JsonUtils::GetValueForKey(json, InitialRowsKey, _InitialRows); JsonUtils::GetValueForKey(json, InitialColsKey, _InitialCols); JsonUtils::GetValueForKey(json, InitialPositionKey, _InitialPosition); JsonUtils::GetValueForKey(json, CenterOnLaunchKey, _CenterOnLaunch); JsonUtils::GetValueForKey(json, ShowTitleInTitlebarKey, _ShowTitleInTitlebar); JsonUtils::GetValueForKey(json, ShowTabsInTitlebarKey, _ShowTabsInTitlebar); JsonUtils::GetValueForKey(json, WordDelimitersKey, _WordDelimiters); JsonUtils::GetValueForKey(json, CopyOnSelectKey, _CopyOnSelect); JsonUtils::GetValueForKey(json, InputServiceWarningKey, _InputServiceWarning); JsonUtils::GetValueForKey(json, CopyFormattingKey, _CopyFormatting); JsonUtils::GetValueForKey(json, WarnAboutLargePasteKey, _WarnAboutLargePaste); JsonUtils::GetValueForKey(json, WarnAboutMultiLinePasteKey, _WarnAboutMultiLinePaste); JsonUtils::GetValueForKey(json, LaunchModeKey, _LaunchMode); JsonUtils::GetValueForKey(json, LanguageKey, _Language); JsonUtils::GetValueForKey(json, ThemeKey, _Theme); JsonUtils::GetValueForKey(json, TabWidthModeKey, _TabWidthMode); JsonUtils::GetValueForKey(json, SnapToGridOnResizeKey, _SnapToGridOnResize); // GetValueForKey will only override the current value if the key exists JsonUtils::GetValueForKey(json, DebugFeaturesKey, _DebugFeaturesEnabled); JsonUtils::GetValueForKey(json, ForceFullRepaintRenderingKey, _ForceFullRepaintRendering); JsonUtils::GetValueForKey(json, SoftwareRenderingKey, _SoftwareRendering); JsonUtils::GetValueForKey(json, ForceVTInputKey, _ForceVTInput); JsonUtils::GetValueForKey(json, EnableStartupTaskKey, _StartOnUserLogin); JsonUtils::GetValueForKey(json, AlwaysOnTopKey, _AlwaysOnTop); // GH#8076 - when adding enum values to this key, we also changed it from // "useTabSwitcher" to "tabSwitcherMode". Continue supporting // "useTabSwitcher", but prefer "tabSwitcherMode" JsonUtils::GetValueForKey(json, LegacyUseTabSwitcherModeKey, _TabSwitcherMode); JsonUtils::GetValueForKey(json, TabSwitcherModeKey, _TabSwitcherMode); JsonUtils::GetValueForKey(json, DisableAnimationsKey, _DisableAnimations); JsonUtils::GetValueForKey(json, StartupActionsKey, _StartupActions); JsonUtils::GetValueForKey(json, FocusFollowMouseKey, _FocusFollowMouse); JsonUtils::GetValueForKey(json, WindowingBehaviorKey, _WindowingBehavior); JsonUtils::GetValueForKey(json, TrimBlockSelectionKey, _TrimBlockSelection); JsonUtils::GetValueForKey(json, DetectURLsKey, _DetectURLs); // This is a helper lambda to get the keybindings and commands out of both // and array of objects. We'll use this twice, once on the legacy // `keybindings` key, and again on the newer `bindings` key. auto parseBindings = [this, &json](auto jsonKey) { if (auto bindings{ json[JsonKey(jsonKey)] }) { auto warnings = _actionMap->LayerJson(bindings); // It's possible that the user provided keybindings have some warnings // in them - problems that we should alert the user to, but we can // recover from. Most of these warnings cannot be detected later in the // Validate settings phase, so we'll collect them now. If there were any // warnings generated from parsing these keybindings, add them to our // list of warnings. _keybindingsWarnings.insert(_keybindingsWarnings.end(), warnings.begin(), warnings.end()); } }; parseBindings(LegacyKeybindingsKey); parseBindings(ActionsKey); } // Method Description: // - Adds the given colorscheme to our map of schemes, using its name as the key. // Arguments: // - scheme: the color scheme to add // Return Value: // - void GlobalAppSettings::AddColorScheme(const Model::ColorScheme& scheme) { _colorSchemes.Insert(scheme.Name(), scheme); } void GlobalAppSettings::RemoveColorScheme(hstring schemeName) { _colorSchemes.TryRemove(schemeName); } // Method Description: // - Return the warnings that we've collected during parsing the JSON for the // keybindings. It's possible that the user provided keybindings have some // warnings in them - problems that we should alert the user to, but we can // recover from. // Arguments: // - // Return Value: // - std::vector GlobalAppSettings::KeybindingsWarnings() const { return _keybindingsWarnings; } // Method Description: // - Create a new serialized JsonObject from an instance of this class // Arguments: // - // Return Value: // - the JsonObject representing this instance Json::Value GlobalAppSettings::ToJson() const { Json::Value json{ Json::ValueType::objectValue }; // clang-format off JsonUtils::SetValueForKey(json, DefaultProfileKey, _UnparsedDefaultProfile); JsonUtils::SetValueForKey(json, AlwaysShowTabsKey, _AlwaysShowTabs); JsonUtils::SetValueForKey(json, ConfirmCloseAllKey, _ConfirmCloseAllTabs); JsonUtils::SetValueForKey(json, InitialRowsKey, _InitialRows); JsonUtils::SetValueForKey(json, InitialColsKey, _InitialCols); JsonUtils::SetValueForKey(json, InitialPositionKey, _InitialPosition); JsonUtils::SetValueForKey(json, CenterOnLaunchKey, _CenterOnLaunch); JsonUtils::SetValueForKey(json, ShowTitleInTitlebarKey, _ShowTitleInTitlebar); JsonUtils::SetValueForKey(json, ShowTabsInTitlebarKey, _ShowTabsInTitlebar); JsonUtils::SetValueForKey(json, WordDelimitersKey, _WordDelimiters); JsonUtils::SetValueForKey(json, InputServiceWarningKey, _InputServiceWarning); JsonUtils::SetValueForKey(json, CopyOnSelectKey, _CopyOnSelect); JsonUtils::SetValueForKey(json, CopyFormattingKey, _CopyFormatting); JsonUtils::SetValueForKey(json, WarnAboutLargePasteKey, _WarnAboutLargePaste); JsonUtils::SetValueForKey(json, WarnAboutMultiLinePasteKey, _WarnAboutMultiLinePaste); JsonUtils::SetValueForKey(json, LaunchModeKey, _LaunchMode); JsonUtils::SetValueForKey(json, LanguageKey, _Language); JsonUtils::SetValueForKey(json, ThemeKey, _Theme); JsonUtils::SetValueForKey(json, TabWidthModeKey, _TabWidthMode); JsonUtils::SetValueForKey(json, SnapToGridOnResizeKey, _SnapToGridOnResize); JsonUtils::SetValueForKey(json, DebugFeaturesKey, _DebugFeaturesEnabled); JsonUtils::SetValueForKey(json, ForceFullRepaintRenderingKey, _ForceFullRepaintRendering); JsonUtils::SetValueForKey(json, SoftwareRenderingKey, _SoftwareRendering); JsonUtils::SetValueForKey(json, ForceVTInputKey, _ForceVTInput); JsonUtils::SetValueForKey(json, EnableStartupTaskKey, _StartOnUserLogin); JsonUtils::SetValueForKey(json, AlwaysOnTopKey, _AlwaysOnTop); JsonUtils::SetValueForKey(json, TabSwitcherModeKey, _TabSwitcherMode); JsonUtils::SetValueForKey(json, DisableAnimationsKey, _DisableAnimations); JsonUtils::SetValueForKey(json, StartupActionsKey, _StartupActions); JsonUtils::SetValueForKey(json, FocusFollowMouseKey, _FocusFollowMouse); JsonUtils::SetValueForKey(json, WindowingBehaviorKey, _WindowingBehavior); JsonUtils::SetValueForKey(json, TrimBlockSelectionKey, _TrimBlockSelection); JsonUtils::SetValueForKey(json, DetectURLsKey, _DetectURLs); // clang-format on json[JsonKey(ActionsKey)] = _actionMap->ToJson(); return json; }