422 lines
18 KiB
C++
422 lines
18 KiB
C++
// 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<implementation::ActionMap>() },
|
|
_keybindingsWarnings{},
|
|
_validDefaultProfile{ false },
|
|
_defaultProfile{}
|
|
{
|
|
_colorSchemes = winrt::single_threaded_map<winrt::hstring, Model::ColorScheme>();
|
|
}
|
|
|
|
// Method Description:
|
|
// - Copies any extraneous data from the parent before completing a CreateChild call
|
|
// Arguments:
|
|
// - <none>
|
|
// Return Value:
|
|
// - <none>
|
|
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> GlobalAppSettings::Copy() const
|
|
{
|
|
auto globals{ winrt::make_self<GlobalAppSettings>() };
|
|
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<ColorScheme>(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<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::ColorScheme> 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<winrt::hstring> 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> GlobalAppSettings::FromJson(const Json::Value& json)
|
|
{
|
|
auto result = winrt::make_self<GlobalAppSettings>();
|
|
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:
|
|
// - <none>
|
|
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:
|
|
// - <none>
|
|
// Return Value:
|
|
// - <none>
|
|
std::vector<winrt::Microsoft::Terminal::Settings::Model::SettingsLoadWarnings> GlobalAppSettings::KeybindingsWarnings() const
|
|
{
|
|
return _keybindingsWarnings;
|
|
}
|
|
|
|
// Method Description:
|
|
// - Create a new serialized JsonObject from an instance of this class
|
|
// Arguments:
|
|
// - <none>
|
|
// 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;
|
|
}
|