Migrate OSS up to 168d28b03
This commit is contained in:
commit
30f7f2082b
|
@ -557,6 +557,7 @@ DECSTR
|
|||
DECSWL
|
||||
DECTCEM
|
||||
Dedupe
|
||||
deduplicate
|
||||
deduplicated
|
||||
DEFAPP
|
||||
DEFAULTBACKGROUND
|
||||
|
@ -784,6 +785,7 @@ FINDSTRINGEXACT
|
|||
FINDUP
|
||||
FIter
|
||||
FIXEDCONVERTED
|
||||
FIXEDFILEINFO
|
||||
Flg
|
||||
flyout
|
||||
fmodern
|
||||
|
@ -1992,6 +1994,7 @@ resx
|
|||
retval
|
||||
rfa
|
||||
rfc
|
||||
rfid
|
||||
rftp
|
||||
rgb
|
||||
rgba
|
||||
|
|
|
@ -289,6 +289,7 @@ If you would like to ask a question that you feel doesn't warrant an issue
|
|||
* You must [enable Developer Mode in the Windows Settings
|
||||
app](https://docs.microsoft.com/en-us/windows/uwp/get-started/enable-your-device-for-development)
|
||||
to locally install and run Windows Terminal
|
||||
* You must have [PowerShell 7 or later](https://github.com/PowerShell/PowerShell/releases/latest) installed
|
||||
* You must have the [Windows 10 1903
|
||||
SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk)
|
||||
installed
|
||||
|
|
|
@ -1401,7 +1401,8 @@
|
|||
"properties": {
|
||||
"acrylicOpacity": {
|
||||
"default": 0.5,
|
||||
"description": "When useAcrylic is set to true, it sets the transparency of the window for the profile. Accepts floating point values from 0-1 (default 0.5).",
|
||||
"description": "[deprecated] Please use `opacity` instead.",
|
||||
"deprecated": true,
|
||||
"maximum": 1,
|
||||
"minimum": 0,
|
||||
"type": "number"
|
||||
|
@ -1614,6 +1615,13 @@
|
|||
"minLength": 1,
|
||||
"type": "string"
|
||||
},
|
||||
"opacity": {
|
||||
"default": 100,
|
||||
"description": "Sets the opacity of the window for the profile. Accepts values from 0-100. Defaults to 50 when useAcrylic is set to true.",
|
||||
"maximum": 100,
|
||||
"minimum": 0,
|
||||
"type": "number"
|
||||
},
|
||||
"padding": {
|
||||
"default": "8, 8, 8, 8",
|
||||
"description": "Sets the padding around the text within the window. Can have three different formats:\n -\"#\" sets the same padding for all sides \n -\"#, #\" sets the same padding for left-right and top-bottom\n -\"#, #, #, #\" sets the padding individually for left, top, right, and bottom.",
|
||||
|
|
|
@ -140,12 +140,12 @@
|
|||
<!-- **END VC LIBS HACK** -->
|
||||
|
||||
<!-- This is required to get the package dependency in the AppXManifest. -->
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace winrt::SampleApp::implementation
|
|||
|
||||
WINRT_PROPERTY(winrt::hstring, ProfileName);
|
||||
WINRT_PROPERTY(bool, UseAcrylic, false);
|
||||
WINRT_PROPERTY(double, TintOpacity, 0.5);
|
||||
WINRT_PROPERTY(double, Opacity, .5);
|
||||
WINRT_PROPERTY(winrt::hstring, Padding, DEFAULT_PADDING);
|
||||
WINRT_PROPERTY(winrt::hstring, FontFace, L"Consolas");
|
||||
WINRT_PROPERTY(int32_t, FontSize, DEFAULT_FONT_SIZE);
|
||||
|
|
|
@ -147,13 +147,13 @@
|
|||
<!-- ========================= Globals ======================== -->
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
</Target>
|
||||
|
||||
|
|
|
@ -80,13 +80,13 @@
|
|||
</ItemGroup>
|
||||
|
||||
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
</Target>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.5.0-prerelease.201202003" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.0-prerelease.210913003" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
|
||||
</packages>
|
||||
|
|
|
@ -120,14 +120,14 @@
|
|||
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets'))" />
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
|
||||
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.5.0-prerelease.201202003" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.0-prerelease.210913003" targetFramework="native" />
|
||||
<package id="Microsoft.VCRTForwarders.140" version="1.0.4" targetFramework="native" />
|
||||
</packages>
|
||||
|
|
|
@ -146,12 +146,12 @@
|
|||
<!-- **END VC LIBS HACK** -->
|
||||
|
||||
<!-- This is required to get the package dependency in the AppXManifest. -->
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
|
||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
|
||||
#include "../TerminalSettingsModel/ColorScheme.h"
|
||||
#include "../TerminalSettingsModel/CascadiaSettings.h"
|
||||
#include "../types/inc/colorTable.hpp"
|
||||
#include "JsonTestClass.h"
|
||||
|
||||
using namespace Microsoft::Console;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model::implementation;
|
||||
using namespace WEX::Logging;
|
||||
using namespace WEX::TestExecution;
|
||||
|
@ -32,339 +34,293 @@ namespace SettingsModelLocalTests
|
|||
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
|
||||
END_TEST_CLASS()
|
||||
|
||||
TEST_METHOD(CanLayerColorScheme);
|
||||
TEST_METHOD(LayerColorSchemeProperties);
|
||||
TEST_METHOD(ParseSimpleColorScheme);
|
||||
TEST_METHOD(LayerColorSchemesOnArray);
|
||||
TEST_METHOD(UpdateSchemeReferences);
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup)
|
||||
static Core::Color rgb(uint8_t r, uint8_t g, uint8_t b) noexcept
|
||||
{
|
||||
InitializeJsonReader();
|
||||
return true;
|
||||
return Core::Color{ r, g, b, 255 };
|
||||
}
|
||||
};
|
||||
|
||||
void ColorSchemeTests::CanLayerColorScheme()
|
||||
void ColorSchemeTests::ParseSimpleColorScheme()
|
||||
{
|
||||
const std::string scheme0String{ R"({
|
||||
"name": "scheme0",
|
||||
"foreground": "#000000",
|
||||
"background": "#010101"
|
||||
})" };
|
||||
const std::string scheme1String{ R"({
|
||||
"name": "scheme1",
|
||||
"foreground": "#020202",
|
||||
"background": "#030303"
|
||||
})" };
|
||||
const std::string scheme2String{ R"({
|
||||
"name": "scheme0",
|
||||
"foreground": "#040404",
|
||||
"background": "#050505"
|
||||
})" };
|
||||
const std::string scheme3String{ R"({
|
||||
// "name": "scheme3",
|
||||
"foreground": "#060606",
|
||||
"background": "#070707"
|
||||
})" };
|
||||
const std::string campbellScheme{ "{"
|
||||
"\"background\" : \"#0C0C0C\","
|
||||
"\"black\" : \"#0C0C0C\","
|
||||
"\"blue\" : \"#0037DA\","
|
||||
"\"brightBlack\" : \"#767676\","
|
||||
"\"brightBlue\" : \"#3B78FF\","
|
||||
"\"brightCyan\" : \"#61D6D6\","
|
||||
"\"brightGreen\" : \"#16C60C\","
|
||||
"\"brightPurple\" : \"#B4009E\","
|
||||
"\"brightRed\" : \"#E74856\","
|
||||
"\"brightWhite\" : \"#F2F2F2\","
|
||||
"\"brightYellow\" : \"#F9F1A5\","
|
||||
"\"cursorColor\" : \"#FFFFFF\","
|
||||
"\"cyan\" : \"#3A96DD\","
|
||||
"\"foreground\" : \"#F2F2F2\","
|
||||
"\"green\" : \"#13A10E\","
|
||||
"\"name\" : \"Campbell\","
|
||||
"\"purple\" : \"#881798\","
|
||||
"\"red\" : \"#C50F1F\","
|
||||
"\"selectionBackground\" : \"#131313\","
|
||||
"\"white\" : \"#CCCCCC\","
|
||||
"\"yellow\" : \"#C19C00\""
|
||||
"}" };
|
||||
|
||||
const auto scheme0Json = VerifyParseSucceeded(scheme0String);
|
||||
const auto scheme1Json = VerifyParseSucceeded(scheme1String);
|
||||
const auto scheme2Json = VerifyParseSucceeded(scheme2String);
|
||||
const auto scheme3Json = VerifyParseSucceeded(scheme3String);
|
||||
const auto schemeObject = VerifyParseSucceeded(campbellScheme);
|
||||
auto scheme = ColorScheme::FromJson(schemeObject);
|
||||
VERIFY_ARE_EQUAL(L"Campbell", scheme->Name());
|
||||
VERIFY_ARE_EQUAL(til::color(0xf2, 0xf2, 0xf2, 255), til::color{ scheme->Foreground() });
|
||||
VERIFY_ARE_EQUAL(til::color(0x0c, 0x0c, 0x0c, 255), til::color{ scheme->Background() });
|
||||
VERIFY_ARE_EQUAL(til::color(0x13, 0x13, 0x13, 255), til::color{ scheme->SelectionBackground() });
|
||||
VERIFY_ARE_EQUAL(til::color(0xFF, 0xFF, 0xFF, 255), til::color{ scheme->CursorColor() });
|
||||
|
||||
const auto scheme0 = ColorScheme::FromJson(scheme0Json);
|
||||
std::array<COLORREF, COLOR_TABLE_SIZE> expectedCampbellTable;
|
||||
const auto campbellSpan = gsl::make_span(expectedCampbellTable);
|
||||
Utils::InitializeCampbellColorTable(campbellSpan);
|
||||
Utils::SetColorTableAlpha(campbellSpan, 0);
|
||||
|
||||
VERIFY_IS_TRUE(scheme0->ShouldBeLayered(scheme0Json));
|
||||
VERIFY_IS_FALSE(scheme0->ShouldBeLayered(scheme1Json));
|
||||
VERIFY_IS_TRUE(scheme0->ShouldBeLayered(scheme2Json));
|
||||
VERIFY_IS_FALSE(scheme0->ShouldBeLayered(scheme3Json));
|
||||
for (size_t i = 0; i < expectedCampbellTable.size(); i++)
|
||||
{
|
||||
const auto& expected = expectedCampbellTable.at(i);
|
||||
const til::color actual{ scheme->Table().at(static_cast<uint32_t>(i)) };
|
||||
VERIFY_ARE_EQUAL(expected, actual);
|
||||
}
|
||||
|
||||
const auto scheme1 = ColorScheme::FromJson(scheme1Json);
|
||||
|
||||
VERIFY_IS_FALSE(scheme1->ShouldBeLayered(scheme0Json));
|
||||
VERIFY_IS_TRUE(scheme1->ShouldBeLayered(scheme1Json));
|
||||
VERIFY_IS_FALSE(scheme1->ShouldBeLayered(scheme2Json));
|
||||
VERIFY_IS_FALSE(scheme1->ShouldBeLayered(scheme3Json));
|
||||
|
||||
const auto scheme3 = ColorScheme::FromJson(scheme3Json);
|
||||
|
||||
VERIFY_IS_FALSE(scheme3->ShouldBeLayered(scheme0Json));
|
||||
VERIFY_IS_FALSE(scheme3->ShouldBeLayered(scheme1Json));
|
||||
VERIFY_IS_FALSE(scheme3->ShouldBeLayered(scheme2Json));
|
||||
VERIFY_IS_FALSE(scheme3->ShouldBeLayered(scheme3Json));
|
||||
}
|
||||
|
||||
void ColorSchemeTests::LayerColorSchemeProperties()
|
||||
{
|
||||
const std::string scheme0String{ R"({
|
||||
"name": "scheme0",
|
||||
"foreground": "#000000",
|
||||
"background": "#010101",
|
||||
"selectionBackground": "#010100",
|
||||
"cursorColor": "#010001",
|
||||
"red": "#010000",
|
||||
"green": "#000100",
|
||||
"blue": "#000001"
|
||||
})" };
|
||||
const std::string scheme1String{ R"({
|
||||
"name": "scheme1",
|
||||
"foreground": "#020202",
|
||||
"background": "#030303",
|
||||
"selectionBackground": "#020200",
|
||||
"cursorColor": "#040004",
|
||||
"red": "#020000",
|
||||
|
||||
"blue": "#000002"
|
||||
})" };
|
||||
const std::string scheme2String{ R"({
|
||||
"name": "scheme0",
|
||||
"foreground": "#040404",
|
||||
"background": "#050505",
|
||||
"selectionBackground": "#030300",
|
||||
"cursorColor": "#060006",
|
||||
"red": "#030000",
|
||||
"green": "#000300"
|
||||
})" };
|
||||
|
||||
const auto scheme0Json = VerifyParseSucceeded(scheme0String);
|
||||
const auto scheme1Json = VerifyParseSucceeded(scheme1String);
|
||||
const auto scheme2Json = VerifyParseSucceeded(scheme2String);
|
||||
|
||||
auto scheme0 = ColorScheme::FromJson(scheme0Json);
|
||||
VERIFY_ARE_EQUAL(L"scheme0", scheme0->_Name);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0, 0, 0), scheme0->_Foreground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 1, 1, 1), scheme0->_Background);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 1, 1, 0), scheme0->_SelectionBackground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 1, 0, 1), scheme0->_CursorColor);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 1, 0, 0), scheme0->_table[XTERM_RED_ATTR]);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0, 1, 0), scheme0->_table[XTERM_GREEN_ATTR]);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0, 0, 1), scheme0->_table[XTERM_BLUE_ATTR]);
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Layering scheme1 on top of scheme0"));
|
||||
scheme0->LayerJson(scheme1Json);
|
||||
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 2, 2, 2), scheme0->_Foreground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 3, 3, 3), scheme0->_Background);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 2, 2, 0), scheme0->_SelectionBackground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 4, 0, 4), scheme0->_CursorColor);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 2, 0, 0), scheme0->_table[XTERM_RED_ATTR]);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0, 1, 0), scheme0->_table[XTERM_GREEN_ATTR]);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0, 0, 2), scheme0->_table[XTERM_BLUE_ATTR]);
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Layering scheme2Json on top of (scheme0+scheme1)"));
|
||||
scheme0->LayerJson(scheme2Json);
|
||||
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 4, 4, 4), scheme0->_Foreground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 5, 5, 5), scheme0->_Background);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 3, 3, 0), scheme0->_SelectionBackground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 6, 0, 6), scheme0->_CursorColor);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 3, 0, 0), scheme0->_table[XTERM_RED_ATTR]);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0, 3, 0), scheme0->_table[XTERM_GREEN_ATTR]);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0, 0, 2), scheme0->_table[XTERM_BLUE_ATTR]);
|
||||
Log::Comment(L"Roundtrip Test for Color Scheme");
|
||||
Json::Value outJson{ scheme->ToJson() };
|
||||
VERIFY_ARE_EQUAL(schemeObject, outJson);
|
||||
}
|
||||
|
||||
void ColorSchemeTests::LayerColorSchemesOnArray()
|
||||
{
|
||||
const std::string scheme0String{ R"({
|
||||
"name": "scheme0",
|
||||
"foreground": "#000000",
|
||||
"background": "#010101"
|
||||
static constexpr std::string_view inboxSettings{ R"({
|
||||
"schemes": [
|
||||
{
|
||||
"background": "#0C0C0C",
|
||||
"black": "#0C0C0C",
|
||||
"blue": "#0037DA",
|
||||
"brightBlack": "#767676",
|
||||
"brightBlue": "#3B78FF",
|
||||
"brightCyan": "#61D6D6",
|
||||
"brightGreen": "#16C60C",
|
||||
"brightPurple": "#B4009E",
|
||||
"brightRed": "#E74856",
|
||||
"brightWhite": "#F2F2F2",
|
||||
"brightYellow": "#F9F1A5",
|
||||
"cursorColor": "#FFFFFF",
|
||||
"cyan": "#3A96DD",
|
||||
"foreground": "#CCCCCC",
|
||||
"green": "#13A10E",
|
||||
"name": "Campbell",
|
||||
"purple": "#881798",
|
||||
"red": "#C50F1F",
|
||||
"selectionBackground": "#FFFFFF",
|
||||
"white": "#CCCCCC",
|
||||
"yellow": "#C19C00"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
const std::string scheme1String{ R"({
|
||||
"name": "scheme1",
|
||||
"foreground": "#020202",
|
||||
"background": "#030303"
|
||||
})" };
|
||||
const std::string scheme2String{ R"({
|
||||
"name": "scheme0",
|
||||
"foreground": "#040404",
|
||||
"background": "#050505"
|
||||
})" };
|
||||
const std::string scheme3String{ R"({
|
||||
// by not providing a name, the scheme will have the name ""
|
||||
"foreground": "#060606",
|
||||
"background": "#070707"
|
||||
static constexpr std::string_view userSettings{ R"({
|
||||
"profiles": [
|
||||
{
|
||||
"name" : "profile0"
|
||||
}
|
||||
],
|
||||
"schemes": [
|
||||
{
|
||||
"background": "#121314",
|
||||
"black": "#121314",
|
||||
"blue": "#121314",
|
||||
"brightBlack": "#121314",
|
||||
"brightBlue": "#121314",
|
||||
"brightCyan": "#121314",
|
||||
"brightGreen": "#121314",
|
||||
"brightPurple": "#121314",
|
||||
"brightRed": "#121314",
|
||||
"brightWhite": "#121314",
|
||||
"brightYellow": "#121314",
|
||||
"cursorColor": "#121314",
|
||||
"cyan": "#121314",
|
||||
"foreground": "#121314",
|
||||
"green": "#121314",
|
||||
"name": "Campbell",
|
||||
"purple": "#121314",
|
||||
"red": "#121314",
|
||||
"selectionBackground": "#121314",
|
||||
"white": "#121314",
|
||||
"yellow": "#121314"
|
||||
},
|
||||
{
|
||||
"background": "#012456",
|
||||
"black": "#0C0C0C",
|
||||
"blue": "#0037DA",
|
||||
"brightBlack": "#767676",
|
||||
"brightBlue": "#3B78FF",
|
||||
"brightCyan": "#61D6D6",
|
||||
"brightGreen": "#16C60C",
|
||||
"brightPurple": "#B4009E",
|
||||
"brightRed": "#E74856",
|
||||
"brightWhite": "#F2F2F2",
|
||||
"brightYellow": "#F9F1A5",
|
||||
"cursorColor": "#FFFFFF",
|
||||
"cyan": "#3A96DD",
|
||||
"foreground": "#CCCCCC",
|
||||
"green": "#13A10E",
|
||||
"name": "Campbell Powershell",
|
||||
"purple": "#881798",
|
||||
"red": "#C50F1F",
|
||||
"selectionBackground": "#FFFFFF",
|
||||
"white": "#CCCCCC",
|
||||
"yellow": "#C19C00"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
|
||||
const auto scheme0Json = VerifyParseSucceeded(scheme0String);
|
||||
const auto scheme1Json = VerifyParseSucceeded(scheme1String);
|
||||
const auto scheme2Json = VerifyParseSucceeded(scheme2String);
|
||||
const auto scheme3Json = VerifyParseSucceeded(scheme3String);
|
||||
const auto settings = winrt::make_self<CascadiaSettings>(userSettings, inboxSettings);
|
||||
|
||||
auto settings = winrt::make_self<CascadiaSettings>();
|
||||
const auto colorSchemes = settings->GlobalSettings().ColorSchemes();
|
||||
VERIFY_ARE_EQUAL(2u, colorSchemes.Size());
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings->_globals->ColorSchemes().Size());
|
||||
VERIFY_IS_NULL(settings->_FindMatchingColorScheme(scheme0Json));
|
||||
VERIFY_IS_NULL(settings->_FindMatchingColorScheme(scheme1Json));
|
||||
VERIFY_IS_NULL(settings->_FindMatchingColorScheme(scheme2Json));
|
||||
VERIFY_IS_NULL(settings->_FindMatchingColorScheme(scheme3Json));
|
||||
const auto scheme0 = winrt::get_self<ColorScheme>(colorSchemes.Lookup(L"Campbell"));
|
||||
VERIFY_ARE_EQUAL(rgb(0x12, 0x13, 0x14), scheme0->Foreground());
|
||||
VERIFY_ARE_EQUAL(rgb(0x12, 0x13, 0x14), scheme0->Background());
|
||||
|
||||
settings->_LayerOrCreateColorScheme(scheme0Json);
|
||||
{
|
||||
for (auto kv : settings->_globals->ColorSchemes())
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"kv:%s->%s", kv.Key().data(), kv.Value().Name().data()));
|
||||
}
|
||||
VERIFY_ARE_EQUAL(1u, settings->_globals->ColorSchemes().Size());
|
||||
|
||||
VERIFY_IS_TRUE(settings->_globals->ColorSchemes().HasKey(L"scheme0"));
|
||||
auto scheme0Proj = settings->_globals->ColorSchemes().Lookup(L"scheme0");
|
||||
auto scheme0 = winrt::get_self<ColorScheme>(scheme0Proj);
|
||||
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingColorScheme(scheme0Json));
|
||||
VERIFY_IS_NULL(settings->_FindMatchingColorScheme(scheme1Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingColorScheme(scheme2Json));
|
||||
VERIFY_IS_NULL(settings->_FindMatchingColorScheme(scheme3Json));
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0, 0, 0), scheme0->_Foreground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 1, 1, 1), scheme0->_Background);
|
||||
}
|
||||
|
||||
settings->_LayerOrCreateColorScheme(scheme1Json);
|
||||
|
||||
{
|
||||
VERIFY_ARE_EQUAL(2u, settings->_globals->ColorSchemes().Size());
|
||||
|
||||
VERIFY_IS_TRUE(settings->_globals->ColorSchemes().HasKey(L"scheme0"));
|
||||
auto scheme0Proj = settings->_globals->ColorSchemes().Lookup(L"scheme0");
|
||||
auto scheme0 = winrt::get_self<ColorScheme>(scheme0Proj);
|
||||
VERIFY_IS_TRUE(settings->_globals->ColorSchemes().HasKey(L"scheme1"));
|
||||
auto scheme1Proj = settings->_globals->ColorSchemes().Lookup(L"scheme1");
|
||||
auto scheme1 = winrt::get_self<ColorScheme>(scheme1Proj);
|
||||
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingColorScheme(scheme0Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingColorScheme(scheme1Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingColorScheme(scheme2Json));
|
||||
VERIFY_IS_NULL(settings->_FindMatchingColorScheme(scheme3Json));
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0, 0, 0), scheme0->_Foreground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 1, 1, 1), scheme0->_Background);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 2, 2, 2), scheme1->_Foreground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 3, 3, 3), scheme1->_Background);
|
||||
}
|
||||
settings->_LayerOrCreateColorScheme(scheme2Json);
|
||||
|
||||
{
|
||||
VERIFY_ARE_EQUAL(2u, settings->_globals->ColorSchemes().Size());
|
||||
|
||||
VERIFY_IS_TRUE(settings->_globals->ColorSchemes().HasKey(L"scheme0"));
|
||||
auto scheme0Proj = settings->_globals->ColorSchemes().Lookup(L"scheme0");
|
||||
auto scheme0 = winrt::get_self<ColorScheme>(scheme0Proj);
|
||||
VERIFY_IS_TRUE(settings->_globals->ColorSchemes().HasKey(L"scheme1"));
|
||||
auto scheme1Proj = settings->_globals->ColorSchemes().Lookup(L"scheme1");
|
||||
auto scheme1 = winrt::get_self<ColorScheme>(scheme1Proj);
|
||||
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingColorScheme(scheme0Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingColorScheme(scheme1Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingColorScheme(scheme2Json));
|
||||
VERIFY_IS_NULL(settings->_FindMatchingColorScheme(scheme3Json));
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 4, 4, 4), scheme0->_Foreground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 5, 5, 5), scheme0->_Background);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 2, 2, 2), scheme1->_Foreground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 3, 3, 3), scheme1->_Background);
|
||||
}
|
||||
settings->_LayerOrCreateColorScheme(scheme3Json);
|
||||
|
||||
{
|
||||
VERIFY_ARE_EQUAL(3u, settings->_globals->ColorSchemes().Size());
|
||||
|
||||
VERIFY_IS_TRUE(settings->_globals->ColorSchemes().HasKey(L"scheme0"));
|
||||
auto scheme0Proj = settings->_globals->ColorSchemes().Lookup(L"scheme0");
|
||||
auto scheme0 = winrt::get_self<ColorScheme>(scheme0Proj);
|
||||
VERIFY_IS_TRUE(settings->_globals->ColorSchemes().HasKey(L"scheme1"));
|
||||
auto scheme1Proj = settings->_globals->ColorSchemes().Lookup(L"scheme1");
|
||||
auto scheme1 = winrt::get_self<ColorScheme>(scheme1Proj);
|
||||
VERIFY_IS_TRUE(settings->_globals->ColorSchemes().HasKey(L""));
|
||||
auto scheme2Proj = settings->_globals->ColorSchemes().Lookup(L"");
|
||||
auto scheme2 = winrt::get_self<ColorScheme>(scheme2Proj);
|
||||
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingColorScheme(scheme0Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingColorScheme(scheme1Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingColorScheme(scheme2Json));
|
||||
VERIFY_IS_NULL(settings->_FindMatchingColorScheme(scheme3Json));
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 4, 4, 4), scheme0->_Foreground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 5, 5, 5), scheme0->_Background);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 2, 2, 2), scheme1->_Foreground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 3, 3, 3), scheme1->_Background);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 6, 6, 6), scheme2->_Foreground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 7, 7, 7), scheme2->_Background);
|
||||
}
|
||||
const auto scheme1 = winrt::get_self<ColorScheme>(colorSchemes.Lookup(L"Campbell Powershell"));
|
||||
VERIFY_ARE_EQUAL(rgb(0xCC, 0xCC, 0xCC), scheme1->Foreground());
|
||||
VERIFY_ARE_EQUAL(rgb(0x01, 0x24, 0x56), scheme1->Background());
|
||||
}
|
||||
|
||||
void ColorSchemeTests::UpdateSchemeReferences()
|
||||
{
|
||||
const std::string settingsString{ R"json({
|
||||
"defaultProfile": "Inherited reference",
|
||||
"profiles": {
|
||||
"defaults": {
|
||||
"colorScheme": "Scheme 1"
|
||||
},
|
||||
"list": [
|
||||
{
|
||||
"name": "Explicit scheme reference",
|
||||
"colorScheme": "Scheme 1"
|
||||
},
|
||||
{
|
||||
"name": "Explicit reference; hidden",
|
||||
"colorScheme": "Scheme 1",
|
||||
"hidden": true
|
||||
},
|
||||
{
|
||||
"name": "Inherited reference"
|
||||
},
|
||||
{
|
||||
"name": "Different reference",
|
||||
"colorScheme": "Scheme 2"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schemes": [
|
||||
{ "name": "Scheme 1" },
|
||||
{ "name": "Scheme 2" },
|
||||
{ "name": "Scheme 1 (renamed)" }
|
||||
]
|
||||
})json" };
|
||||
static constexpr std::string_view settingsString{ R"json({
|
||||
"defaultProfile": "Inherited reference",
|
||||
"profiles": {
|
||||
"defaults": {
|
||||
"colorScheme": "Campbell"
|
||||
},
|
||||
"list": [
|
||||
{
|
||||
"name": "Explicit scheme reference",
|
||||
"colorScheme": "Campbell"
|
||||
},
|
||||
{
|
||||
"name": "Explicit reference; hidden",
|
||||
"colorScheme": "Campbell",
|
||||
"hidden": true
|
||||
},
|
||||
{
|
||||
"name": "Inherited reference"
|
||||
},
|
||||
{
|
||||
"name": "Different reference",
|
||||
"colorScheme": "One Half Dark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schemes": [
|
||||
{
|
||||
"background": "#0C0C0C",
|
||||
"black": "#0C0C0C",
|
||||
"blue": "#0037DA",
|
||||
"brightBlack": "#767676",
|
||||
"brightBlue": "#3B78FF",
|
||||
"brightCyan": "#61D6D6",
|
||||
"brightGreen": "#16C60C",
|
||||
"brightPurple": "#B4009E",
|
||||
"brightRed": "#E74856",
|
||||
"brightWhite": "#F2F2F2",
|
||||
"brightYellow": "#F9F1A5",
|
||||
"cursorColor": "#FFFFFF",
|
||||
"cyan": "#3A96DD",
|
||||
"foreground": "#CCCCCC",
|
||||
"green": "#13A10E",
|
||||
"name": "Campbell",
|
||||
"purple": "#881798",
|
||||
"red": "#C50F1F",
|
||||
"selectionBackground": "#FFFFFF",
|
||||
"white": "#CCCCCC",
|
||||
"yellow": "#C19C00"
|
||||
},
|
||||
{
|
||||
"background": "#0C0C0C",
|
||||
"black": "#0C0C0C",
|
||||
"blue": "#0037DA",
|
||||
"brightBlack": "#767676",
|
||||
"brightBlue": "#3B78FF",
|
||||
"brightCyan": "#61D6D6",
|
||||
"brightGreen": "#16C60C",
|
||||
"brightPurple": "#B4009E",
|
||||
"brightRed": "#E74856",
|
||||
"brightWhite": "#F2F2F2",
|
||||
"brightYellow": "#F9F1A5",
|
||||
"cursorColor": "#FFFFFF",
|
||||
"cyan": "#3A96DD",
|
||||
"foreground": "#CCCCCC",
|
||||
"green": "#13A10E",
|
||||
"name": "Campbell (renamed)",
|
||||
"purple": "#881798",
|
||||
"red": "#C50F1F",
|
||||
"selectionBackground": "#FFFFFF",
|
||||
"white": "#CCCCCC",
|
||||
"yellow": "#C19C00"
|
||||
},
|
||||
{
|
||||
"background": "#282C34",
|
||||
"black": "#282C34",
|
||||
"blue": "#61AFEF",
|
||||
"brightBlack": "#5A6374",
|
||||
"brightBlue": "#61AFEF",
|
||||
"brightCyan": "#56B6C2",
|
||||
"brightGreen": "#98C379",
|
||||
"brightPurple": "#C678DD",
|
||||
"brightRed": "#E06C75",
|
||||
"brightWhite": "#DCDFE4",
|
||||
"brightYellow": "#E5C07B",
|
||||
"cursorColor": "#FFFFFF",
|
||||
"cyan": "#56B6C2",
|
||||
"foreground": "#DCDFE4",
|
||||
"green": "#98C379",
|
||||
"name": "One Half Dark",
|
||||
"purple": "#C678DD",
|
||||
"red": "#E06C75",
|
||||
"selectionBackground": "#FFFFFF",
|
||||
"white": "#DCDFE4",
|
||||
"yellow": "#E5C07B"
|
||||
}
|
||||
]
|
||||
})json" };
|
||||
|
||||
auto settings{ winrt::make_self<CascadiaSettings>(false) };
|
||||
settings->_ParseJsonString(settingsString, false);
|
||||
settings->_ApplyDefaultsFromUserSettings();
|
||||
settings->LayerJson(settings->_userSettings);
|
||||
settings->_ValidateSettings();
|
||||
const auto settings{ winrt::make_self<CascadiaSettings>(settingsString) };
|
||||
|
||||
// update all references to "Scheme 1"
|
||||
const auto newName{ L"Scheme 1 (renamed)" };
|
||||
settings->UpdateColorSchemeReferences(L"Scheme 1", newName);
|
||||
const auto newName{ L"Campbell (renamed)" };
|
||||
settings->UpdateColorSchemeReferences(L"Campbell", newName);
|
||||
|
||||
// verify profile defaults
|
||||
Log::Comment(L"Profile Defaults");
|
||||
VERIFY_ARE_EQUAL(newName, settings->ProfileDefaults().DefaultAppearance().ColorSchemeName());
|
||||
VERIFY_IS_TRUE(settings->ProfileDefaults().DefaultAppearance().HasColorSchemeName());
|
||||
|
||||
// verify all other profiles
|
||||
const auto& profiles{ settings->AllProfiles() };
|
||||
{
|
||||
const auto& prof{ profiles.GetAt(0) };
|
||||
Log::Comment(prof.Name().c_str());
|
||||
VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().ColorSchemeName());
|
||||
VERIFY_IS_TRUE(prof.DefaultAppearance().HasColorSchemeName());
|
||||
}
|
||||
{
|
||||
const auto& prof{ profiles.GetAt(1) };
|
||||
Log::Comment(prof.Name().c_str());
|
||||
VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().ColorSchemeName());
|
||||
VERIFY_IS_TRUE(prof.DefaultAppearance().HasColorSchemeName());
|
||||
}
|
||||
{
|
||||
const auto& prof{ profiles.GetAt(2) };
|
||||
Log::Comment(prof.Name().c_str());
|
||||
VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().ColorSchemeName());
|
||||
VERIFY_IS_FALSE(prof.DefaultAppearance().HasColorSchemeName());
|
||||
}
|
||||
{
|
||||
const auto& prof{ profiles.GetAt(3) };
|
||||
Log::Comment(prof.Name().c_str());
|
||||
VERIFY_ARE_EQUAL(L"Scheme 2", prof.DefaultAppearance().ColorSchemeName());
|
||||
VERIFY_ARE_EQUAL(L"One Half Dark", prof.DefaultAppearance().ColorSchemeName());
|
||||
VERIFY_IS_TRUE(prof.DefaultAppearance().HasColorSchemeName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,12 +43,6 @@ namespace SettingsModelLocalTests
|
|||
TEST_METHOD(TestLayerOnAutogeneratedName);
|
||||
|
||||
TEST_METHOD(TestGenerateCommandline);
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup)
|
||||
{
|
||||
InitializeJsonReader();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void CommandTests::ManyCommandsSameAction()
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,44 +7,34 @@ Module Name:
|
|||
|
||||
Abstract:
|
||||
- This class is a helper that can be used to quickly create tests that need to
|
||||
read & parse json data. Test classes that need to read JSON should make sure
|
||||
to derive from this class, and also make sure to call InitializeJsonReader()
|
||||
in the TEST_CLASS_SETUP().
|
||||
read & parse json data.
|
||||
|
||||
Author(s):
|
||||
Mike Griese (migrie) August-2019
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
class JsonTestClass
|
||||
{
|
||||
public:
|
||||
void InitializeJsonReader()
|
||||
static Json::Value VerifyParseSucceeded(const std::string_view& content)
|
||||
{
|
||||
_reader = std::unique_ptr<Json::CharReader>(Json::CharReaderBuilder::CharReaderBuilder().newCharReader());
|
||||
};
|
||||
static const std::unique_ptr<Json::CharReader> reader{ Json::CharReaderBuilder::CharReaderBuilder().newCharReader() };
|
||||
|
||||
void InitializeJsonWriter()
|
||||
{
|
||||
_writer = std::unique_ptr<Json::StreamWriter>(Json::StreamWriterBuilder::StreamWriterBuilder().newStreamWriter());
|
||||
}
|
||||
|
||||
Json::Value VerifyParseSucceeded(std::string content)
|
||||
{
|
||||
Json::Value root;
|
||||
std::string errs;
|
||||
const bool parseResult = _reader->parse(content.c_str(), content.c_str() + content.size(), &root, &errs);
|
||||
const bool parseResult = reader->parse(content.data(), content.data() + content.size(), &root, &errs);
|
||||
VERIFY_IS_TRUE(parseResult, winrt::to_hstring(errs).c_str());
|
||||
return root;
|
||||
};
|
||||
|
||||
std::string toString(const Json::Value& json)
|
||||
static std::string toString(const Json::Value& json)
|
||||
{
|
||||
static const std::unique_ptr<Json::StreamWriter> writer{ Json::StreamWriterBuilder::StreamWriterBuilder().newStreamWriter() };
|
||||
|
||||
std::stringstream s;
|
||||
_writer->write(json, &s);
|
||||
writer->write(json, &s);
|
||||
return s.str();
|
||||
}
|
||||
|
||||
protected:
|
||||
std::unique_ptr<Json::CharReader> _reader;
|
||||
std::unique_ptr<Json::StreamWriter> _writer;
|
||||
};
|
||||
|
|
|
@ -59,12 +59,6 @@ namespace SettingsModelLocalTests
|
|||
|
||||
TEST_METHOD(TestGetKeyBindingForAction);
|
||||
TEST_METHOD(KeybindingsWithoutVkey);
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup)
|
||||
{
|
||||
InitializeJsonReader();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void KeyBindingsTests::KeyChords()
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include "../TerminalSettingsModel/CascadiaSettings.h"
|
||||
#include "JsonTestClass.h"
|
||||
|
||||
#include <defaults.h>
|
||||
|
||||
using namespace Microsoft::Console;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
using namespace WEX::Logging;
|
||||
|
@ -32,81 +34,86 @@ namespace SettingsModelLocalTests
|
|||
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
|
||||
END_TEST_CLASS()
|
||||
|
||||
TEST_METHOD(CanLayerProfile);
|
||||
TEST_METHOD(ProfileGeneratesGuid);
|
||||
TEST_METHOD(LayerProfileProperties);
|
||||
TEST_METHOD(LayerProfileIcon);
|
||||
TEST_METHOD(LayerProfilesOnArray);
|
||||
TEST_METHOD(DuplicateProfileTest);
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup)
|
||||
{
|
||||
InitializeJsonReader();
|
||||
return true;
|
||||
}
|
||||
TEST_METHOD(TestGenGuidsForProfiles);
|
||||
};
|
||||
|
||||
void ProfileTests::CanLayerProfile()
|
||||
void ProfileTests::ProfileGeneratesGuid()
|
||||
{
|
||||
const std::string profile0String{ R"({
|
||||
"name" : "profile0",
|
||||
"guid" : "{6239a42c-1111-49a3-80bd-e8fdd045185c}"
|
||||
})" };
|
||||
const std::string profile1String{ R"({
|
||||
"name" : "profile1",
|
||||
"guid" : "{6239a42c-2222-49a3-80bd-e8fdd045185c}"
|
||||
})" };
|
||||
const std::string profile2String{ R"({
|
||||
"name" : "profile2",
|
||||
"guid" : "{6239a42c-1111-49a3-80bd-e8fdd045185c}"
|
||||
})" };
|
||||
const std::string profile3String{ R"({
|
||||
"name" : "profile3"
|
||||
})" };
|
||||
// Parse some profiles without guids. We should NOT generate new guids
|
||||
// for them. If a profile doesn't have a GUID, we'll leave its _guid
|
||||
// set to nullopt. The Profile::Guid() getter will
|
||||
// ensure all profiles have a GUID that's actually set.
|
||||
// The null guid _is_ a valid guid, so we won't re-generate that
|
||||
// guid. null is _not_ a valid guid, so we'll leave that nullopt
|
||||
|
||||
const auto profile0Json = VerifyParseSucceeded(profile0String);
|
||||
const auto profile1Json = VerifyParseSucceeded(profile1String);
|
||||
const auto profile2Json = VerifyParseSucceeded(profile2String);
|
||||
const auto profile3Json = VerifyParseSucceeded(profile3String);
|
||||
// See SettingsTests::ValidateProfilesGenerateGuids for a version of
|
||||
// this test that includes synthesizing GUIDS for profiles without GUIDs
|
||||
// set
|
||||
|
||||
const std::string profileWithoutGuid{ R"({
|
||||
"name" : "profile0"
|
||||
})" };
|
||||
const std::string secondProfileWithoutGuid{ R"({
|
||||
"name" : "profile1"
|
||||
})" };
|
||||
const std::string profileWithNullForGuid{ R"({
|
||||
"name" : "profile2",
|
||||
"guid" : null
|
||||
})" };
|
||||
const std::string profileWithNullGuid{ R"({
|
||||
"name" : "profile3",
|
||||
"guid" : "{00000000-0000-0000-0000-000000000000}"
|
||||
})" };
|
||||
const std::string profileWithGuid{ R"({
|
||||
"name" : "profile4",
|
||||
"guid" : "{6239a42c-1de4-49a3-80bd-e8fdd045185c}"
|
||||
})" };
|
||||
|
||||
const auto profile0Json = VerifyParseSucceeded(profileWithoutGuid);
|
||||
const auto profile1Json = VerifyParseSucceeded(secondProfileWithoutGuid);
|
||||
const auto profile2Json = VerifyParseSucceeded(profileWithNullForGuid);
|
||||
const auto profile3Json = VerifyParseSucceeded(profileWithNullGuid);
|
||||
const auto profile4Json = VerifyParseSucceeded(profileWithGuid);
|
||||
|
||||
const auto profile0 = implementation::Profile::FromJson(profile0Json);
|
||||
|
||||
VERIFY_IS_FALSE(profile0->ShouldBeLayered(profile1Json));
|
||||
VERIFY_IS_TRUE(profile0->ShouldBeLayered(profile2Json));
|
||||
VERIFY_IS_FALSE(profile0->ShouldBeLayered(profile3Json));
|
||||
|
||||
const auto profile1 = implementation::Profile::FromJson(profile1Json);
|
||||
|
||||
VERIFY_IS_FALSE(profile1->ShouldBeLayered(profile0Json));
|
||||
// A profile _can_ be layered with itself, though what's the point?
|
||||
VERIFY_IS_TRUE(profile1->ShouldBeLayered(profile1Json));
|
||||
VERIFY_IS_FALSE(profile1->ShouldBeLayered(profile2Json));
|
||||
VERIFY_IS_FALSE(profile1->ShouldBeLayered(profile3Json));
|
||||
|
||||
const auto profile2 = implementation::Profile::FromJson(profile2Json);
|
||||
const auto profile3 = implementation::Profile::FromJson(profile3Json);
|
||||
const auto profile4 = implementation::Profile::FromJson(profile4Json);
|
||||
const winrt::guid cmdGuid = Utils::GuidFromString(L"{6239a42c-1de4-49a3-80bd-e8fdd045185c}");
|
||||
const winrt::guid nullGuid{};
|
||||
|
||||
VERIFY_IS_FALSE(profile3->ShouldBeLayered(profile0Json));
|
||||
// A profile _can_ be layered with itself, though what's the point?
|
||||
VERIFY_IS_FALSE(profile3->ShouldBeLayered(profile1Json));
|
||||
VERIFY_IS_FALSE(profile3->ShouldBeLayered(profile2Json));
|
||||
VERIFY_IS_TRUE(profile3->ShouldBeLayered(profile3Json));
|
||||
VERIFY_IS_FALSE(profile0->HasGuid());
|
||||
VERIFY_IS_FALSE(profile1->HasGuid());
|
||||
VERIFY_IS_FALSE(profile2->HasGuid());
|
||||
VERIFY_IS_TRUE(profile3->HasGuid());
|
||||
VERIFY_IS_TRUE(profile4->HasGuid());
|
||||
|
||||
VERIFY_ARE_EQUAL(profile3->Guid(), nullGuid);
|
||||
VERIFY_ARE_EQUAL(profile4->Guid(), cmdGuid);
|
||||
}
|
||||
|
||||
void ProfileTests::LayerProfileProperties()
|
||||
{
|
||||
const std::string profile0String{ R"({
|
||||
static constexpr std::string_view profile0String{ R"({
|
||||
"name": "profile0",
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"foreground": "#000000",
|
||||
"background": "#010101",
|
||||
"selectionBackground": "#010101"
|
||||
})" };
|
||||
const std::string profile1String{ R"({
|
||||
static constexpr std::string_view profile1String{ R"({
|
||||
"name": "profile1",
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"foreground": "#020202",
|
||||
"startingDirectory": "C:/"
|
||||
})" };
|
||||
const std::string profile2String{ R"({
|
||||
static constexpr std::string_view profile2String{ R"({
|
||||
"name": "profile2",
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"foreground": "#030303",
|
||||
|
@ -172,21 +179,21 @@ namespace SettingsModelLocalTests
|
|||
|
||||
void ProfileTests::LayerProfileIcon()
|
||||
{
|
||||
const std::string profile0String{ R"({
|
||||
static constexpr std::string_view profile0String{ R"({
|
||||
"name": "profile0",
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"icon": "not-null.png"
|
||||
})" };
|
||||
const std::string profile1String{ R"({
|
||||
static constexpr std::string_view profile1String{ R"({
|
||||
"name": "profile1",
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"icon": null
|
||||
})" };
|
||||
const std::string profile2String{ R"({
|
||||
static constexpr std::string_view profile2String{ R"({
|
||||
"name": "profile2",
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}"
|
||||
})" };
|
||||
const std::string profile3String{ R"({
|
||||
static constexpr std::string_view profile3String{ R"({
|
||||
"name": "profile3",
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"icon": "another-real.png"
|
||||
|
@ -228,102 +235,95 @@ namespace SettingsModelLocalTests
|
|||
|
||||
void ProfileTests::LayerProfilesOnArray()
|
||||
{
|
||||
const std::string profile0String{ R"({
|
||||
"name" : "profile0",
|
||||
"guid" : "{6239a42c-0000-49a3-80bd-e8fdd045185c}"
|
||||
static constexpr std::string_view inboxProfiles{ R"({
|
||||
"profiles": [
|
||||
{
|
||||
"name" : "profile0",
|
||||
"guid" : "{6239a42c-0000-49a3-80bd-e8fdd045185c}"
|
||||
}, {
|
||||
"name" : "profile1",
|
||||
"guid" : "{6239a42c-1111-49a3-80bd-e8fdd045185c}"
|
||||
}, {
|
||||
"name" : "profile2",
|
||||
"guid" : "{6239a42c-2222-49a3-80bd-e8fdd045185c}"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
const std::string profile1String{ R"({
|
||||
"name" : "profile1",
|
||||
"guid" : "{6239a42c-1111-49a3-80bd-e8fdd045185c}"
|
||||
})" };
|
||||
const std::string profile2String{ R"({
|
||||
"name" : "profile2",
|
||||
"guid" : "{6239a42c-2222-49a3-80bd-e8fdd045185c}"
|
||||
})" };
|
||||
const std::string profile3String{ R"({
|
||||
"name" : "profile3",
|
||||
"guid" : "{6239a42c-0000-49a3-80bd-e8fdd045185c}"
|
||||
})" };
|
||||
const std::string profile4String{ R"({
|
||||
"name" : "profile4",
|
||||
"guid" : "{6239a42c-0000-49a3-80bd-e8fdd045185c}"
|
||||
static constexpr std::string_view userProfiles{ R"({
|
||||
"profiles": [
|
||||
{
|
||||
"name" : "profile3",
|
||||
"guid" : "{6239a42c-0000-49a3-80bd-e8fdd045185c}"
|
||||
}, {
|
||||
"name" : "profile4",
|
||||
"guid" : "{6239a42c-1111-49a3-80bd-e8fdd045185c}"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
|
||||
const auto profile0Json = VerifyParseSucceeded(profile0String);
|
||||
const auto profile1Json = VerifyParseSucceeded(profile1String);
|
||||
const auto profile2Json = VerifyParseSucceeded(profile2String);
|
||||
const auto profile3Json = VerifyParseSucceeded(profile3String);
|
||||
const auto profile4Json = VerifyParseSucceeded(profile4String);
|
||||
|
||||
auto settings = winrt::make_self<implementation::CascadiaSettings>();
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings->_allProfiles.Size());
|
||||
VERIFY_IS_NULL(settings->_FindMatchingProfile(profile0Json));
|
||||
VERIFY_IS_NULL(settings->_FindMatchingProfile(profile1Json));
|
||||
VERIFY_IS_NULL(settings->_FindMatchingProfile(profile2Json));
|
||||
VERIFY_IS_NULL(settings->_FindMatchingProfile(profile3Json));
|
||||
VERIFY_IS_NULL(settings->_FindMatchingProfile(profile4Json));
|
||||
|
||||
settings->_LayerOrCreateProfile(profile0Json);
|
||||
VERIFY_ARE_EQUAL(1u, settings->_allProfiles.Size());
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile0Json));
|
||||
VERIFY_IS_NULL(settings->_FindMatchingProfile(profile1Json));
|
||||
VERIFY_IS_NULL(settings->_FindMatchingProfile(profile2Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile3Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile4Json));
|
||||
|
||||
settings->_LayerOrCreateProfile(profile1Json);
|
||||
VERIFY_ARE_EQUAL(2u, settings->_allProfiles.Size());
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile0Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile1Json));
|
||||
VERIFY_IS_NULL(settings->_FindMatchingProfile(profile2Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile3Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile4Json));
|
||||
|
||||
settings->_LayerOrCreateProfile(profile2Json);
|
||||
VERIFY_ARE_EQUAL(3u, settings->_allProfiles.Size());
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile0Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile1Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile2Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile3Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile4Json));
|
||||
VERIFY_ARE_EQUAL(L"profile0", settings->_allProfiles.GetAt(0).Name());
|
||||
|
||||
settings->_LayerOrCreateProfile(profile3Json);
|
||||
VERIFY_ARE_EQUAL(3u, settings->_allProfiles.Size());
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile0Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile1Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile2Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile3Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile4Json));
|
||||
VERIFY_ARE_EQUAL(L"profile3", settings->_allProfiles.GetAt(0).Name());
|
||||
|
||||
settings->_LayerOrCreateProfile(profile4Json);
|
||||
VERIFY_ARE_EQUAL(3u, settings->_allProfiles.Size());
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile0Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile1Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile2Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile3Json));
|
||||
VERIFY_IS_NOT_NULL(settings->_FindMatchingProfile(profile4Json));
|
||||
VERIFY_ARE_EQUAL(L"profile4", settings->_allProfiles.GetAt(0).Name());
|
||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(userProfiles, inboxProfiles);
|
||||
const auto allProfiles = settings->AllProfiles();
|
||||
VERIFY_ARE_EQUAL(3u, allProfiles.Size());
|
||||
VERIFY_ARE_EQUAL(L"profile3", allProfiles.GetAt(0).Name());
|
||||
VERIFY_ARE_EQUAL(L"profile4", allProfiles.GetAt(1).Name());
|
||||
VERIFY_ARE_EQUAL(L"profile2", allProfiles.GetAt(2).Name());
|
||||
}
|
||||
|
||||
void ProfileTests::DuplicateProfileTest()
|
||||
{
|
||||
const std::string profile0String{ R"({
|
||||
"name" : "profile0",
|
||||
"backgroundImage" : "some//path"
|
||||
static constexpr std::string_view userProfiles{ R"({
|
||||
"profiles": [
|
||||
{
|
||||
"name": "profile0",
|
||||
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"backgroundImage": "file:///some/path",
|
||||
"hidden": false,
|
||||
}
|
||||
]
|
||||
})" };
|
||||
|
||||
const auto profile0Json = VerifyParseSucceeded(profile0String);
|
||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(userProfiles);
|
||||
const auto profile = settings->AllProfiles().GetAt(0);
|
||||
const auto duplicatedProfile = settings->DuplicateProfile(profile);
|
||||
|
||||
auto settings = winrt::make_self<implementation::CascadiaSettings>();
|
||||
|
||||
settings->_LayerOrCreateProfile(profile0Json);
|
||||
auto duplicatedProfile = settings->DuplicateProfile(*settings->_FindMatchingProfile(profile0Json));
|
||||
duplicatedProfile.Name(L"profile0");
|
||||
duplicatedProfile.Guid(profile.Guid());
|
||||
duplicatedProfile.Name(profile.Name());
|
||||
|
||||
const auto json = winrt::get_self<implementation::Profile>(profile)->ToJson();
|
||||
const auto duplicatedJson = winrt::get_self<implementation::Profile>(duplicatedProfile)->ToJson();
|
||||
VERIFY_ARE_EQUAL(profile0Json, duplicatedJson);
|
||||
VERIFY_ARE_EQUAL(json, duplicatedJson, til::u8u16(toString(duplicatedJson)).c_str());
|
||||
}
|
||||
|
||||
void ProfileTests::TestGenGuidsForProfiles()
|
||||
{
|
||||
// We'll generate GUIDs in the Profile::Guid getter. We should make sure that
|
||||
// the GUID generated for a dynamic profile (with a source) is different
|
||||
// than that of a profile without a source.
|
||||
|
||||
static constexpr std::string_view userSettings{ R"({
|
||||
"profiles": [
|
||||
{
|
||||
"name": "profile0",
|
||||
"source": "Terminal.App.UnitTest.0",
|
||||
},
|
||||
{
|
||||
"name": "profile0"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
|
||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(userSettings, DefaultJson);
|
||||
|
||||
VERIFY_ARE_EQUAL(4u, settings->AllProfiles().Size());
|
||||
|
||||
VERIFY_ARE_EQUAL(L"profile0", settings->AllProfiles().GetAt(0).Name());
|
||||
VERIFY_IS_TRUE(settings->AllProfiles().GetAt(0).HasGuid());
|
||||
VERIFY_IS_FALSE(settings->AllProfiles().GetAt(0).Source().empty());
|
||||
|
||||
VERIFY_ARE_EQUAL(L"profile0", settings->AllProfiles().GetAt(1).Name());
|
||||
VERIFY_IS_TRUE(settings->AllProfiles().GetAt(1).HasGuid());
|
||||
VERIFY_IS_TRUE(settings->AllProfiles().GetAt(1).Source().empty());
|
||||
|
||||
VERIFY_ARE_NOT_EQUAL(settings->AllProfiles().GetAt(0).Guid(), settings->AllProfiles().GetAt(1).Guid());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "JsonTestClass.h"
|
||||
#include "TestUtils.h"
|
||||
#include <defaults.h>
|
||||
#include "../ut_app/TestDynamicProfileGenerator.h"
|
||||
|
||||
using namespace Microsoft::Console;
|
||||
using namespace WEX::Logging;
|
||||
|
@ -43,13 +42,6 @@ namespace SettingsModelLocalTests
|
|||
TEST_METHOD(CascadiaSettings);
|
||||
TEST_METHOD(LegacyFontSettings);
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup)
|
||||
{
|
||||
InitializeJsonReader();
|
||||
InitializeJsonWriter();
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// Method Description:
|
||||
// - deserializes and reserializes a json string representing a settings object model of type T
|
||||
|
@ -309,10 +301,10 @@ namespace SettingsModelLocalTests
|
|||
])" };
|
||||
const std::string actionsString9B{ R"([
|
||||
{
|
||||
"commands":
|
||||
"commands":
|
||||
[
|
||||
{
|
||||
"command":
|
||||
"command":
|
||||
{
|
||||
"action": "sendInput",
|
||||
"input": "${profile.name}"
|
||||
|
@ -325,13 +317,13 @@ namespace SettingsModelLocalTests
|
|||
])" };
|
||||
const std::string actionsString9C{ R""([
|
||||
{
|
||||
"commands":
|
||||
"commands":
|
||||
[
|
||||
{
|
||||
"commands":
|
||||
"commands":
|
||||
[
|
||||
{
|
||||
"command":
|
||||
"command":
|
||||
{
|
||||
"action": "sendInput",
|
||||
"input": "${profile.name} ${scheme.name}"
|
||||
|
@ -348,7 +340,7 @@ namespace SettingsModelLocalTests
|
|||
])"" };
|
||||
const std::string actionsString9D{ R""([
|
||||
{
|
||||
"command":
|
||||
"command":
|
||||
{
|
||||
"action": "newTab",
|
||||
"profile": "${profile.name}"
|
||||
|
@ -404,75 +396,71 @@ namespace SettingsModelLocalTests
|
|||
void SerializationTests::CascadiaSettings()
|
||||
{
|
||||
const std::string settingsString{ R"({
|
||||
"$schema": "https://aka.ms/terminal-profiles-schema",
|
||||
"defaultProfile": "{61c54bbd-1111-5271-96e7-009a87ff44bf}",
|
||||
"disabledProfileSources": [ "Windows.Terminal.Wsl" ],
|
||||
"$help" : "https://aka.ms/terminal-documentation",
|
||||
"$schema" : "https://aka.ms/terminal-profiles-schema",
|
||||
"defaultProfile": "{61c54bbd-1111-5271-96e7-009a87ff44bf}",
|
||||
"disabledProfileSources": [ "Windows.Terminal.Wsl" ],
|
||||
"profiles": {
|
||||
"defaults": {
|
||||
"font": {
|
||||
"face": "Zamora Code"
|
||||
}
|
||||
},
|
||||
"list": [
|
||||
{
|
||||
"font": { "face": "Cascadia Code" },
|
||||
"guid": "{61c54bbd-1111-5271-96e7-009a87ff44bf}",
|
||||
"name": "HowettShell"
|
||||
},
|
||||
{
|
||||
"hidden": true,
|
||||
"guid": "{c08b0496-e71c-5503-b84e-3af7a7a6d2a7}",
|
||||
"name": "BhojwaniShell"
|
||||
},
|
||||
{
|
||||
"antialiasingMode": "aliased",
|
||||
"guid": "{fe9df758-ac22-5c20-922d-c7766cdd13af}",
|
||||
"name": "NiksaShell"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schemes": [
|
||||
{
|
||||
"name": "Cinnamon Roll",
|
||||
|
||||
"profiles": {
|
||||
"defaults": {
|
||||
"font": {
|
||||
"face": "Zamora Code"
|
||||
}
|
||||
},
|
||||
"list": [
|
||||
{
|
||||
"font": { "face": "Cascadia Code" },
|
||||
"guid": "{61c54bbd-1111-5271-96e7-009a87ff44bf}",
|
||||
"name": "HowettShell"
|
||||
},
|
||||
{
|
||||
"hidden": true,
|
||||
"name": "BhojwaniShell"
|
||||
},
|
||||
{
|
||||
"antialiasingMode": "aliased",
|
||||
"name": "NiksaShell"
|
||||
}
|
||||
]
|
||||
},
|
||||
"schemes": [
|
||||
{
|
||||
"name": "Cinnamon Roll",
|
||||
"cursorColor": "#FFFFFD",
|
||||
"selectionBackground": "#FFFFFF",
|
||||
|
||||
"cursorColor": "#FFFFFD",
|
||||
"selectionBackground": "#FFFFFF",
|
||||
"background": "#3C0315",
|
||||
"foreground": "#FFFFFD",
|
||||
|
||||
"background": "#3C0315",
|
||||
"foreground": "#FFFFFD",
|
||||
"black": "#282A2E",
|
||||
"blue": "#0170C5",
|
||||
"cyan": "#3F8D83",
|
||||
"green": "#76AB23",
|
||||
"purple": "#7D498F",
|
||||
"red": "#BD0940",
|
||||
"white": "#FFFFFD",
|
||||
"yellow": "#E0DE48",
|
||||
"brightBlack": "#676E7A",
|
||||
"brightBlue": "#5C98C5",
|
||||
"brightCyan": "#8ABEB7",
|
||||
"brightGreen": "#B5D680",
|
||||
"brightPurple": "#AC79BB",
|
||||
"brightRed": "#BD6D85",
|
||||
"brightWhite": "#FFFFFD",
|
||||
"brightYellow": "#FFFD76"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{ "command": { "action": "sendInput", "input": "VT Griese Mode" }, "keys": "ctrl+k" }
|
||||
]
|
||||
})" };
|
||||
|
||||
"black": "#282A2E",
|
||||
"blue": "#0170C5",
|
||||
"cyan": "#3F8D83",
|
||||
"green": "#76AB23",
|
||||
"purple": "#7D498F",
|
||||
"red": "#BD0940",
|
||||
"white": "#FFFFFD",
|
||||
"yellow": "#E0DE48",
|
||||
"brightBlack": "#676E7A",
|
||||
"brightBlue": "#5C98C5",
|
||||
"brightCyan": "#8ABEB7",
|
||||
"brightGreen": "#B5D680",
|
||||
"brightPurple": "#AC79BB",
|
||||
"brightRed": "#BD6D85",
|
||||
"brightWhite": "#FFFFFD",
|
||||
"brightYellow": "#FFFD76"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{ "command": { "action": "renameTab", "title": "Liang Tab" }, "keys": "ctrl+t" },
|
||||
{ "command": { "action": "sendInput", "input": "VT Griese Mode" }, "keys": "ctrl+k" },
|
||||
{ "command": { "action": "renameWindow", "name": "Hecker Window" }, "keys": "ctrl+l" }
|
||||
]
|
||||
})" };
|
||||
|
||||
auto settings{ winrt::make_self<implementation::CascadiaSettings>(false) };
|
||||
settings->_ParseJsonString(settingsString, false);
|
||||
settings->_ApplyDefaultsFromUserSettings();
|
||||
settings->LayerJson(settings->_userSettings);
|
||||
settings->_ValidateSettings();
|
||||
const auto settings{ winrt::make_self<implementation::CascadiaSettings>(settingsString) };
|
||||
|
||||
const auto result{ settings->ToJson() };
|
||||
VERIFY_ARE_EQUAL(toString(settings->_userSettings), toString(result));
|
||||
VERIFY_ARE_EQUAL(toString(VerifyParseSucceeded(settingsString)), toString(result));
|
||||
}
|
||||
|
||||
void SerializationTests::LegacyFontSettings()
|
||||
|
|
|
@ -98,10 +98,10 @@
|
|||
<!-- From Microsoft.UI.Xaml.targets -->
|
||||
<Native-Platform Condition="'$(Platform)' == 'Win32'">x86</Native-Platform>
|
||||
<Native-Platform Condition="'$(Platform)' != 'Win32'">$(Platform)</Native-Platform>
|
||||
<_MUXBinRoot>"$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\runtimes\win10-$(Native-Platform)\native\"</_MUXBinRoot>
|
||||
<_MUXBinRoot>"$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\runtimes\win10-$(Native-Platform)\native\"</_MUXBinRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- We actually can just straight up reference MUX here, it's fine -->
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -62,7 +62,7 @@ namespace SettingsModelLocalTests
|
|||
|
||||
void TerminalSettingsTests::TestTerminalArgsForBinding()
|
||||
{
|
||||
const std::string settingsJson{ R"(
|
||||
static constexpr std::string_view settingsJson{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": { "list": [
|
||||
|
@ -106,12 +106,12 @@ namespace SettingsModelLocalTests
|
|||
const winrt::guid guid0{ ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-0000-49a3-80bd-e8fdd045185c}") };
|
||||
const winrt::guid guid1{ ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}") };
|
||||
|
||||
CascadiaSettings settings{ til::u8u16(settingsJson) };
|
||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(settingsJson);
|
||||
|
||||
auto actionMap = settings.GlobalSettings().ActionMap();
|
||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||
auto actionMap = settings->GlobalSettings().ActionMap();
|
||||
VERIFY_ARE_EQUAL(3u, settings->ActiveProfiles().Size());
|
||||
|
||||
const auto profile2Guid = settings.ActiveProfiles().GetAt(2).Guid();
|
||||
const auto profile2Guid = settings->ActiveProfiles().GetAt(2).Guid();
|
||||
VERIFY_ARE_NOT_EQUAL(winrt::guid{}, profile2Guid);
|
||||
|
||||
const auto& actionMapImpl{ winrt::get_self<implementation::ActionMap>(actionMap) };
|
||||
|
@ -131,8 +131,8 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
|
||||
const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto termSettings = settingsStruct.DefaultSettings();
|
||||
VERIFY_ARE_EQUAL(guid0, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
|
||||
|
@ -153,8 +153,8 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
|
||||
VERIFY_ARE_EQUAL(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}", realArgs.TerminalArgs().Profile());
|
||||
|
||||
const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto termSettings = settingsStruct.DefaultSettings();
|
||||
VERIFY_ARE_EQUAL(guid1, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
|
||||
|
@ -175,8 +175,8 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
|
||||
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
|
||||
|
||||
const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto termSettings = settingsStruct.DefaultSettings();
|
||||
VERIFY_ARE_EQUAL(guid1, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
|
||||
|
@ -197,8 +197,8 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
|
||||
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
|
||||
|
||||
const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto termSettings = settingsStruct.DefaultSettings();
|
||||
VERIFY_ARE_EQUAL(profile2Guid, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
|
||||
|
@ -219,13 +219,13 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
VERIFY_ARE_EQUAL(L"foo.exe", realArgs.TerminalArgs().Commandline());
|
||||
|
||||
const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto termSettings = settingsStruct.DefaultSettings();
|
||||
if constexpr (Feature_ShowProfileDefaultsInSettings::IsEnabled())
|
||||
{
|
||||
// This action specified a command but no profile; it gets reassigned to the base profile
|
||||
VERIFY_ARE_EQUAL(settings.ProfileDefaults(), profile);
|
||||
VERIFY_ARE_EQUAL(settings->ProfileDefaults(), profile);
|
||||
VERIFY_ARE_EQUAL(29, termSettings.HistorySize());
|
||||
}
|
||||
else
|
||||
|
@ -251,8 +251,8 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
|
||||
VERIFY_ARE_EQUAL(L"foo.exe", realArgs.TerminalArgs().Commandline());
|
||||
|
||||
const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto termSettings = settingsStruct.DefaultSettings();
|
||||
VERIFY_ARE_EQUAL(guid1, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline());
|
||||
|
@ -271,8 +271,8 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
|
||||
const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto termSettings = settingsStruct.DefaultSettings();
|
||||
VERIFY_ARE_EQUAL(guid0, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
|
||||
|
@ -292,8 +292,8 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory());
|
||||
|
||||
const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto termSettings = settingsStruct.DefaultSettings();
|
||||
VERIFY_ARE_EQUAL(guid0, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
|
||||
|
@ -315,8 +315,8 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory());
|
||||
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
|
||||
|
||||
const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto termSettings = settingsStruct.DefaultSettings();
|
||||
VERIFY_ARE_EQUAL(profile2Guid, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
|
||||
|
@ -337,8 +337,8 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
|
||||
|
||||
const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto termSettings = settingsStruct.DefaultSettings();
|
||||
VERIFY_ARE_EQUAL(guid0, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
|
||||
|
@ -360,8 +360,8 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
|
||||
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
|
||||
|
||||
const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto termSettings = settingsStruct.DefaultSettings();
|
||||
VERIFY_ARE_EQUAL(profile2Guid, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
|
||||
|
@ -385,8 +385,8 @@ namespace SettingsModelLocalTests
|
|||
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
|
||||
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
|
||||
|
||||
const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
|
||||
const auto termSettings = settingsStruct.DefaultSettings();
|
||||
VERIFY_ARE_EQUAL(guid1, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline());
|
||||
|
@ -399,7 +399,7 @@ namespace SettingsModelLocalTests
|
|||
void TerminalSettingsTests::MakeSettingsForProfile()
|
||||
{
|
||||
// Test that making settings generally works.
|
||||
const std::string settingsString{ R"(
|
||||
static constexpr std::string_view settingsString{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
|
@ -415,17 +415,17 @@ namespace SettingsModelLocalTests
|
|||
}
|
||||
]
|
||||
})" };
|
||||
CascadiaSettings settings{ til::u8u16(settingsString) };
|
||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(settingsString);
|
||||
|
||||
const auto guid1 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}");
|
||||
const auto guid2 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-2222-49a3-80bd-e8fdd045185c}");
|
||||
|
||||
const auto profile1 = settings.FindProfile(guid1);
|
||||
const auto profile2 = settings.FindProfile(guid2);
|
||||
const auto profile1 = settings->FindProfile(guid1);
|
||||
const auto profile2 = settings->FindProfile(guid2);
|
||||
|
||||
try
|
||||
{
|
||||
auto terminalSettings{ TerminalSettings::CreateWithProfile(settings, profile1, nullptr) };
|
||||
auto terminalSettings{ TerminalSettings::CreateWithProfile(*settings, profile1, nullptr) };
|
||||
VERIFY_ARE_NOT_EQUAL(nullptr, terminalSettings);
|
||||
VERIFY_ARE_EQUAL(1, terminalSettings.DefaultSettings().HistorySize());
|
||||
}
|
||||
|
@ -436,7 +436,7 @@ namespace SettingsModelLocalTests
|
|||
|
||||
try
|
||||
{
|
||||
auto terminalSettings{ TerminalSettings::CreateWithProfile(settings, profile2, nullptr) };
|
||||
auto terminalSettings{ TerminalSettings::CreateWithProfile(*settings, profile2, nullptr) };
|
||||
VERIFY_ARE_NOT_EQUAL(nullptr, terminalSettings);
|
||||
VERIFY_ARE_EQUAL(2, terminalSettings.DefaultSettings().HistorySize());
|
||||
}
|
||||
|
@ -447,7 +447,7 @@ namespace SettingsModelLocalTests
|
|||
|
||||
try
|
||||
{
|
||||
const auto termSettings{ TerminalSettings::CreateWithNewTerminalArgs(settings, nullptr, nullptr) };
|
||||
const auto termSettings{ TerminalSettings::CreateWithNewTerminalArgs(*settings, nullptr, nullptr) };
|
||||
VERIFY_ARE_NOT_EQUAL(nullptr, termSettings);
|
||||
VERIFY_ARE_EQUAL(1, termSettings.DefaultSettings().HistorySize());
|
||||
}
|
||||
|
@ -463,7 +463,7 @@ namespace SettingsModelLocalTests
|
|||
// defaultProfile that's not in the list, we validate the settings, and
|
||||
// then call MakeSettings(nullopt). The validation should ensure that
|
||||
// the default profile is something reasonable
|
||||
const std::string settingsString{ R"(
|
||||
static constexpr std::string_view settingsString{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-3333-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
|
@ -479,14 +479,14 @@ namespace SettingsModelLocalTests
|
|||
}
|
||||
]
|
||||
})" };
|
||||
CascadiaSettings settings{ til::u8u16(settingsString) };
|
||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(settingsString);
|
||||
|
||||
VERIFY_ARE_EQUAL(2u, settings.Warnings().Size());
|
||||
VERIFY_ARE_EQUAL(2u, settings.ActiveProfiles().Size());
|
||||
VERIFY_ARE_EQUAL(settings.GlobalSettings().DefaultProfile(), settings.ActiveProfiles().GetAt(0).Guid());
|
||||
VERIFY_ARE_EQUAL(2u, settings->Warnings().Size());
|
||||
VERIFY_ARE_EQUAL(2u, settings->ActiveProfiles().Size());
|
||||
VERIFY_ARE_EQUAL(settings->GlobalSettings().DefaultProfile(), settings->ActiveProfiles().GetAt(0).Guid());
|
||||
try
|
||||
{
|
||||
const auto termSettings{ TerminalSettings::CreateWithNewTerminalArgs(settings, nullptr, nullptr) };
|
||||
const auto termSettings{ TerminalSettings::CreateWithNewTerminalArgs(*settings, nullptr, nullptr) };
|
||||
VERIFY_ARE_NOT_EQUAL(nullptr, termSettings);
|
||||
VERIFY_ARE_EQUAL(1, termSettings.DefaultSettings().HistorySize());
|
||||
}
|
||||
|
@ -501,7 +501,7 @@ namespace SettingsModelLocalTests
|
|||
Log::Comment(NoThrowString().Format(
|
||||
L"Ensure that setting (or not) a property in the profile that should override a property of the color scheme works correctly."));
|
||||
|
||||
const std::string settings0String{ R"(
|
||||
static constexpr std::string_view settings0String{ R"(
|
||||
{
|
||||
"defaultProfile": "profile5",
|
||||
"profiles": [
|
||||
|
@ -534,18 +534,50 @@ namespace SettingsModelLocalTests
|
|||
"schemes": [
|
||||
{
|
||||
"name": "schemeWithCursorColor",
|
||||
"cursorColor": "#123456"
|
||||
"cursorColor": "#123456",
|
||||
"black": "#121314",
|
||||
"red": "#121314",
|
||||
"green": "#121314",
|
||||
"yellow": "#121314",
|
||||
"blue": "#121314",
|
||||
"purple": "#121314",
|
||||
"cyan": "#121314",
|
||||
"white": "#121314",
|
||||
"brightBlack": "#121314",
|
||||
"brightRed": "#121314",
|
||||
"brightGreen": "#121314",
|
||||
"brightYellow": "#121314",
|
||||
"brightBlue": "#121314",
|
||||
"brightPurple": "#121314",
|
||||
"brightCyan": "#121314",
|
||||
"brightWhite": "#121314"
|
||||
},
|
||||
{
|
||||
"name": "schemeWithoutCursorColor"
|
||||
"name": "schemeWithoutCursorColor",
|
||||
"black": "#121314",
|
||||
"red": "#121314",
|
||||
"green": "#121314",
|
||||
"yellow": "#121314",
|
||||
"blue": "#121314",
|
||||
"purple": "#121314",
|
||||
"cyan": "#121314",
|
||||
"white": "#121314",
|
||||
"brightBlack": "#121314",
|
||||
"brightRed": "#121314",
|
||||
"brightGreen": "#121314",
|
||||
"brightYellow": "#121314",
|
||||
"brightBlue": "#121314",
|
||||
"brightPurple": "#121314",
|
||||
"brightCyan": "#121314",
|
||||
"brightWhite": "#121314"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
|
||||
CascadiaSettings settings{ til::u8u16(settings0String) };
|
||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(settings0String);
|
||||
|
||||
VERIFY_ARE_EQUAL(6u, settings.ActiveProfiles().Size());
|
||||
VERIFY_ARE_EQUAL(2u, settings.GlobalSettings().ColorSchemes().Size());
|
||||
VERIFY_ARE_EQUAL(6u, settings->ActiveProfiles().Size());
|
||||
VERIFY_ARE_EQUAL(2u, settings->GlobalSettings().ColorSchemes().Size());
|
||||
|
||||
auto createTerminalSettings = [&](const auto& profile, const auto& schemes) {
|
||||
auto terminalSettings{ winrt::make_self<implementation::TerminalSettings>() };
|
||||
|
@ -554,12 +586,14 @@ namespace SettingsModelLocalTests
|
|||
return terminalSettings;
|
||||
};
|
||||
|
||||
auto terminalSettings0 = createTerminalSettings(settings.ActiveProfiles().GetAt(0), settings.GlobalSettings().ColorSchemes());
|
||||
auto terminalSettings1 = createTerminalSettings(settings.ActiveProfiles().GetAt(1), settings.GlobalSettings().ColorSchemes());
|
||||
auto terminalSettings2 = createTerminalSettings(settings.ActiveProfiles().GetAt(2), settings.GlobalSettings().ColorSchemes());
|
||||
auto terminalSettings3 = createTerminalSettings(settings.ActiveProfiles().GetAt(3), settings.GlobalSettings().ColorSchemes());
|
||||
auto terminalSettings4 = createTerminalSettings(settings.ActiveProfiles().GetAt(4), settings.GlobalSettings().ColorSchemes());
|
||||
auto terminalSettings5 = createTerminalSettings(settings.ActiveProfiles().GetAt(5), settings.GlobalSettings().ColorSchemes());
|
||||
const auto activeProfiles = settings->ActiveProfiles();
|
||||
const auto colorSchemes = settings->GlobalSettings().ColorSchemes();
|
||||
const auto terminalSettings0 = createTerminalSettings(activeProfiles.GetAt(0), colorSchemes);
|
||||
const auto terminalSettings1 = createTerminalSettings(activeProfiles.GetAt(1), colorSchemes);
|
||||
const auto terminalSettings2 = createTerminalSettings(activeProfiles.GetAt(2), colorSchemes);
|
||||
const auto terminalSettings3 = createTerminalSettings(activeProfiles.GetAt(3), colorSchemes);
|
||||
const auto terminalSettings4 = createTerminalSettings(activeProfiles.GetAt(4), colorSchemes);
|
||||
const auto terminalSettings5 = createTerminalSettings(activeProfiles.GetAt(5), colorSchemes);
|
||||
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0x12, 0x34, 0x56), terminalSettings0->CursorColor()); // from color scheme
|
||||
VERIFY_ARE_EQUAL(DEFAULT_CURSOR_COLOR, terminalSettings1->CursorColor()); // default
|
||||
|
@ -571,7 +605,7 @@ namespace SettingsModelLocalTests
|
|||
|
||||
void TerminalSettingsTests::TestCommandlineToTitlePromotion()
|
||||
{
|
||||
const std::string settingsJson{ R"(
|
||||
static constexpr std::string_view settingsJson{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": { "list": [
|
||||
|
@ -587,65 +621,63 @@ namespace SettingsModelLocalTests
|
|||
} }
|
||||
})" };
|
||||
|
||||
const winrt::guid guid0{ ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-0000-49a3-80bd-e8fdd045185c}") };
|
||||
|
||||
CascadiaSettings settings{ til::u8u16(settingsJson) };
|
||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(settingsJson);
|
||||
|
||||
{ // just a profile (profile wins)
|
||||
NewTerminalArgs args{};
|
||||
args.Profile(L"profile0");
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, args, nullptr) };
|
||||
VERIFY_ARE_EQUAL(L"profile0", settingsStruct.DefaultSettings().StartingTitle());
|
||||
}
|
||||
{ // profile and command line -> no promotion (profile wins)
|
||||
NewTerminalArgs args{};
|
||||
args.Profile(L"profile0");
|
||||
args.Commandline(L"foo.exe");
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, args, nullptr) };
|
||||
VERIFY_ARE_EQUAL(L"profile0", settingsStruct.DefaultSettings().StartingTitle());
|
||||
}
|
||||
{ // just a title -> it is propagated
|
||||
NewTerminalArgs args{};
|
||||
args.TabTitle(L"Analog Kid");
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, args, nullptr) };
|
||||
VERIFY_ARE_EQUAL(L"Analog Kid", settingsStruct.DefaultSettings().StartingTitle());
|
||||
}
|
||||
{ // title and command line -> no promotion
|
||||
NewTerminalArgs args{};
|
||||
args.TabTitle(L"Digital Man");
|
||||
args.Commandline(L"foo.exe");
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, args, nullptr) };
|
||||
VERIFY_ARE_EQUAL(L"Digital Man", settingsStruct.DefaultSettings().StartingTitle());
|
||||
}
|
||||
{ // just a commandline -> promotion
|
||||
NewTerminalArgs args{};
|
||||
args.Commandline(L"foo.exe");
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, args, nullptr) };
|
||||
VERIFY_ARE_EQUAL(L"foo.exe", settingsStruct.DefaultSettings().StartingTitle());
|
||||
}
|
||||
// various typesof commandline follow
|
||||
{
|
||||
NewTerminalArgs args{};
|
||||
args.Commandline(L"foo.exe bar");
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, args, nullptr) };
|
||||
VERIFY_ARE_EQUAL(L"foo.exe", settingsStruct.DefaultSettings().StartingTitle());
|
||||
}
|
||||
{
|
||||
NewTerminalArgs args{};
|
||||
args.Commandline(L"\"foo exe.exe\" bar");
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, args, nullptr) };
|
||||
VERIFY_ARE_EQUAL(L"foo exe.exe", settingsStruct.DefaultSettings().StartingTitle());
|
||||
}
|
||||
{
|
||||
NewTerminalArgs args{};
|
||||
args.Commandline(L"\"\" grand designs");
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, args, nullptr) };
|
||||
VERIFY_ARE_EQUAL(L"", settingsStruct.DefaultSettings().StartingTitle());
|
||||
}
|
||||
{
|
||||
NewTerminalArgs args{};
|
||||
args.Commandline(L" imagine a man");
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
|
||||
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, args, nullptr) };
|
||||
VERIFY_ARE_EQUAL(L"", settingsStruct.DefaultSettings().StartingTitle());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ namespace TerminalAppLocalTests
|
|||
// containing a ${profile.name} to replace. When we expand it, it should
|
||||
// have created one command for each profile.
|
||||
|
||||
const std::string settingsJson{ R"(
|
||||
static constexpr std::wstring_view settingsJson{ LR"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
|
@ -111,10 +111,7 @@ namespace TerminalAppLocalTests
|
|||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
||||
})" };
|
||||
|
||||
const auto guid0 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-0000-49a3-80bd-e8fdd045185c}");
|
||||
const auto guid1 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}");
|
||||
|
||||
CascadiaSettings settings{ til::u8u16(settingsJson) };
|
||||
CascadiaSettings settings{ settingsJson, {} };
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
|
||||
|
@ -207,7 +204,7 @@ namespace TerminalAppLocalTests
|
|||
// For this test, put an iterable command without a given `name` to
|
||||
// replace. When we expand it, it should still work.
|
||||
|
||||
const std::string settingsJson{ R"(
|
||||
static constexpr std::wstring_view settingsJson{ LR"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
|
@ -238,10 +235,7 @@ namespace TerminalAppLocalTests
|
|||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
||||
})" };
|
||||
|
||||
const auto guid0 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-0000-49a3-80bd-e8fdd045185c}");
|
||||
const auto guid1 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}");
|
||||
|
||||
CascadiaSettings settings{ til::u8u16(settingsJson) };
|
||||
CascadiaSettings settings{ settingsJson, {} };
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
|
||||
|
@ -335,7 +329,7 @@ namespace TerminalAppLocalTests
|
|||
// cause bad json to be filled in. Something like a profile with a name
|
||||
// of "Foo\"", so the trailing '"' might break the json parsing.
|
||||
|
||||
const std::string settingsJson{ R"(
|
||||
static constexpr std::wstring_view settingsJson{ LR"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
|
@ -367,10 +361,7 @@ namespace TerminalAppLocalTests
|
|||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
||||
})" };
|
||||
|
||||
const auto guid0 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-0000-49a3-80bd-e8fdd045185c}");
|
||||
const auto guid1 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}");
|
||||
|
||||
CascadiaSettings settings{ til::u8u16(settingsJson) };
|
||||
CascadiaSettings settings{ settingsJson, {} };
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
|
||||
|
@ -468,7 +459,7 @@ namespace TerminalAppLocalTests
|
|||
// ├─ first.com
|
||||
// └─ second.com
|
||||
|
||||
const std::string settingsJson{ R"(
|
||||
static constexpr std::wstring_view settingsJson{ LR"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
|
@ -508,7 +499,7 @@ namespace TerminalAppLocalTests
|
|||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
||||
})" };
|
||||
|
||||
CascadiaSettings settings{ til::u8u16(settingsJson) };
|
||||
CascadiaSettings settings{ settingsJson, {} };
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||
|
@ -558,7 +549,7 @@ namespace TerminalAppLocalTests
|
|||
// ├─ child1
|
||||
// └─ child2
|
||||
|
||||
const std::string settingsJson{ R"(
|
||||
static constexpr std::wstring_view settingsJson{ LR"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
|
@ -603,7 +594,7 @@ namespace TerminalAppLocalTests
|
|||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
||||
})" };
|
||||
|
||||
CascadiaSettings settings{ til::u8u16(settingsJson) };
|
||||
CascadiaSettings settings{ settingsJson, {} };
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||
|
@ -691,7 +682,7 @@ namespace TerminalAppLocalTests
|
|||
// ├─ Split pane, direction: right, profile: profile2
|
||||
// └─ Split pane, direction: down, profile: profile2
|
||||
|
||||
const std::string settingsJson{ R"(
|
||||
static constexpr std::wstring_view settingsJson{ LR"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
|
@ -727,7 +718,7 @@ namespace TerminalAppLocalTests
|
|||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
||||
})" };
|
||||
|
||||
CascadiaSettings settings{ til::u8u16(settingsJson) };
|
||||
CascadiaSettings settings{ settingsJson, {} };
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||
|
@ -828,7 +819,7 @@ namespace TerminalAppLocalTests
|
|||
// ├─ Profile 2
|
||||
// └─ Profile 3
|
||||
|
||||
const std::string settingsJson{ R"(
|
||||
static constexpr std::wstring_view settingsJson{ LR"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
|
@ -864,7 +855,7 @@ namespace TerminalAppLocalTests
|
|||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
||||
})" };
|
||||
|
||||
CascadiaSettings settings{ til::u8u16(settingsJson) };
|
||||
CascadiaSettings settings{ settingsJson, {} };
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||
|
@ -926,7 +917,7 @@ namespace TerminalAppLocalTests
|
|||
// ├─ Split right
|
||||
// └─ Split down
|
||||
|
||||
const std::string settingsJson{ R"(
|
||||
static constexpr std::wstring_view settingsJson{ LR"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
|
@ -967,7 +958,7 @@ namespace TerminalAppLocalTests
|
|||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
||||
})" };
|
||||
|
||||
CascadiaSettings settings{ til::u8u16(settingsJson) };
|
||||
CascadiaSettings settings{ settingsJson, {} };
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||
|
@ -1071,7 +1062,7 @@ namespace TerminalAppLocalTests
|
|||
// containing a ${profile.name} to replace. When we expand it, it should
|
||||
// have created one command for each profile.
|
||||
|
||||
const std::string settingsJson{ R"(
|
||||
static constexpr std::wstring_view settingsJson{ LR"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
|
@ -1107,7 +1098,7 @@ namespace TerminalAppLocalTests
|
|||
]
|
||||
})" };
|
||||
|
||||
CascadiaSettings settings{ til::u8u16(settingsJson) };
|
||||
CascadiaSettings settings{ settingsJson, {} };
|
||||
|
||||
// Since at least one profile does not reference a color scheme,
|
||||
// we add a warning saying "the color scheme is unknown"
|
||||
|
|
|
@ -311,7 +311,7 @@ namespace TerminalAppLocalTests
|
|||
// TerminalPage and not only create them successfully, but also create a
|
||||
// tab using those settings successfully.
|
||||
|
||||
const std::string settingsJson0{ R"(
|
||||
static constexpr std::wstring_view settingsJson0{ LR"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
|
@ -328,7 +328,7 @@ namespace TerminalAppLocalTests
|
|||
]
|
||||
})" };
|
||||
|
||||
CascadiaSettings settings0{ til::u8u16(settingsJson0) };
|
||||
CascadiaSettings settings0{ settingsJson0, {} };
|
||||
VERIFY_IS_NOT_NULL(settings0);
|
||||
|
||||
// This is super wacky, but we can't just initialize the
|
||||
|
@ -357,7 +357,7 @@ namespace TerminalAppLocalTests
|
|||
//
|
||||
// Created to test GH#2455
|
||||
|
||||
const std::string settingsJson0{ R"(
|
||||
static constexpr std::wstring_view settingsJson0{ LR"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
|
@ -374,7 +374,7 @@ namespace TerminalAppLocalTests
|
|||
]
|
||||
})" };
|
||||
|
||||
const std::string settingsJson1{ R"(
|
||||
static constexpr std::wstring_view settingsJson1{ LR"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
|
@ -386,10 +386,10 @@ namespace TerminalAppLocalTests
|
|||
]
|
||||
})" };
|
||||
|
||||
CascadiaSettings settings0{ til::u8u16(settingsJson0) };
|
||||
CascadiaSettings settings0{ settingsJson0, {} };
|
||||
VERIFY_IS_NOT_NULL(settings0);
|
||||
|
||||
CascadiaSettings settings1{ til::u8u16(settingsJson1) };
|
||||
CascadiaSettings settings1{ settingsJson1, {} };
|
||||
VERIFY_IS_NOT_NULL(settings1);
|
||||
|
||||
const auto guid1 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}");
|
||||
|
@ -444,7 +444,7 @@ namespace TerminalAppLocalTests
|
|||
//
|
||||
// Created to test GH#2455
|
||||
|
||||
const std::string settingsJson0{ R"(
|
||||
static constexpr std::wstring_view settingsJson0{ LR"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
|
@ -461,7 +461,7 @@ namespace TerminalAppLocalTests
|
|||
]
|
||||
})" };
|
||||
|
||||
const std::string settingsJson1{ R"(
|
||||
static constexpr std::wstring_view settingsJson1{ LR"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
|
@ -473,10 +473,10 @@ namespace TerminalAppLocalTests
|
|||
]
|
||||
})" };
|
||||
|
||||
CascadiaSettings settings0{ til::u8u16(settingsJson0) };
|
||||
CascadiaSettings settings0{ settingsJson0, {} };
|
||||
VERIFY_IS_NOT_NULL(settings0);
|
||||
|
||||
CascadiaSettings settings1{ til::u8u16(settingsJson1) };
|
||||
CascadiaSettings settings1{ settingsJson1, {} };
|
||||
VERIFY_IS_NOT_NULL(settings1);
|
||||
|
||||
const auto guid1 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}");
|
||||
|
@ -558,7 +558,7 @@ namespace TerminalAppLocalTests
|
|||
// - The initialized TerminalPage, ready to use.
|
||||
winrt::com_ptr<winrt::TerminalApp::implementation::TerminalPage> TabTests::_commonSetup()
|
||||
{
|
||||
const std::string settingsJson0{ R"(
|
||||
static constexpr std::wstring_view settingsJson0{ LR"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"showTabsInTitlebar": false,
|
||||
|
@ -659,7 +659,7 @@ namespace TerminalAppLocalTests
|
|||
]
|
||||
})" };
|
||||
|
||||
CascadiaSettings settings0{ til::u8u16(settingsJson0) };
|
||||
CascadiaSettings settings0{ settingsJson0, {} };
|
||||
VERIFY_IS_NOT_NULL(settings0);
|
||||
|
||||
const auto guid1 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}");
|
||||
|
|
|
@ -92,11 +92,11 @@
|
|||
<!-- From Microsoft.UI.Xaml.targets -->
|
||||
<Native-Platform Condition="'$(Platform)' == 'Win32'">x86</Native-Platform>
|
||||
<Native-Platform Condition="'$(Platform)' != 'Win32'">$(Platform)</Native-Platform>
|
||||
<_MUXBinRoot>"$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\runtimes\win10-$(Native-Platform)\native\"</_MUXBinRoot>
|
||||
<_MUXBinRoot>"$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\runtimes\win10-$(Native-Platform)\native\"</_MUXBinRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- We actually can just straight up reference MUX here, it's fine -->
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -123,7 +123,7 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
|
||||
<Import Project="$(OpenConsoleDir)\src\common.build.post.props" />
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
// - Add the given peasant to the list of peasants we're tracking. This
|
||||
// Peasant may have already been assigned an ID. If it hasn't, then give
|
||||
// it an ID.
|
||||
// - NB: this takes a unique_lock on _peasantsMutex.
|
||||
// Arguments:
|
||||
// - peasant: the new Peasant to track.
|
||||
// Return Value:
|
||||
|
@ -71,10 +72,24 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
{
|
||||
// Peasant already had an ID (from an older monarch). Leave that one
|
||||
// be. Make sure that the next peasant's ID is higher than it.
|
||||
_nextPeasantID = providedID >= _nextPeasantID ? providedID + 1 : _nextPeasantID;
|
||||
// If multiple peasants are added concurrently we keep trying to update
|
||||
// until we get to set the new id.
|
||||
uint64_t current;
|
||||
do
|
||||
{
|
||||
current = _nextPeasantID.load(std::memory_order_relaxed);
|
||||
} while (current <= providedID && !_nextPeasantID.compare_exchange_weak(current, providedID + 1, std::memory_order_relaxed));
|
||||
}
|
||||
|
||||
auto newPeasantsId = peasant.GetID();
|
||||
|
||||
// Keep track of which peasant we are
|
||||
// SAFETY: this is only true for one peasant, and each peasant
|
||||
// is only added to a monarch once, so we do not need synchronization here.
|
||||
if (peasant.GetPID() == _ourPID)
|
||||
{
|
||||
_ourPeasantId = newPeasantsId;
|
||||
}
|
||||
// Add an event listener to the peasant's WindowActivated event.
|
||||
peasant.WindowActivated({ this, &Monarch::_peasantWindowActivated });
|
||||
peasant.IdentifyWindowsRequested({ this, &Monarch::_identifyWindows });
|
||||
|
@ -84,7 +99,10 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
peasant.HideNotificationIconRequested([this](auto&&, auto&&) { _HideNotificationIconRequestedHandlers(*this, nullptr); });
|
||||
peasant.QuitAllRequested({ this, &Monarch::_handleQuitAll });
|
||||
|
||||
_peasants[newPeasantsId] = peasant;
|
||||
{
|
||||
std::unique_lock lock{ _peasantsMutex };
|
||||
_peasants[newPeasantsId] = peasant;
|
||||
}
|
||||
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Monarch_AddPeasant",
|
||||
|
@ -124,9 +142,15 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
// closing all windows.
|
||||
_QuitAllRequestedHandlers(*this, nullptr);
|
||||
|
||||
_quitting.store(true);
|
||||
// Tell all peasants to exit.
|
||||
const auto callback = [&](const auto& /*id*/, const auto& p) {
|
||||
p.Quit();
|
||||
const auto callback = [&](const auto& id, const auto& p) {
|
||||
// We want to tell our peasant to quit last, so that we don't try
|
||||
// to perform a bunch of elections on quit.
|
||||
if (id != _ourPeasantId)
|
||||
{
|
||||
p.Quit();
|
||||
}
|
||||
};
|
||||
const auto onError = [&](const auto& id) {
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
|
@ -137,18 +161,46 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
};
|
||||
|
||||
_forEachPeasant(callback, onError);
|
||||
|
||||
{
|
||||
std::shared_lock lock{ _peasantsMutex };
|
||||
const auto peasantSearch = _peasants.find(_ourPeasantId);
|
||||
if (peasantSearch != _peasants.end())
|
||||
{
|
||||
peasantSearch->second.Quit();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Somehow we don't have our own peasant, this should never happen.
|
||||
// We are trying to quit anyways so just fail here.
|
||||
assert(peasantSearch != _peasants.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Tells the monarch that a peasant is being closed.
|
||||
// - NB: this (separately) takes unique locks on _peasantsMutex and
|
||||
// _mruPeasantsMutex.
|
||||
// Arguments:
|
||||
// - peasantId: the id of the peasant
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Monarch::SignalClose(const uint64_t peasantId)
|
||||
{
|
||||
_clearOldMruEntries(peasantId);
|
||||
_peasants.erase(peasantId);
|
||||
// If we are quitting we don't care about maintaining our list of
|
||||
// peasants anymore, and don't need to notify the host that something
|
||||
// changed.
|
||||
if (_quitting.load(std::memory_order_acquire))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_clearOldMruEntries({ peasantId });
|
||||
{
|
||||
std::unique_lock lock{ _peasantsMutex };
|
||||
_peasants.erase(peasantId);
|
||||
}
|
||||
_WindowClosedHandlers(nullptr, nullptr);
|
||||
}
|
||||
|
||||
|
@ -160,23 +212,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
// - the number of active peasants.
|
||||
uint64_t Monarch::GetNumberOfPeasants()
|
||||
{
|
||||
auto num = 0;
|
||||
auto callback = [&](const auto& /*id*/, const auto& p) {
|
||||
// Check that the peasant is alive, and if so increment the count
|
||||
p.GetID();
|
||||
num += 1;
|
||||
};
|
||||
auto onError = [](const auto& id) {
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Monarch_GetNumberOfPeasants_Failed",
|
||||
TraceLoggingInt64(id, "peasantID", "The ID of the peasant which we could not enumerate"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
};
|
||||
|
||||
_forEachPeasant(callback, onError);
|
||||
|
||||
return num;
|
||||
std::shared_lock lock{ _peasantsMutex };
|
||||
return _peasants.size();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -197,16 +234,25 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
// Method Description:
|
||||
// - Lookup a peasant by its ID. If the peasant has died, this will also
|
||||
// remove the peasant from our list of peasants.
|
||||
// - NB: this (separately) takes unique locks on _peasantsMutex and
|
||||
// _mruPeasantsMutex.
|
||||
// Arguments:
|
||||
// - peasantID: The ID Of the peasant to find
|
||||
// - clearMruPeasantOnFailure: When true this function will handle clearing
|
||||
// from _mruPeasants if a peasant was not found, otherwise the caller is
|
||||
// expected to handle that cleanup themselves.
|
||||
// Return Value:
|
||||
// - the peasant if it exists in our map, otherwise null
|
||||
Remoting::IPeasant Monarch::_getPeasant(uint64_t peasantID)
|
||||
Remoting::IPeasant Monarch::_getPeasant(uint64_t peasantID, bool clearMruPeasantOnFailure)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto peasantSearch = _peasants.find(peasantID);
|
||||
auto maybeThePeasant = peasantSearch == _peasants.end() ? nullptr : peasantSearch->second;
|
||||
IPeasant maybeThePeasant = nullptr;
|
||||
{
|
||||
std::shared_lock lock{ _peasantsMutex };
|
||||
const auto peasantSearch = _peasants.find(peasantID);
|
||||
maybeThePeasant = peasantSearch == _peasants.end() ? nullptr : peasantSearch->second;
|
||||
}
|
||||
// Ask the peasant for their PID. This will validate that they're
|
||||
// actually still alive.
|
||||
if (maybeThePeasant)
|
||||
|
@ -218,12 +264,19 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
// Remove the peasant from the list of peasants
|
||||
_peasants.erase(peasantID);
|
||||
|
||||
// Remove the peasant from the list of MRU windows. They're dead.
|
||||
// They can't be the MRU anymore.
|
||||
_clearOldMruEntries(peasantID);
|
||||
// Remove the peasant from the list of peasants
|
||||
{
|
||||
std::unique_lock lock{ _peasantsMutex };
|
||||
_peasants.erase(peasantID);
|
||||
}
|
||||
|
||||
if (clearMruPeasantOnFailure)
|
||||
{
|
||||
// Remove the peasant from the list of MRU windows. They're dead.
|
||||
// They can't be the MRU anymore.
|
||||
_clearOldMruEntries({ peasantID });
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -244,39 +297,27 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint64_t> peasantsToErase{};
|
||||
uint64_t result = 0;
|
||||
for (const auto& [id, p] : _peasants)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto otherName = p.WindowName();
|
||||
if (otherName == name)
|
||||
{
|
||||
result = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
// Normally, we'd just erase the peasant here. However, we can't
|
||||
// erase from the map while we're iterating over it like this.
|
||||
// Instead, pull a good ole Java and collect this id for removal
|
||||
// later.
|
||||
peasantsToErase.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the dead peasants we came across while iterating.
|
||||
for (const auto& id : peasantsToErase)
|
||||
{
|
||||
// Remove the peasant from the list of peasants
|
||||
_peasants.erase(id);
|
||||
// Remove the peasant from the list of MRU windows. They're dead.
|
||||
// They can't be the MRU anymore.
|
||||
_clearOldMruEntries(id);
|
||||
}
|
||||
const auto callback = [&](const auto& id, const auto& p) {
|
||||
auto otherName = p.WindowName();
|
||||
if (otherName == name)
|
||||
{
|
||||
result = id;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const auto onError = [&](const auto& id) {
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Monarch_lookupPeasantIdForName_Failed",
|
||||
TraceLoggingInt64(id, "peasantID", "The ID of the peasant which we could not get the name of"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
};
|
||||
|
||||
_forEachPeasant(callback, onError);
|
||||
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Monarch_lookupPeasantIdForName",
|
||||
|
@ -328,33 +369,42 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
// - Helper for removing a peasant from the list of MRU peasants. We want to
|
||||
// do this both when the peasant dies, and also when the peasant is newly
|
||||
// activated (so that we don't leave an old entry for it in the list).
|
||||
// - NB: This takes a unique lock on _mruPeasantsMutex.
|
||||
// Arguments:
|
||||
// - peasantID: The ID of the peasant to remove from the MRU list
|
||||
// - peasantIds: The list of peasant IDs to remove from the MRU list
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Monarch::_clearOldMruEntries(const uint64_t peasantID)
|
||||
void Monarch::_clearOldMruEntries(const std::unordered_set<uint64_t>& peasantIds)
|
||||
{
|
||||
auto result = std::find_if(_mruPeasants.begin(),
|
||||
_mruPeasants.end(),
|
||||
[peasantID](auto&& other) {
|
||||
return peasantID == other.PeasantID();
|
||||
});
|
||||
|
||||
if (result != std::end(_mruPeasants))
|
||||
if (peasantIds.size() == 0)
|
||||
{
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Monarch_RemovedPeasantFromDesktop",
|
||||
TraceLoggingUInt64(peasantID, "peasantID", "The ID of the peasant"),
|
||||
TraceLoggingGuid(result->DesktopID(), "desktopGuid", "The GUID of the previous desktop the window was on"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
|
||||
_mruPeasants.erase(result);
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_lock lock{ _mruPeasantsMutex };
|
||||
auto partition = std::remove_if(_mruPeasants.begin(), _mruPeasants.end(), [&](const auto& p) {
|
||||
const auto id = p.PeasantID();
|
||||
// remove the element if it was found in the list to erase.
|
||||
if (peasantIds.count(id) == 1)
|
||||
{
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Monarch_RemovedPeasantFromDesktop",
|
||||
TraceLoggingUInt64(id, "peasantID", "The ID of the peasant"),
|
||||
TraceLoggingGuid(p.DesktopID(), "desktopGuid", "The GUID of the previous desktop the window was on"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// Remove everything that was in the list
|
||||
_mruPeasants.erase(partition, _mruPeasants.end());
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Actually handle inserting the WindowActivatedArgs into our list of MRU windows.
|
||||
// - NB: this takes a unique_lock on _mruPeasantsMutex.
|
||||
// Arguments:
|
||||
// - localArgs: an in-proc WindowActivatedArgs that we should add to our list of MRU windows.
|
||||
// Return Value:
|
||||
|
@ -365,19 +415,22 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
|
||||
// * Check all the current lists to look for this peasant.
|
||||
// remove it from any where it exists.
|
||||
_clearOldMruEntries(localArgs->PeasantID());
|
||||
_clearOldMruEntries({ localArgs->PeasantID() });
|
||||
|
||||
// * If the current desktop doesn't have a vector, add one.
|
||||
const auto desktopGuid{ localArgs->DesktopID() };
|
||||
|
||||
// * Add this args list. By using lower_bound with insert, we can get it
|
||||
// into exactly the right spot, without having to re-sort the whole
|
||||
// array.
|
||||
_mruPeasants.insert(std::lower_bound(_mruPeasants.begin(),
|
||||
_mruPeasants.end(),
|
||||
*localArgs,
|
||||
[](const auto& first, const auto& second) { return first.ActivatedTime() > second.ActivatedTime(); }),
|
||||
*localArgs);
|
||||
{
|
||||
std::unique_lock lock{ _mruPeasantsMutex };
|
||||
// * Add this args list. By using lower_bound with insert, we can get it
|
||||
// into exactly the right spot, without having to re-sort the whole
|
||||
// array.
|
||||
_mruPeasants.insert(std::lower_bound(_mruPeasants.begin(),
|
||||
_mruPeasants.end(),
|
||||
*localArgs,
|
||||
[](const auto& first, const auto& second) { return first.ActivatedTime() > second.ActivatedTime(); }),
|
||||
*localArgs);
|
||||
}
|
||||
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Monarch_SetMostRecentPeasant",
|
||||
|
@ -391,6 +444,9 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
// Method Description:
|
||||
// - Retrieves the ID of the MRU peasant window. If requested, will limit
|
||||
// the search to windows that are on the current desktop.
|
||||
// - NB: This method will hold a shared lock on _mruPeasantsMutex and
|
||||
// potentially a unique_lock on _peasantsMutex at the same time.
|
||||
// Separately it might hold a unique_lock on _mruPeasantsMutex.
|
||||
// Arguments:
|
||||
// - limitToCurrentDesktop: if true, only return the MRU peasant that's
|
||||
// actually on the current desktop.
|
||||
|
@ -403,8 +459,13 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
// - the ID of the most recent peasant, otherwise 0 if we could not find one.
|
||||
uint64_t Monarch::_getMostRecentPeasantID(const bool limitToCurrentDesktop, const bool ignoreQuakeWindow)
|
||||
{
|
||||
std::shared_lock lock{ _mruPeasantsMutex };
|
||||
if (_mruPeasants.empty())
|
||||
{
|
||||
// unlock the mruPeasants mutex to make sure we can't deadlock here.
|
||||
lock.unlock();
|
||||
// Only need a shared lock for read
|
||||
std::shared_lock peasantsLock{ _peasantsMutex };
|
||||
// We haven't yet been told the MRU peasant. Just use the first one.
|
||||
// This is just gonna be a random one, but really shouldn't happen
|
||||
// in practice. The WindowManager should set the MRU peasant
|
||||
|
@ -445,15 +506,17 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
// - If it isn't on the current desktop, we'll loop again, on the
|
||||
// following peasant.
|
||||
// * If we don't care, then we'll just return that one.
|
||||
//
|
||||
// We're not just using an iterator because the contents of the list
|
||||
// might change while we're iterating here (if the peasant is dead we'll
|
||||
// remove it from the list).
|
||||
int positionInList = 0;
|
||||
while (_mruPeasants.cbegin() + positionInList < _mruPeasants.cend())
|
||||
uint64_t result = 0;
|
||||
std::unordered_set<uint64_t> peasantsToErase{};
|
||||
for (const auto& mruWindowArgs : _mruPeasants)
|
||||
{
|
||||
const auto mruWindowArgs{ *(_mruPeasants.begin() + positionInList) };
|
||||
const auto peasant{ _getPeasant(mruWindowArgs.PeasantID()) };
|
||||
// Try to get the peasant, but do not have _getPeasant clean up old
|
||||
// _mruPeasants because we are iterating here.
|
||||
// SAFETY: _getPeasant can take a unique_lock on _peasantsMutex if
|
||||
// it detects a peasant is dead. Currently _getMostRecentPeasantId
|
||||
// is the only method that holds a lock on both _mruPeasantsMutex and
|
||||
// _peasantsMutex at the same time so there cannot be a deadlock here.
|
||||
const auto peasant{ _getPeasant(mruWindowArgs.PeasantID(), false) };
|
||||
if (!peasant)
|
||||
{
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
|
@ -467,6 +530,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
// We'll go through the loop again. We removed the current one
|
||||
// at positionInList, so the next one in positionInList will be
|
||||
// a new, different peasant.
|
||||
peasantsToErase.emplace(mruWindowArgs.PeasantID());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -504,7 +568,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
"true if this window was in fact on the current desktop"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
return mruWindowArgs.PeasantID();
|
||||
result = mruWindowArgs.PeasantID();
|
||||
break;
|
||||
}
|
||||
// If this window wasn't on the current desktop, another one
|
||||
// might be. We'll increment positionInList below, and try
|
||||
|
@ -518,20 +583,30 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
|
||||
return mruWindowArgs.PeasantID();
|
||||
result = mruWindowArgs.PeasantID();
|
||||
break;
|
||||
}
|
||||
positionInList++;
|
||||
}
|
||||
|
||||
// Here, we've checked all the windows, and none of them was both alive
|
||||
// and the most recent (on this desktop). Just return 0 - the caller
|
||||
// will use this to create a new window.
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Monarch_getMostRecentPeasantID_NotFound",
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
lock.unlock();
|
||||
|
||||
return 0;
|
||||
if (peasantsToErase.size() > 0)
|
||||
{
|
||||
_clearOldMruEntries(peasantsToErase);
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
// Here, we've checked all the windows, and none of them was both alive
|
||||
// and the most recent (on this desktop). Just return 0 - the caller
|
||||
// will use this to create a new window.
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Monarch_getMostRecentPeasantID_NotFound",
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -855,7 +930,10 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
Windows::Foundation::Collections::IVectorView<PeasantInfo> Monarch::GetPeasantInfos()
|
||||
{
|
||||
std::vector<PeasantInfo> names;
|
||||
names.reserve(_peasants.size());
|
||||
{
|
||||
std::shared_lock lock{ _peasantsMutex };
|
||||
names.reserve(_peasants.size());
|
||||
}
|
||||
|
||||
const auto func = [&](const auto& id, const auto& p) -> void {
|
||||
names.push_back({ id, p.WindowName(), p.ActiveTabTitle() });
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "Peasant.h"
|
||||
#include "../cascadia/inc/cppwinrt_utils.h"
|
||||
#include "WindowActivatedArgs.h"
|
||||
#include <atomic>
|
||||
|
||||
// We sure different GUIDs here depending on whether we're running a Release,
|
||||
// Preview, or Dev build. This ensures that different installs don't
|
||||
|
@ -69,23 +70,29 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
private:
|
||||
uint64_t _ourPID;
|
||||
|
||||
uint64_t _nextPeasantID{ 1 };
|
||||
uint64_t _thisPeasantID{ 0 };
|
||||
std::atomic<uint64_t> _nextPeasantID{ 1 };
|
||||
uint64_t _ourPeasantId{ 0 };
|
||||
|
||||
// When we're quitting we do not care as much about handling some events that we know will be triggered
|
||||
std::atomic<bool> _quitting{ false };
|
||||
|
||||
winrt::com_ptr<IVirtualDesktopManager> _desktopManager{ nullptr };
|
||||
|
||||
std::unordered_map<uint64_t, winrt::Microsoft::Terminal::Remoting::IPeasant> _peasants;
|
||||
|
||||
std::vector<Remoting::WindowActivatedArgs> _mruPeasants;
|
||||
// These should not be locked at the same time to prevent deadlocks
|
||||
// unless they are both shared_locks.
|
||||
std::shared_mutex _peasantsMutex{};
|
||||
std::shared_mutex _mruPeasantsMutex{};
|
||||
|
||||
winrt::Microsoft::Terminal::Remoting::IPeasant _getPeasant(uint64_t peasantID);
|
||||
winrt::Microsoft::Terminal::Remoting::IPeasant _getPeasant(uint64_t peasantID, bool clearMruPeasantOnFailure = true);
|
||||
uint64_t _getMostRecentPeasantID(bool limitToCurrentDesktop, const bool ignoreQuakeWindow);
|
||||
uint64_t _lookupPeasantIdForName(std::wstring_view name);
|
||||
|
||||
void _peasantWindowActivated(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs& args);
|
||||
void _doHandleActivatePeasant(const winrt::com_ptr<winrt::Microsoft::Terminal::Remoting::implementation::WindowActivatedArgs>& args);
|
||||
void _clearOldMruEntries(const uint64_t peasantID);
|
||||
void _clearOldMruEntries(const std::unordered_set<uint64_t>& peasantIds);
|
||||
|
||||
void _forAllPeasantsIgnoringTheDead(std::function<void(const winrt::Microsoft::Terminal::Remoting::IPeasant&, const uint64_t)> callback,
|
||||
std::function<void(const uint64_t)> errorCallback);
|
||||
|
@ -107,6 +114,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
// returns false.
|
||||
// - If any single peasant is dead, then we'll call onError and then add it to a
|
||||
// list of peasants to clean up once the loop ends.
|
||||
// - NB: this (separately) takes unique locks on _peasantsMutex and
|
||||
// _mruPeasantsMutex.
|
||||
// Arguments:
|
||||
// - func: The function to call on each peasant
|
||||
// - onError: The function to call if a peasant is dead.
|
||||
|
@ -119,44 +128,55 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
using R = std::invoke_result_t<F, Map::key_type, Map::mapped_type>;
|
||||
static constexpr auto IsVoid = std::is_void_v<R>;
|
||||
|
||||
std::vector<uint64_t> peasantsToErase;
|
||||
|
||||
for (const auto& [id, p] : _peasants)
|
||||
std::unordered_set<uint64_t> peasantsToErase;
|
||||
{
|
||||
try
|
||||
std::shared_lock lock{ _peasantsMutex };
|
||||
|
||||
for (const auto& [id, p] : _peasants)
|
||||
{
|
||||
if constexpr (IsVoid)
|
||||
try
|
||||
{
|
||||
func(id, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!func(id, p))
|
||||
if constexpr (IsVoid)
|
||||
{
|
||||
break;
|
||||
func(id, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!func(id, p))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error& exception)
|
||||
{
|
||||
onError(id);
|
||||
catch (const winrt::hresult_error& exception)
|
||||
{
|
||||
onError(id);
|
||||
|
||||
if (exception.code() == 0x800706ba) // The RPC server is unavailable.
|
||||
{
|
||||
peasantsToErase.emplace_back(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
throw;
|
||||
if (exception.code() == 0x800706ba) // The RPC server is unavailable.
|
||||
{
|
||||
peasantsToErase.emplace(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& id : peasantsToErase)
|
||||
if (peasantsToErase.size() > 0)
|
||||
{
|
||||
_peasants.erase(id);
|
||||
_clearOldMruEntries(id);
|
||||
// Don't hold a lock on _peasants and _mruPeasants at the same
|
||||
// time to avoid deadlocks.
|
||||
{
|
||||
std::unique_lock lock{ _peasantsMutex };
|
||||
for (const auto& id : peasantsToErase)
|
||||
{
|
||||
_peasants.erase(id);
|
||||
}
|
||||
}
|
||||
_clearOldMruEntries(peasantsToErase);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -324,6 +324,14 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
|
||||
// If the peasant asks us to quit we should not try to act in future elections.
|
||||
_peasant.QuitRequested([weakThis{ get_weak() }](auto&&, auto&&) {
|
||||
if (auto wm = weakThis.get())
|
||||
{
|
||||
wm->_monarchWaitInterrupt.SetEvent();
|
||||
}
|
||||
});
|
||||
|
||||
return _peasant;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<!-- Include the MUX Controls resources -->
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"
|
||||
ControlsResourcesVersion="Version1" />
|
||||
<ResourceDictionary>
|
||||
|
||||
<!--
|
||||
|
|
|
@ -29,12 +29,12 @@ namespace winrt
|
|||
using IInspectable = Windows::Foundation::IInspectable;
|
||||
}
|
||||
|
||||
static const winrt::hstring StartupTaskName = L"StartTerminalOnLoginTask";
|
||||
static constexpr std::wstring_view StartupTaskName = L"StartTerminalOnLoginTask";
|
||||
// clang-format off
|
||||
// !!! IMPORTANT !!!
|
||||
// Make sure that these keys are in the same order as the
|
||||
// SettingsLoadWarnings/Errors enum is!
|
||||
static const std::array<std::wstring_view, static_cast<uint32_t>(SettingsLoadWarnings::WARNINGS_SIZE)> settingsLoadWarningsLabels {
|
||||
static const std::array settingsLoadWarningsLabels {
|
||||
USES_RESOURCE(L"MissingDefaultProfileText"),
|
||||
USES_RESOURCE(L"DuplicateProfileText"),
|
||||
USES_RESOURCE(L"UnknownColorSchemeText"),
|
||||
|
@ -43,7 +43,6 @@ static const std::array<std::wstring_view, static_cast<uint32_t>(SettingsLoadWar
|
|||
USES_RESOURCE(L"AtLeastOneKeybindingWarning"),
|
||||
USES_RESOURCE(L"TooManyKeysForChord"),
|
||||
USES_RESOURCE(L"MissingRequiredParameter"),
|
||||
USES_RESOURCE(L"LegacyGlobalsProperty"),
|
||||
USES_RESOURCE(L"FailedToParseCommandJson"),
|
||||
USES_RESOURCE(L"FailedToWriteToSettings"),
|
||||
USES_RESOURCE(L"InvalidColorSchemeInCmd"),
|
||||
|
@ -51,12 +50,15 @@ static const std::array<std::wstring_view, static_cast<uint32_t>(SettingsLoadWar
|
|||
USES_RESOURCE(L"FailedToParseStartupActions"),
|
||||
USES_RESOURCE(L"FailedToParseSubCommands"),
|
||||
};
|
||||
static const std::array<std::wstring_view, static_cast<uint32_t>(SettingsLoadErrors::ERRORS_SIZE)> settingsLoadErrorsLabels {
|
||||
static const std::array settingsLoadErrorsLabels {
|
||||
USES_RESOURCE(L"NoProfilesText"),
|
||||
USES_RESOURCE(L"AllProfilesHiddenText")
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
static_assert(settingsLoadWarningsLabels.size() == static_cast<size_t>(SettingsLoadWarnings::WARNINGS_SIZE));
|
||||
static_assert(settingsLoadErrorsLabels.size() == static_cast<size_t>(SettingsLoadErrors::ERRORS_SIZE));
|
||||
|
||||
// Function Description:
|
||||
// - General-purpose helper for looking up a localized string for a
|
||||
// warning/error. First will look for the given key in the provided map of
|
||||
|
@ -68,12 +70,12 @@ static const std::array<std::wstring_view, static_cast<uint32_t>(SettingsLoadErr
|
|||
// - map: A map of keys->Resource keys.
|
||||
// Return Value:
|
||||
// - the localized string for the given type, if it exists.
|
||||
template<std::size_t N>
|
||||
static winrt::hstring _GetMessageText(uint32_t index, std::array<std::wstring_view, N> keys)
|
||||
template<typename T>
|
||||
winrt::hstring _GetMessageText(uint32_t index, const T& keys)
|
||||
{
|
||||
if (index < keys.size())
|
||||
{
|
||||
return GetLibraryResourceString(keys.at(index));
|
||||
return GetLibraryResourceString(til::at(keys, index));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
@ -488,27 +490,6 @@ namespace winrt::TerminalApp::implementation
|
|||
if (!warningText.empty())
|
||||
{
|
||||
warningsTextBlock.Inlines().Append(_BuildErrorRun(warningText, ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Resources()));
|
||||
|
||||
// The "LegacyGlobalsProperty" warning is special - it has a URL
|
||||
// that goes with it. So we need to manually construct a
|
||||
// Hyperlink and insert it along with the warning text.
|
||||
if (warning == SettingsLoadWarnings::LegacyGlobalsProperty)
|
||||
{
|
||||
// Add the URL here too
|
||||
const auto legacyGlobalsLinkLabel = RS_(L"LegacyGlobalsPropertyHrefLabel");
|
||||
const auto legacyGlobalsLinkUriValue = RS_(L"LegacyGlobalsPropertyHrefUrl");
|
||||
|
||||
winrt::Windows::UI::Xaml::Documents::Run legacyGlobalsLinkText;
|
||||
winrt::Windows::UI::Xaml::Documents::Hyperlink legacyGlobalsLink;
|
||||
winrt::Windows::Foundation::Uri legacyGlobalsLinkUri{ legacyGlobalsLinkUriValue };
|
||||
|
||||
legacyGlobalsLinkText.Text(legacyGlobalsLinkLabel);
|
||||
legacyGlobalsLink.NavigateUri(legacyGlobalsLinkUri);
|
||||
legacyGlobalsLink.Inlines().Append(legacyGlobalsLinkText);
|
||||
|
||||
warningsTextBlock.Inlines().Append(legacyGlobalsLink);
|
||||
}
|
||||
|
||||
warningsTextBlock.Inlines().Append(Documents::LineBreak{});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,10 +53,6 @@ Pane::Pane(const Profile& profile, const TermControl& control, const bool lastFo
|
|||
_SetupResources();
|
||||
}
|
||||
|
||||
// Use the unfocused border color as the pane background, so an actual color
|
||||
// appears behind panes as we animate them sliding in.
|
||||
_root.Background(s_unfocusedBorderBrush);
|
||||
|
||||
// Register an event with the control to have it inform us when it gains focus.
|
||||
_gotFocusRevoker = _control.GotFocus(winrt::auto_revoke, { this, &Pane::_ControlGotFocusHandler });
|
||||
_lostFocusRevoker = _control.LostFocus(winrt::auto_revoke, { this, &Pane::_ControlLostFocusHandler });
|
||||
|
@ -1616,6 +1612,8 @@ winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst)
|
|||
// Create the dummy grid. This grid will be the one we actually animate,
|
||||
// in the place of the closed pane.
|
||||
Controls::Grid dummyGrid;
|
||||
// GH#603 - we can safely add a BG here, as the control is gone right
|
||||
// away, to fill the space as the rest of the pane expands.
|
||||
dummyGrid.Background(s_unfocusedBorderBrush);
|
||||
// It should be the size of the closed pane.
|
||||
dummyGrid.Width(removedOriginalSize.Width);
|
||||
|
@ -1871,6 +1869,19 @@ void Pane::_SetupEntranceAnimation()
|
|||
return;
|
||||
}
|
||||
|
||||
// Use the unfocused border color as the pane background, so an actual color
|
||||
// appears behind panes as we animate them sliding in.
|
||||
//
|
||||
// GH#603 - We set only the background of the new pane, while it animates
|
||||
// in. Once the animation is done, we'll remove that background, so if the
|
||||
// user wants vintage opacity, they'll be able to see what's under the
|
||||
// window.
|
||||
// * If we don't give it a background, then the BG will be entirely transparent.
|
||||
// * If we give the parent (us) root BG a color, then a transparent pane
|
||||
// will flash opaque during the animation, then back to transparent, which
|
||||
// looks bad.
|
||||
_secondChild->_root.Background(s_unfocusedBorderBrush);
|
||||
|
||||
const auto [firstSize, secondSize] = _CalcChildrenSizes(::base::saturated_cast<float>(totalSize));
|
||||
|
||||
// This is safe to capture this, because it's only being called in the
|
||||
|
@ -1938,11 +1949,12 @@ void Pane::_SetupEntranceAnimation()
|
|||
|
||||
// When the animation is completed, undo the trickiness from before, to
|
||||
// restore the controls to the behavior they'd usually have.
|
||||
animation.Completed([childGrid, control](auto&&, auto&&) {
|
||||
animation.Completed([childGrid, control, root = _secondChild->_root](auto&&, auto&&) {
|
||||
control.Width(NAN);
|
||||
childGrid.Width(NAN);
|
||||
childGrid.HorizontalAlignment(HorizontalAlignment::Stretch);
|
||||
control.HorizontalAlignment(HorizontalAlignment::Stretch);
|
||||
root.Background(nullptr);
|
||||
});
|
||||
}
|
||||
else
|
||||
|
@ -1956,11 +1968,12 @@ void Pane::_SetupEntranceAnimation()
|
|||
|
||||
// When the animation is completed, undo the trickiness from before, to
|
||||
// restore the controls to the behavior they'd usually have.
|
||||
animation.Completed([childGrid, control](auto&&, auto&&) {
|
||||
animation.Completed([childGrid, control, root = _secondChild->_root](auto&&, auto&&) {
|
||||
control.Height(NAN);
|
||||
childGrid.Height(NAN);
|
||||
childGrid.VerticalAlignment(VerticalAlignment::Stretch);
|
||||
control.VerticalAlignment(VerticalAlignment::Stretch);
|
||||
root.Background(nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace winrt::TerminalApp::implementation
|
|||
TraceLoggingBool(usedManualProfile, "ProfileSpecified", "Whether the new tab specified a profile explicitly"),
|
||||
TraceLoggingGuid(profile.Guid(), "ProfileGuid", "The GUID of the profile spawned in the new tab"),
|
||||
TraceLoggingBool(settings.DefaultSettings().UseAcrylic(), "UseAcrylic", "The acrylic preference from the settings"),
|
||||
TraceLoggingFloat64(settings.DefaultSettings().TintOpacity(), "TintOpacity", "Opacity preference from the settings"),
|
||||
TraceLoggingFloat64(settings.DefaultSettings().Opacity(), "TintOpacity", "Opacity preference from the settings"),
|
||||
TraceLoggingWideString(settings.DefaultSettings().FontFace().c_str(), "FontFace", "Font face chosen in the settings"),
|
||||
TraceLoggingWideString(schemeName.data(), "SchemeName", "Color scheme set in the settings"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
|
|
|
@ -376,13 +376,14 @@
|
|||
</ItemDefinitionGroup>
|
||||
<!-- ========================= Globals ======================== -->
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets'))" />
|
||||
</Target>
|
||||
|
|
|
@ -9,10 +9,11 @@
|
|||
xmlns:local="using:TerminalApp"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
|
||||
Background="Transparent"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid x:Name="Root"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
Background="Transparent">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
|
|
|
@ -1400,11 +1400,22 @@ namespace winrt::TerminalApp::implementation
|
|||
deselectedTabBrush.Color(deselectedTabColor);
|
||||
|
||||
// currently if a tab has a custom color, a deselected state is
|
||||
// signified by using the same color with a bit ot transparency
|
||||
// signified by using the same color with a bit of transparency
|
||||
//
|
||||
// Prior to MUX 2.7, we set TabViewItemHeaderBackground, but now we can
|
||||
// use TabViewItem().Background() for that. HOWEVER,
|
||||
// TabViewItem().Background() only sets the color of the tab background
|
||||
// when the TabViewItem is unselected. So we still need to set the other
|
||||
// properties ourselves.
|
||||
TabViewItem().Background(deselectedTabBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundSelected"), selectedTabBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackground"), deselectedTabBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPointerOver"), hoverTabBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPressed"), selectedTabBrush);
|
||||
|
||||
// TabViewItem().Foreground() unfortunately does not work for us. It
|
||||
// sets the color for the text when the TabViewItem isn't selected, but
|
||||
// not when it is hovered, pressed, dragged, or selected, so we'll need
|
||||
// to just set them all anyways.
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForeground"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundSelected"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundPointerOver"), fontBrush);
|
||||
|
@ -1442,7 +1453,6 @@ namespace winrt::TerminalApp::implementation
|
|||
void TerminalTab::_ClearTabBackgroundColor()
|
||||
{
|
||||
winrt::hstring keys[] = {
|
||||
L"TabViewItemHeaderBackground",
|
||||
L"TabViewItemHeaderBackgroundSelected",
|
||||
L"TabViewItemHeaderBackgroundPointerOver",
|
||||
L"TabViewItemHeaderForeground",
|
||||
|
@ -1463,6 +1473,9 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
}
|
||||
|
||||
// Clear out the Background.
|
||||
TabViewItem().Background(nullptr);
|
||||
|
||||
_RefreshVisualState();
|
||||
_colorCleared();
|
||||
}
|
||||
|
@ -1487,7 +1500,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// - <none>
|
||||
void TerminalTab::_RefreshVisualState()
|
||||
{
|
||||
if (_focusState != FocusState::Unfocused)
|
||||
if (TabViewItem().IsSelected())
|
||||
{
|
||||
VisualStateManager::GoToState(TabViewItem(), L"Normal", true);
|
||||
VisualStateManager::GoToState(TabViewItem(), L"Selected", true);
|
||||
|
|
|
@ -89,13 +89,13 @@
|
|||
</ItemGroup>
|
||||
|
||||
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
</Target>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.5.0-prerelease.201202003" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.0-prerelease.210913003" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
|
||||
</packages>
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
#include "LibraryResources.h"
|
||||
|
||||
using namespace ::Microsoft::Console;
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
// Format is: "DecimalResult (HexadecimalForm)"
|
||||
static constexpr auto _errorFormat = L"{0} ({0:#010x})"sv;
|
||||
|
||||
// Notes:
|
||||
// There is a number of ways that the Conpty connection can be terminated (voluntarily or not):
|
||||
|
@ -417,7 +421,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
const auto hr = wil::ResultFromCaughtException();
|
||||
|
||||
winrt::hstring failureText{ fmt::format(std::wstring_view{ RS_(L"ProcessFailedToLaunch") },
|
||||
gsl::narrow_cast<unsigned long>(hr),
|
||||
fmt::format(_errorFormat, hr),
|
||||
_commandline) };
|
||||
_TerminalOutputHandlers(failureText);
|
||||
|
||||
|
@ -444,7 +448,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
{
|
||||
try
|
||||
{
|
||||
winrt::hstring exitText{ fmt::format(std::wstring_view{ RS_(L"ProcessExited") }, status) };
|
||||
winrt::hstring exitText{ fmt::format(std::wstring_view{ RS_(L"ProcessExited") }, fmt::format(_errorFormat, status)) };
|
||||
_TerminalOutputHandlers(L"\r\n");
|
||||
_TerminalOutputHandlers(exitText);
|
||||
}
|
||||
|
|
|
@ -205,15 +205,15 @@
|
|||
</data>
|
||||
<data name="ProcessExited" xml:space="preserve">
|
||||
<value>[process exited with code {0}]</value>
|
||||
<comment>The first argument {0} is the (positive) error code of the process. When there is no error, the number ZERO will be displayed.</comment>
|
||||
<comment>The first argument {0} is the error code of the process. When there is no error, the number ZERO will be displayed. </comment>
|
||||
</data>
|
||||
<data name="ProcessFailedToLaunch" xml:space="preserve">
|
||||
<value>[error {0:#08x} when launching `{1}']</value>
|
||||
<comment>The first argument {0...} is the hexadecimal error code. The second argument {1} is the user-specified path to a program.
|
||||
<value>[error {0} when launching `{1}']</value>
|
||||
<comment>The first argument {0} is the error code. The second argument {1} is the user-specified path to a program.
|
||||
If this string is broken to multiple lines, it will not be displayed properly.</comment>
|
||||
</data>
|
||||
<data name="BadPathText" xml:space="preserve">
|
||||
<value>Could not access starting directory "{0}"</value>
|
||||
<comment>The first argument {0} is a path to a directory on the filesystem, as provided by the user.</comment>
|
||||
</data>
|
||||
</root>
|
||||
</root>
|
||||
|
|
|
@ -56,7 +56,9 @@
|
|||
<Midl Include="AzureConnection.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Resources\en-US\Resources.resw" />
|
||||
<PRIResource Include="Resources\en-US\Resources.resw">
|
||||
<SubType>Designer</SubType>
|
||||
</PRIResource>
|
||||
<OCResourceDirectory Include="Resources" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
|
@ -88,11 +90,11 @@
|
|||
</Target>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(IntDir)..\OpenConsoleProxy;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(IntDir)..\OpenConsoleProxy;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>$(OpenConsoleCommonOutDir)\conptylib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||
</Project>
|
||||
</Project>
|
|
@ -32,6 +32,7 @@
|
|||
<Midl Include="EchoConnection.idl" />
|
||||
<Midl Include="AzureConnection.idl" />
|
||||
<Midl Include="ConptyConnection.idl" />
|
||||
<Midl Include="ConnectionInformation.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
|
|
@ -276,7 +276,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// GH#5098: Inform the engine of the opacity of the default text background.
|
||||
if (_settings.UseAcrylic())
|
||||
{
|
||||
_renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast<float>(_settings.TintOpacity()));
|
||||
_renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast<float>(_settings.Opacity()));
|
||||
}
|
||||
|
||||
THROW_IF_FAILED(_renderEngine->Enable());
|
||||
|
@ -425,41 +425,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
return;
|
||||
}
|
||||
|
||||
auto newOpacity = std::clamp(_settings.TintOpacity() + adjustment,
|
||||
auto newOpacity = std::clamp(_settings.Opacity() + adjustment,
|
||||
0.0,
|
||||
1.0);
|
||||
if (_settings.UseAcrylic())
|
||||
{
|
||||
try
|
||||
{
|
||||
_settings.TintOpacity(newOpacity);
|
||||
|
||||
if (newOpacity >= 1.0)
|
||||
{
|
||||
_settings.UseAcrylic(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// GH#5098: Inform the engine of the new opacity of the default text background.
|
||||
SetBackgroundOpacity(::base::saturated_cast<float>(newOpacity));
|
||||
}
|
||||
// GH#5098: Inform the engine of the new opacity of the default text background.
|
||||
SetBackgroundOpacity(::base::saturated_cast<float>(newOpacity));
|
||||
|
||||
auto eventArgs = winrt::make_self<TransparencyChangedEventArgs>(newOpacity);
|
||||
_TransparencyChangedHandlers(*this, *eventArgs);
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
else if (adjustment < 0)
|
||||
{
|
||||
_settings.UseAcrylic(true);
|
||||
_settings.Opacity(newOpacity);
|
||||
|
||||
//Setting initial opacity set to 1 to ensure smooth transition to acrylic during mouse scroll
|
||||
newOpacity = std::clamp(1.0 + adjustment, 0.0, 1.0);
|
||||
_settings.TintOpacity(newOpacity);
|
||||
|
||||
auto eventArgs = winrt::make_self<TransparencyChangedEventArgs>(newOpacity);
|
||||
_TransparencyChangedHandlers(*this, *eventArgs);
|
||||
}
|
||||
auto eventArgs = winrt::make_self<TransparencyChangedEventArgs>(newOpacity);
|
||||
_TransparencyChangedHandlers(*this, *eventArgs);
|
||||
}
|
||||
|
||||
void ControlCore::ToggleShaderEffects()
|
||||
|
@ -1003,6 +979,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
{
|
||||
_terminal->WritePastedText(hstr);
|
||||
_terminal->ClearSelection();
|
||||
_renderer->TriggerSelection();
|
||||
_terminal->TrySnapOnInput();
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace Microsoft.Terminal.Control
|
|||
Windows.UI.Xaml.VerticalAlignment BackgroundImageVerticalAlignment;
|
||||
Boolean IntenseIsBold;
|
||||
// IntenseIsBright is in Core Appearance
|
||||
Double Opacity;
|
||||
|
||||
// Experimental settings
|
||||
Boolean RetroTerminalEffect;
|
||||
|
|
|
@ -29,7 +29,6 @@ namespace Microsoft.Terminal.Control
|
|||
String ProfileName;
|
||||
|
||||
Boolean UseAcrylic;
|
||||
Double TintOpacity;
|
||||
ScrollbarState ScrollState;
|
||||
|
||||
String FontFace;
|
||||
|
|
|
@ -428,6 +428,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// - <none>
|
||||
void TermControl::_InitializeBackgroundBrush()
|
||||
{
|
||||
auto appearance = _settings.try_as<IControlAppearance>();
|
||||
if (_settings.UseAcrylic())
|
||||
{
|
||||
// See if we've already got an acrylic background brush
|
||||
|
@ -449,7 +450,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
acrylic.TintColor(bgColor);
|
||||
|
||||
// Apply brush settings
|
||||
acrylic.TintOpacity(_settings.TintOpacity());
|
||||
acrylic.TintOpacity(appearance.Opacity());
|
||||
|
||||
// Apply brush to control if it's not already there
|
||||
if (RootGrid().Background() != acrylic)
|
||||
|
@ -458,15 +459,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
}
|
||||
|
||||
// GH#5098: Inform the engine of the new opacity of the default text background.
|
||||
_core.SetBackgroundOpacity(::base::saturated_cast<float>(_settings.TintOpacity()));
|
||||
_core.SetBackgroundOpacity(::base::saturated_cast<float>(appearance.Opacity()));
|
||||
}
|
||||
else
|
||||
{
|
||||
Media::SolidColorBrush solidColor{};
|
||||
solidColor.Opacity(_settings.Opacity());
|
||||
RootGrid().Background(solidColor);
|
||||
|
||||
// GH#5098: Inform the engine of the new opacity of the default text background.
|
||||
_core.SetBackgroundOpacity(1.0f);
|
||||
_core.SetBackgroundOpacity(appearance.Opacity());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -497,7 +499,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
}
|
||||
else if (auto solidColor = RootGrid().Background().try_as<Media::SolidColorBrush>())
|
||||
{
|
||||
const auto originalOpacity = solidColor.Opacity();
|
||||
solidColor.Color(bg);
|
||||
solidColor.Opacity(originalOpacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
d:DesignWidth="1024"
|
||||
AllowDrop="True"
|
||||
AllowFocusOnInteraction="True"
|
||||
Background="Transparent"
|
||||
CharacterReceived="_CharacterHandler"
|
||||
DragOver="_DragOverHandler"
|
||||
Drop="_DragDropHandler"
|
||||
|
|
|
@ -34,7 +34,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
void Launch::OnNavigatedTo(const NavigationEventArgs& e)
|
||||
{
|
||||
_State = e.Parameter().as<Editor::LaunchPageNavigationState>();
|
||||
_State.Settings().RefreshDefaultTerminals();
|
||||
}
|
||||
|
||||
IInspectable Launch::CurrentDefaultProfile()
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
x:Uid="Globals_DefaultTerminal"
|
||||
x:Load="false">
|
||||
<ComboBox x:Name="DefaultTerminal"
|
||||
ItemsSource="{x:Bind State.Settings.DefaultTerminals, Mode=OneWay}"
|
||||
ItemsSource="{x:Bind State.Settings.DefaultTerminals}"
|
||||
SelectedItem="{x:Bind State.Settings.CurrentDefaultTerminal, Mode=TwoWay}"
|
||||
Style="{StaticResource ComboBoxSettingStyle}">
|
||||
<ComboBox.ItemTemplate>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Page.Resources>
|
||||
|
|
|
@ -312,12 +312,12 @@
|
|||
</ItemDefinitionGroup>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||
</Project>
|
|
@ -22,7 +22,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
|
||||
void SetAcrylicOpacityPercentageValue(double value)
|
||||
{
|
||||
AcrylicOpacity(winrt::Microsoft::Terminal::Settings::Editor::Converters::PercentageValueToPercentage(value));
|
||||
_profile.DefaultAppearance().Opacity(winrt::Microsoft::Terminal::Settings::Editor::Converters::PercentageValueToPercentage(value));
|
||||
};
|
||||
|
||||
void SetPadding(double value)
|
||||
|
@ -66,7 +66,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
OBSERVABLE_PROJECTED_SETTING(_profile, TabColor);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, SuppressApplicationTitle);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, UseAcrylic);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, AcrylicOpacity);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, ScrollState);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, Padding);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, Commandline);
|
||||
|
@ -78,6 +77,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Background);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), SelectionBackground);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), CursorColor);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Opacity);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, HistorySize);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, SnapOnInput);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, AltGrAliasing);
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, TabColor);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SuppressApplicationTitle);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, UseAcrylic);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Double, AcrylicOpacity);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Double, Opacity);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.ScrollbarState, ScrollState);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Padding);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Commandline);
|
||||
|
@ -109,6 +109,6 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||
IInspectable CurrentScrollState;
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> ScrollStateList { get; };
|
||||
|
||||
Windows.UI.Xaml.Controls.Slider AcrylicOpacitySlider { get; };
|
||||
Windows.UI.Xaml.Controls.Slider OpacitySlider { get; };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -238,11 +238,33 @@
|
|||
<local:Appearances Appearance="{x:Bind State.Profile.DefaultAppearance, Mode=OneWay}"
|
||||
SourceProfile="{x:Bind State.Profile, Mode=OneWay}" />
|
||||
|
||||
<!-- Grouping: Acrylic -->
|
||||
<!-- Grouping: Transparency -->
|
||||
<StackPanel Style="{StaticResource PivotStackStyle}">
|
||||
<TextBlock x:Uid="Profile_AcrylicHeader"
|
||||
<TextBlock x:Uid="Profile_TransparencyHeader"
|
||||
Style="{StaticResource SubtitleTextBlockStyle}" />
|
||||
|
||||
<!-- Opacity -->
|
||||
<local:SettingContainer x:Name="OpacityContainer"
|
||||
x:Uid="Profile_Opacity"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearOpacity}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasOpacity, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.OpacityOverrideSource, Mode=OneWay}">
|
||||
<StackPanel x:Name="OpacityControl">
|
||||
<Grid Style="{StaticResource CustomSliderControlGridStyle}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Slider x:Name="OpacitySlider"
|
||||
Grid.Column="0"
|
||||
Value="{x:Bind local:Converters.PercentageToPercentageValue(State.Profile.Opacity), BindBack=State.Profile.SetAcrylicOpacityPercentageValue, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Style="{StaticResource SliderValueLabelStyle}"
|
||||
Text="{x:Bind local:Converters.AppendPercentageSign(OpacitySlider.Value), Mode=OneWay}" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Use Acrylic -->
|
||||
<local:SettingContainer x:Uid="Profile_UseAcrylic"
|
||||
Margin="0"
|
||||
|
@ -253,28 +275,6 @@
|
|||
IsOn="{x:Bind State.Profile.UseAcrylic, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Acrylic Opacity -->
|
||||
<local:SettingContainer x:Name="AcrylicOpacityContainer"
|
||||
x:Uid="Profile_AcrylicOpacity"
|
||||
ClearSettingValue="{x:Bind State.Profile.ClearAcrylicOpacity}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasAcrylicOpacity, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.AcrylicOpacityOverrideSource, Mode=OneWay}"
|
||||
Visibility="{Binding ElementName=UseAcrylicToggleSwitch, Path=IsOn, Mode=OneWay}">
|
||||
<StackPanel x:Name="AcrylicOpacityControl">
|
||||
<Grid Style="{StaticResource CustomSliderControlGridStyle}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Slider x:Name="AcrylicOpacitySlider"
|
||||
Grid.Column="0"
|
||||
Value="{x:Bind local:Converters.PercentageToPercentageValue(State.Profile.AcrylicOpacity), BindBack=State.Profile.SetAcrylicOpacityPercentageValue, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Style="{StaticResource SliderValueLabelStyle}"
|
||||
Text="{x:Bind local:Converters.AppendPercentageSign(AcrylicOpacitySlider.Value), Mode=OneWay}" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</local:SettingContainer>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Grouping: Window -->
|
||||
|
|
|
@ -495,6 +495,14 @@
|
|||
<value>Sets the transparency of the window.</value>
|
||||
<comment>A description for what the "acrylic opacity" setting does. Presented near "Profile_AcrylicOpacity.Header".</comment>
|
||||
</data>
|
||||
<data name="Profile_Opacity.Header" xml:space="preserve">
|
||||
<value>Background Opacity</value>
|
||||
<comment>Header for a control to determine the level of opacity for the background of the control. The user can choose to make the background of the app more or less opaque.</comment>
|
||||
</data>
|
||||
<data name="Profile_Opacity.HelpText" xml:space="preserve">
|
||||
<value>Sets the transparency of the window.</value>
|
||||
<comment>A description for what the "opacity" setting does. Presented near "Profile_Opacity.Header".</comment>
|
||||
</data>
|
||||
<data name="Profile_Advanced.Header" xml:space="preserve">
|
||||
<value>Advanced</value>
|
||||
<comment>Header for a sub-page of profile settings focused on more advanced scenarios.</comment>
|
||||
|
@ -986,6 +994,10 @@
|
|||
<value>Acrylic</value>
|
||||
<comment>Header for a group of settings related to the acrylic texture rendering on the background of the app.</comment>
|
||||
</data>
|
||||
<data name="Profile_TransparencyHeader.Text" xml:space="preserve">
|
||||
<value>Transparency</value>
|
||||
<comment>Header for a group of settings related to transparency, including the acrylic texture rendering on the background of the app.</comment>
|
||||
</data>
|
||||
<data name="Profile_BackgroundHeader.Text" xml:space="preserve">
|
||||
<value>Background image</value>
|
||||
<comment>Header for a group of settings that control the image presented on the background of the app. Presented near "Profile_BackgroundImage" and other keys starting with "Profile_BackgroundImage".</comment>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.UI.Xaml" version="2.5.0-prerelease.201202003" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.0-prerelease.210913003" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
|
||||
</packages>
|
||||
|
|
|
@ -26,30 +26,32 @@ static constexpr std::string_view BackgroundImageAlignmentKey{ "backgroundImageA
|
|||
static constexpr std::string_view RetroTerminalEffectKey{ "experimental.retroTerminalEffect" };
|
||||
static constexpr std::string_view PixelShaderPathKey{ "experimental.pixelShaderPath" };
|
||||
static constexpr std::string_view IntenseTextStyleKey{ "intenseTextStyle" };
|
||||
static constexpr std::string_view LegacyAcrylicTransparencyKey{ "acrylicOpacity" };
|
||||
static constexpr std::string_view OpacityKey{ "opacity" };
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::Model::implementation::AppearanceConfig::AppearanceConfig(const winrt::weak_ref<Profile> sourceProfile) :
|
||||
_sourceProfile(sourceProfile)
|
||||
AppearanceConfig::AppearanceConfig(winrt::weak_ref<Profile> sourceProfile) :
|
||||
_sourceProfile(std::move(sourceProfile))
|
||||
{
|
||||
}
|
||||
|
||||
winrt::com_ptr<AppearanceConfig> AppearanceConfig::CopyAppearance(const winrt::com_ptr<AppearanceConfig> source, const winrt::weak_ref<Profile> sourceProfile)
|
||||
winrt::com_ptr<AppearanceConfig> AppearanceConfig::CopyAppearance(const AppearanceConfig* source, winrt::weak_ref<Profile> sourceProfile)
|
||||
{
|
||||
auto appearance{ winrt::make_self<AppearanceConfig>(sourceProfile) };
|
||||
auto const sourceAppearance = source.try_as<AppearanceConfig>();
|
||||
appearance->_BackgroundImagePath = sourceAppearance->_BackgroundImagePath;
|
||||
appearance->_BackgroundImageOpacity = sourceAppearance->_BackgroundImageOpacity;
|
||||
appearance->_BackgroundImageStretchMode = sourceAppearance->_BackgroundImageStretchMode;
|
||||
appearance->_ColorSchemeName = sourceAppearance->_ColorSchemeName;
|
||||
appearance->_Foreground = sourceAppearance->_Foreground;
|
||||
appearance->_Background = sourceAppearance->_Background;
|
||||
appearance->_SelectionBackground = sourceAppearance->_SelectionBackground;
|
||||
appearance->_CursorColor = sourceAppearance->_CursorColor;
|
||||
appearance->_CursorShape = sourceAppearance->_CursorShape;
|
||||
appearance->_CursorHeight = sourceAppearance->_CursorHeight;
|
||||
appearance->_BackgroundImageAlignment = sourceAppearance->_BackgroundImageAlignment;
|
||||
appearance->_RetroTerminalEffect = sourceAppearance->_RetroTerminalEffect;
|
||||
appearance->_PixelShaderPath = sourceAppearance->_PixelShaderPath;
|
||||
appearance->_IntenseTextStyle = sourceAppearance->_IntenseTextStyle;
|
||||
auto appearance{ winrt::make_self<AppearanceConfig>(std::move(sourceProfile)) };
|
||||
appearance->_BackgroundImagePath = source->_BackgroundImagePath;
|
||||
appearance->_BackgroundImageOpacity = source->_BackgroundImageOpacity;
|
||||
appearance->_BackgroundImageStretchMode = source->_BackgroundImageStretchMode;
|
||||
appearance->_ColorSchemeName = source->_ColorSchemeName;
|
||||
appearance->_Foreground = source->_Foreground;
|
||||
appearance->_Background = source->_Background;
|
||||
appearance->_SelectionBackground = source->_SelectionBackground;
|
||||
appearance->_CursorColor = source->_CursorColor;
|
||||
appearance->_CursorShape = source->_CursorShape;
|
||||
appearance->_CursorHeight = source->_CursorHeight;
|
||||
appearance->_BackgroundImageAlignment = source->_BackgroundImageAlignment;
|
||||
appearance->_RetroTerminalEffect = source->_RetroTerminalEffect;
|
||||
appearance->_PixelShaderPath = source->_PixelShaderPath;
|
||||
appearance->_IntenseTextStyle = source->_IntenseTextStyle;
|
||||
appearance->_Opacity = source->_Opacity;
|
||||
return appearance;
|
||||
}
|
||||
|
||||
|
@ -71,6 +73,7 @@ Json::Value AppearanceConfig::ToJson() const
|
|||
JsonUtils::SetValueForKey(json, RetroTerminalEffectKey, _RetroTerminalEffect);
|
||||
JsonUtils::SetValueForKey(json, PixelShaderPathKey, _PixelShaderPath);
|
||||
JsonUtils::SetValueForKey(json, IntenseTextStyleKey, _IntenseTextStyle);
|
||||
JsonUtils::SetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<double, IntAsFloatPercentConversionTrait>{});
|
||||
|
||||
return json;
|
||||
}
|
||||
|
@ -102,6 +105,8 @@ void AppearanceConfig::LayerJson(const Json::Value& json)
|
|||
JsonUtils::GetValueForKey(json, RetroTerminalEffectKey, _RetroTerminalEffect);
|
||||
JsonUtils::GetValueForKey(json, PixelShaderPathKey, _PixelShaderPath);
|
||||
JsonUtils::GetValueForKey(json, IntenseTextStyleKey, _IntenseTextStyle);
|
||||
JsonUtils::GetValueForKey(json, LegacyAcrylicTransparencyKey, _Opacity);
|
||||
JsonUtils::GetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<double, IntAsFloatPercentConversionTrait>{});
|
||||
}
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::Model::Profile AppearanceConfig::SourceProfile()
|
||||
|
|
|
@ -18,7 +18,6 @@ Author(s):
|
|||
|
||||
#include "AppearanceConfig.g.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
#include "IInheritable.h"
|
||||
#include <DefaultSettings.h>
|
||||
|
||||
|
@ -27,8 +26,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
struct AppearanceConfig : AppearanceConfigT<AppearanceConfig>, IInheritable<AppearanceConfig>
|
||||
{
|
||||
public:
|
||||
AppearanceConfig(const winrt::weak_ref<Profile> sourceProfile);
|
||||
static winrt::com_ptr<AppearanceConfig> CopyAppearance(const winrt::com_ptr<AppearanceConfig> source, const winrt::weak_ref<Profile> sourceProfile);
|
||||
AppearanceConfig(winrt::weak_ref<Profile> sourceProfile);
|
||||
static winrt::com_ptr<AppearanceConfig> CopyAppearance(const AppearanceConfig* source, winrt::weak_ref<Profile> sourceProfile);
|
||||
Json::Value ToJson() const;
|
||||
void LayerJson(const Json::Value& json);
|
||||
|
||||
|
@ -53,6 +52,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
INHERITABLE_SETTING(Model::IAppearanceConfig, bool, RetroTerminalEffect, false);
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, hstring, PixelShaderPath, L"");
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, Model::IntenseStyle, IntenseTextStyle, Model::IntenseStyle::Bright);
|
||||
INHERITABLE_SETTING(Model::IAppearanceConfig, double, Opacity, 1.0);
|
||||
|
||||
private:
|
||||
winrt::weak_ref<Profile> _sourceProfile;
|
||||
|
|
|
@ -6,16 +6,14 @@
|
|||
#include "AzureCloudShellGenerator.h"
|
||||
#include "LegacyProfileGeneratorNamespaces.h"
|
||||
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "../../inc/DefaultSettings.h"
|
||||
#include "Utils.h"
|
||||
#include "DefaultProfileUtils.h"
|
||||
#include "DynamicProfileUtils.h"
|
||||
|
||||
using namespace ::Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::Terminal::TerminalConnection;
|
||||
|
||||
std::wstring_view AzureCloudShellGenerator::GetNamespace()
|
||||
std::wstring_view AzureCloudShellGenerator::GetNamespace() const noexcept
|
||||
{
|
||||
return AzureGeneratorNamespace;
|
||||
}
|
||||
|
@ -27,19 +25,14 @@ std::wstring_view AzureCloudShellGenerator::GetNamespace()
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - a vector with the Azure Cloud Shell connection profile, if available.
|
||||
std::vector<Profile> AzureCloudShellGenerator::GenerateProfiles()
|
||||
void AzureCloudShellGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const
|
||||
{
|
||||
std::vector<Profile> profiles;
|
||||
|
||||
if (AzureConnection::IsAzureConnectionAvailable())
|
||||
{
|
||||
auto azureCloudShellProfile{ CreateDefaultProfile(L"Azure Cloud Shell") };
|
||||
azureCloudShellProfile.Commandline(L"Azure");
|
||||
azureCloudShellProfile.StartingDirectory(DEFAULT_STARTING_DIRECTORY);
|
||||
azureCloudShellProfile.DefaultAppearance().ColorSchemeName(L"Vintage");
|
||||
azureCloudShellProfile.ConnectionType(AzureConnection::ConnectionType());
|
||||
profiles.emplace_back(azureCloudShellProfile);
|
||||
auto azureCloudShellProfile{ CreateDynamicProfile(L"Azure Cloud Shell") };
|
||||
azureCloudShellProfile->StartingDirectory(winrt::hstring{ DEFAULT_STARTING_DIRECTORY });
|
||||
azureCloudShellProfile->DefaultAppearance().ColorSchemeName(L"Vintage");
|
||||
azureCloudShellProfile->ConnectionType(AzureConnection::ConnectionType());
|
||||
profiles.emplace_back(std::move(azureCloudShellProfile));
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
|
|
|
@ -16,17 +16,15 @@ Author(s):
|
|||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IDynamicProfileGenerator.h"
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
class AzureCloudShellGenerator : public IDynamicProfileGenerator
|
||||
class AzureCloudShellGenerator final : public IDynamicProfileGenerator
|
||||
{
|
||||
public:
|
||||
AzureCloudShellGenerator() = default;
|
||||
~AzureCloudShellGenerator() = default;
|
||||
std::wstring_view GetNamespace() override;
|
||||
|
||||
std::vector<winrt::Microsoft::Terminal::Settings::Model::Profile> GenerateProfiles() override;
|
||||
std::wstring_view GetNamespace() const noexcept override;
|
||||
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const override;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -3,15 +3,12 @@
|
|||
|
||||
#include "pch.h"
|
||||
#include "BaseVisualStudioGenerator.h"
|
||||
#include "DefaultProfileUtils.h"
|
||||
#include "DynamicProfileUtils.h"
|
||||
|
||||
using namespace Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
std::vector<Profile> BaseVisualStudioGenerator::GenerateProfiles()
|
||||
void BaseVisualStudioGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const
|
||||
{
|
||||
std::vector<Profile> profiles;
|
||||
|
||||
// There's no point in enumerating valid Visual Studio instances more than once,
|
||||
// so cache them for use by both Visual Studio profile generators.
|
||||
static const auto instances = VsSetupConfiguration::QueryInstances();
|
||||
|
@ -25,27 +22,15 @@ std::vector<Profile> BaseVisualStudioGenerator::GenerateProfiles()
|
|||
continue;
|
||||
}
|
||||
|
||||
auto DevShell{ CreateProfile(GetProfileGuidSeed(instance)) };
|
||||
DevShell.Name(GetProfileName(instance));
|
||||
DevShell.Commandline(GetProfileCommandLine(instance));
|
||||
DevShell.StartingDirectory(instance.GetInstallationPath());
|
||||
DevShell.Icon(GetProfileIconPath());
|
||||
|
||||
profiles.emplace_back(DevShell);
|
||||
const auto seed = GetProfileGuidSeed(instance);
|
||||
const winrt::guid profileGuid{ ::Microsoft::Console::Utils::CreateV5Uuid(TERMINAL_PROFILE_NAMESPACE_GUID, gsl::as_bytes(gsl::make_span(seed))) };
|
||||
auto profile = winrt::make_self<implementation::Profile>(profileGuid);
|
||||
profile->Name(winrt::hstring{ GetProfileName(instance) });
|
||||
profile->Commandline(winrt::hstring{ GetProfileCommandLine(instance) });
|
||||
profile->StartingDirectory(winrt::hstring{ instance.GetInstallationPath() });
|
||||
profile->Icon(winrt::hstring{ GetProfileIconPath() });
|
||||
profiles.emplace_back(std::move(profile));
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
|
||||
Profile BaseVisualStudioGenerator::CreateProfile(const std::wstring_view seed)
|
||||
{
|
||||
const winrt::guid profileGuid{ Microsoft::Console::Utils::CreateV5Uuid(TERMINAL_PROFILE_NAMESPACE_GUID,
|
||||
gsl::as_bytes(gsl::make_span(seed))) };
|
||||
|
||||
auto newProfile = winrt::make_self<implementation::Profile>(profileGuid);
|
||||
newProfile->Origin(OriginTag::Generated);
|
||||
|
||||
return *newProfile;
|
||||
}
|
||||
|
|
|
@ -18,14 +18,12 @@ Author(s):
|
|||
#include "IDynamicProfileGenerator.h"
|
||||
#include "VsSetupConfiguration.h"
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
class BaseVisualStudioGenerator : public IDynamicProfileGenerator
|
||||
{
|
||||
public:
|
||||
// Inherited via IDynamicProfileGenerator
|
||||
std::wstring_view GetNamespace() override = 0;
|
||||
std::vector<winrt::Microsoft::Terminal::Settings::Model::Profile> GenerateProfiles() override;
|
||||
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const override;
|
||||
|
||||
protected:
|
||||
virtual bool IsInstanceValid(const VsSetupConfiguration::VsSetupInstance& instance) const = 0;
|
||||
|
@ -33,8 +31,5 @@ namespace Microsoft::Terminal::Settings::Model
|
|||
virtual std::wstring GetProfileCommandLine(const VsSetupConfiguration::VsSetupInstance& instance) const = 0;
|
||||
virtual std::wstring GetProfileGuidSeed(const VsSetupConfiguration::VsSetupInstance& instance) const = 0;
|
||||
virtual std::wstring GetProfileIconPath() const = 0;
|
||||
|
||||
private:
|
||||
winrt::Microsoft::Terminal::Settings::Model::Profile CreateProfile(const std::wstring_view instanceId);
|
||||
};
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,163 +20,137 @@ Author(s):
|
|||
#include "CascadiaSettings.g.h"
|
||||
|
||||
#include "GlobalAppSettings.h"
|
||||
#include "TerminalWarnings.h"
|
||||
#include "IDynamicProfileGenerator.h"
|
||||
|
||||
#include "Profile.h"
|
||||
#include "ColorScheme.h"
|
||||
|
||||
// fwdecl unittest classes
|
||||
namespace SettingsModelLocalTests
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
class SerializationTests;
|
||||
class DeserializationTests;
|
||||
class ProfileTests;
|
||||
class ColorSchemeTests;
|
||||
class KeyBindingsTests;
|
||||
};
|
||||
namespace TerminalAppUnitTests
|
||||
{
|
||||
class DynamicProfileTests;
|
||||
class JsonTests;
|
||||
};
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
class SettingsTypedDeserializationException;
|
||||
};
|
||||
|
||||
class Microsoft::Terminal::Settings::Model::SettingsTypedDeserializationException final : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
SettingsTypedDeserializationException(const std::string_view description) :
|
||||
runtime_error(description.data()) {}
|
||||
};
|
||||
class IDynamicProfileGenerator;
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
winrt::com_ptr<Profile> CreateChild(const winrt::com_ptr<Profile>& parent);
|
||||
|
||||
class SettingsTypedDeserializationException final : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
SettingsTypedDeserializationException(const char* message) noexcept :
|
||||
std::runtime_error(message) {}
|
||||
};
|
||||
|
||||
struct ParsedSettings
|
||||
{
|
||||
winrt::com_ptr<implementation::GlobalAppSettings> globals;
|
||||
winrt::com_ptr<implementation::Profile> baseLayerProfile;
|
||||
std::vector<winrt::com_ptr<implementation::Profile>> profiles;
|
||||
std::unordered_map<winrt::guid, winrt::com_ptr<implementation::Profile>> profilesByGuid;
|
||||
};
|
||||
|
||||
struct SettingsLoader
|
||||
{
|
||||
static SettingsLoader Default(const std::string_view& userJSON, const std::string_view& inboxJSON);
|
||||
SettingsLoader(const std::string_view& userJSON, const std::string_view& inboxJSON);
|
||||
|
||||
void GenerateProfiles();
|
||||
void ApplyRuntimeInitialSettings();
|
||||
void MergeInboxIntoUserSettings();
|
||||
void FindFragmentsAndMergeIntoUserSettings();
|
||||
void FinalizeLayering();
|
||||
bool DisableDeletedProfiles();
|
||||
|
||||
ParsedSettings inboxSettings;
|
||||
ParsedSettings userSettings;
|
||||
bool duplicateProfile = false;
|
||||
|
||||
private:
|
||||
static std::pair<size_t, size_t> _lineAndColumnFromPosition(const std::string_view& string, const size_t position);
|
||||
static void _rethrowSerializationExceptionWithLocationInfo(const JsonUtils::DeserializationError& e, const std::string_view& settingsString);
|
||||
static Json::Value _parseJSON(const std::string_view& content);
|
||||
static const Json::Value& _getJSONValue(const Json::Value& json, const std::string_view& key) noexcept;
|
||||
static bool _isValidProfileObject(const Json::Value& profileJson);
|
||||
gsl::span<const winrt::com_ptr<implementation::Profile>> _getNonUserOriginProfiles() const;
|
||||
void _parse(const OriginTag origin, const winrt::hstring& source, const std::string_view& content, ParsedSettings& settings);
|
||||
void _appendProfile(winrt::com_ptr<implementation::Profile>&& profile, ParsedSettings& settings);
|
||||
void _executeGenerator(const IDynamicProfileGenerator& generator);
|
||||
|
||||
std::unordered_set<std::wstring_view> _ignoredNamespaces;
|
||||
// See _getNonUserOriginProfiles().
|
||||
size_t _userProfileCount = 0;
|
||||
};
|
||||
|
||||
struct CascadiaSettings : CascadiaSettingsT<CascadiaSettings>
|
||||
{
|
||||
public:
|
||||
CascadiaSettings();
|
||||
explicit CascadiaSettings(const bool addDynamicProfiles);
|
||||
CascadiaSettings(hstring json);
|
||||
Model::CascadiaSettings Copy() const;
|
||||
|
||||
static Model::CascadiaSettings LoadDefaults();
|
||||
static Model::CascadiaSettings LoadAll();
|
||||
static Model::CascadiaSettings LoadUniversal();
|
||||
|
||||
Model::GlobalAppSettings GlobalSettings() const;
|
||||
Windows::Foundation::Collections::IObservableVector<Model::Profile> AllProfiles() const noexcept;
|
||||
Windows::Foundation::Collections::IObservableVector<Model::Profile> ActiveProfiles() const noexcept;
|
||||
Model::ActionMap ActionMap() const noexcept;
|
||||
|
||||
static com_ptr<CascadiaSettings> FromJson(const Json::Value& json);
|
||||
void LayerJson(const Json::Value& json);
|
||||
|
||||
void WriteSettingsToDisk() const;
|
||||
Json::Value ToJson() const;
|
||||
|
||||
static hstring SettingsPath();
|
||||
static hstring DefaultSettingsPath();
|
||||
Model::Profile ProfileDefaults() const;
|
||||
|
||||
static winrt::hstring SettingsPath();
|
||||
static winrt::hstring DefaultSettingsPath();
|
||||
static winrt::hstring ApplicationDisplayName();
|
||||
static winrt::hstring ApplicationVersion();
|
||||
|
||||
CascadiaSettings() noexcept = default;
|
||||
CascadiaSettings(const winrt::hstring& userJSON, const winrt::hstring& inboxJSON);
|
||||
CascadiaSettings(const std::string_view& userJSON, const std::string_view& inboxJSON = {});
|
||||
explicit CascadiaSettings(SettingsLoader&& loader);
|
||||
|
||||
// user settings
|
||||
Model::CascadiaSettings Copy() const;
|
||||
Model::GlobalAppSettings GlobalSettings() const;
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<Model::Profile> AllProfiles() const noexcept;
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<Model::Profile> ActiveProfiles() const noexcept;
|
||||
Model::ActionMap ActionMap() const noexcept;
|
||||
void WriteSettingsToDisk() const;
|
||||
Json::Value ToJson() const;
|
||||
Model::Profile ProfileDefaults() const;
|
||||
Model::Profile CreateNewProfile();
|
||||
Model::Profile FindProfile(const guid& profileGuid) const noexcept;
|
||||
Model::Profile FindProfile(const winrt::guid& guid) const noexcept;
|
||||
Model::ColorScheme GetColorSchemeForProfile(const Model::Profile& profile) const;
|
||||
void UpdateColorSchemeReferences(const hstring oldName, const hstring newName);
|
||||
|
||||
Windows::Foundation::Collections::IVectorView<SettingsLoadWarnings> Warnings();
|
||||
void ClearWarnings();
|
||||
void AppendWarning(SettingsLoadWarnings warning);
|
||||
Windows::Foundation::IReference<SettingsLoadErrors> GetLoadingError();
|
||||
hstring GetSerializationErrorMessage();
|
||||
|
||||
void UpdateColorSchemeReferences(const winrt::hstring& oldName, const winrt::hstring& newName);
|
||||
Model::Profile GetProfileForArgs(const Model::NewTerminalArgs& newTerminalArgs) const;
|
||||
|
||||
Model::Profile GetProfileByName(const winrt::hstring& name) const;
|
||||
Model::Profile GetProfileByIndex(uint32_t index) const;
|
||||
Model::Profile DuplicateProfile(const Model::Profile& source);
|
||||
void RefreshDefaultTerminals();
|
||||
|
||||
// load errors
|
||||
winrt::Windows::Foundation::Collections::IVectorView<Model::SettingsLoadWarnings> Warnings() const;
|
||||
winrt::Windows::Foundation::IReference<Model::SettingsLoadErrors> GetLoadingError() const;
|
||||
winrt::hstring GetSerializationErrorMessage() const;
|
||||
|
||||
// defterm
|
||||
static bool IsDefaultTerminalAvailable() noexcept;
|
||||
Windows::Foundation::Collections::IObservableVector<Model::DefaultTerminal> DefaultTerminals() const noexcept;
|
||||
Model::DefaultTerminal CurrentDefaultTerminal() const noexcept;
|
||||
void CurrentDefaultTerminal(Model::DefaultTerminal terminal);
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<Model::DefaultTerminal> DefaultTerminals() const noexcept;
|
||||
Model::DefaultTerminal CurrentDefaultTerminal() noexcept;
|
||||
void CurrentDefaultTerminal(const Model::DefaultTerminal& terminal);
|
||||
|
||||
private:
|
||||
com_ptr<GlobalAppSettings> _globals;
|
||||
Windows::Foundation::Collections::IObservableVector<Model::Profile> _allProfiles;
|
||||
Windows::Foundation::Collections::IObservableVector<Model::Profile> _activeProfiles;
|
||||
Windows::Foundation::Collections::IVector<Model::SettingsLoadWarnings> _warnings;
|
||||
Windows::Foundation::IReference<SettingsLoadErrors> _loadError;
|
||||
hstring _deserializationErrorMessage;
|
||||
static const std::filesystem::path& _settingsPath();
|
||||
|
||||
Windows::Foundation::Collections::IObservableVector<Model::DefaultTerminal> _defaultTerminals;
|
||||
Model::DefaultTerminal _currentDefaultTerminal;
|
||||
winrt::com_ptr<implementation::Profile> _createNewProfile(const std::wstring_view& name) const;
|
||||
|
||||
std::vector<std::unique_ptr<::Microsoft::Terminal::Settings::Model::IDynamicProfileGenerator>> _profileGenerators;
|
||||
void _resolveDefaultProfile() const;
|
||||
|
||||
std::string _userSettingsString;
|
||||
Json::Value _userSettings;
|
||||
Json::Value _defaultSettings;
|
||||
winrt::com_ptr<Profile> _userDefaultProfileSettings{ nullptr };
|
||||
void _validateSettings();
|
||||
void _validateAllSchemesExist();
|
||||
void _validateMediaResources();
|
||||
void _validateKeybindings() const;
|
||||
void _validateColorSchemesInCommands() const;
|
||||
bool _hasInvalidColorScheme(const Model::Command& command) const;
|
||||
|
||||
winrt::com_ptr<Profile> _CreateNewProfile(const std::wstring_view& name) const;
|
||||
// user settings
|
||||
winrt::com_ptr<implementation::GlobalAppSettings> _globals;
|
||||
winrt::com_ptr<implementation::Profile> _baseLayerProfile;
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<Model::Profile> _allProfiles;
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<Model::Profile> _activeProfiles;
|
||||
|
||||
void _LayerOrCreateProfile(const Json::Value& profileJson);
|
||||
winrt::com_ptr<implementation::Profile> _FindMatchingProfile(const Json::Value& profileJson);
|
||||
std::optional<uint32_t> _FindMatchingProfileIndex(const Json::Value& profileJson);
|
||||
void _LayerOrCreateColorScheme(const Json::Value& schemeJson);
|
||||
Json::Value _ParseUtf8JsonString(std::string_view fileData);
|
||||
// load errors
|
||||
winrt::Windows::Foundation::Collections::IVector<Model::SettingsLoadWarnings> _warnings;
|
||||
winrt::Windows::Foundation::IReference<Model::SettingsLoadErrors> _loadError;
|
||||
winrt::hstring _deserializationErrorMessage;
|
||||
|
||||
winrt::com_ptr<implementation::ColorScheme> _FindMatchingColorScheme(const Json::Value& schemeJson);
|
||||
void _ParseJsonString(std::string_view fileData, const bool isDefaultSettings);
|
||||
static const Json::Value& _GetProfilesJsonObject(const Json::Value& json);
|
||||
static const Json::Value& _GetDisabledProfileSourcesJsonObject(const Json::Value& json);
|
||||
bool _PrependSchemaDirective();
|
||||
bool _AppendDynamicProfilesToUserSettings();
|
||||
std::string _ApplyFirstRunChangesToSettingsTemplate(std::string_view settingsTemplate) const;
|
||||
void _CopyProfileInheritanceTree(com_ptr<CascadiaSettings>& cloneSettings) const;
|
||||
|
||||
void _ApplyDefaultsFromUserSettings();
|
||||
|
||||
void _LoadDynamicProfiles();
|
||||
void _LoadFragmentExtensions();
|
||||
void _ApplyJsonStubsHelper(const std::wstring_view directory, const std::unordered_set<std::wstring>& ignoredNamespaces);
|
||||
std::unordered_set<std::string> _AccumulateJsonFilesInDirectory(const std::wstring_view directory);
|
||||
void _ParseAndLayerFragmentFiles(const std::unordered_set<std::string> files, const winrt::hstring source);
|
||||
|
||||
static const std::filesystem::path& _SettingsPath();
|
||||
static std::optional<std::string> _ReadUserSettings();
|
||||
|
||||
std::optional<guid> _GetProfileGuidByName(const hstring) const;
|
||||
std::optional<guid> _GetProfileGuidByIndex(std::optional<int> index) const;
|
||||
|
||||
void _ValidateSettings();
|
||||
void _ValidateProfilesExist();
|
||||
void _ValidateDefaultProfileExists();
|
||||
void _ValidateNoDuplicateProfiles();
|
||||
void _ResolveDefaultProfile();
|
||||
void _ReorderProfilesToMatchUserSettingsOrder();
|
||||
void _UpdateActiveProfiles();
|
||||
void _ValidateAllSchemesExist();
|
||||
void _ValidateMediaResources();
|
||||
void _ValidateKeybindings();
|
||||
void _ValidateColorSchemesInCommands();
|
||||
void _ValidateNoGlobalsKey();
|
||||
|
||||
bool _HasInvalidColorScheme(const Model::Command& command);
|
||||
|
||||
friend class SettingsModelLocalTests::SerializationTests;
|
||||
friend class SettingsModelLocalTests::DeserializationTests;
|
||||
friend class SettingsModelLocalTests::ProfileTests;
|
||||
friend class SettingsModelLocalTests::ColorSchemeTests;
|
||||
friend class SettingsModelLocalTests::KeyBindingsTests;
|
||||
friend class TerminalAppUnitTests::DynamicProfileTests;
|
||||
friend class TerminalAppUnitTests::JsonTests;
|
||||
// defterm
|
||||
Model::DefaultTerminal _currentDefaultTerminal{ nullptr };
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -9,11 +9,6 @@ import "DefaultTerminal.idl";
|
|||
namespace Microsoft.Terminal.Settings.Model
|
||||
{
|
||||
[default_interface] runtimeclass CascadiaSettings {
|
||||
CascadiaSettings(String json);
|
||||
CascadiaSettings Copy();
|
||||
|
||||
void WriteSettingsToDisk();
|
||||
|
||||
static CascadiaSettings LoadDefaults();
|
||||
static CascadiaSettings LoadAll();
|
||||
static CascadiaSettings LoadUniversal();
|
||||
|
@ -23,19 +18,24 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
|
||||
static String ApplicationDisplayName { get; };
|
||||
static String ApplicationVersion { get; };
|
||||
|
||||
CascadiaSettings(String userJSON, String inboxJSON);
|
||||
|
||||
CascadiaSettings Copy();
|
||||
void WriteSettingsToDisk();
|
||||
|
||||
GlobalAppSettings GlobalSettings { get; };
|
||||
|
||||
Profile ProfileDefaults { get; };
|
||||
|
||||
Windows.Foundation.Collections.IObservableVector<Profile> AllProfiles { get; };
|
||||
Windows.Foundation.Collections.IObservableVector<Profile> ActiveProfiles { get; };
|
||||
IObservableVector<Profile> AllProfiles { get; };
|
||||
IObservableVector<Profile> ActiveProfiles { get; };
|
||||
|
||||
Profile DuplicateProfile(Profile sourceProfile);
|
||||
|
||||
ActionMap ActionMap { get; };
|
||||
|
||||
Windows.Foundation.Collections.IVectorView<SettingsLoadWarnings> Warnings { get; };
|
||||
IVectorView<SettingsLoadWarnings> Warnings { get; };
|
||||
Windows.Foundation.IReference<SettingsLoadErrors> GetLoadingError { get; };
|
||||
String GetSerializationErrorMessage { get; };
|
||||
|
||||
|
@ -46,9 +46,8 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
|
||||
Profile GetProfileForArgs(NewTerminalArgs newTerminalArgs);
|
||||
|
||||
void RefreshDefaultTerminals();
|
||||
static Boolean IsDefaultTerminalAvailable { get; };
|
||||
Windows.Foundation.Collections.IObservableVector<DefaultTerminal> DefaultTerminals { get; };
|
||||
IObservableVector<DefaultTerminal> DefaultTerminals { get; };
|
||||
DefaultTerminal CurrentDefaultTerminal;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "pch.h"
|
||||
#include "ColorScheme.h"
|
||||
#include "DefaultSettings.h"
|
||||
#include "../../types/inc/Utils.hpp"
|
||||
#include "../../types/inc/colorTable.hpp"
|
||||
#include "Utils.h"
|
||||
|
@ -41,25 +40,16 @@ static constexpr std::array<std::string_view, 16> TableColors = {
|
|||
"brightWhite"
|
||||
};
|
||||
|
||||
ColorScheme::ColorScheme() :
|
||||
ColorScheme(L"", DEFAULT_FOREGROUND, DEFAULT_BACKGROUND, DEFAULT_CURSOR_COLOR)
|
||||
ColorScheme::ColorScheme() noexcept :
|
||||
ColorScheme{ winrt::hstring{} }
|
||||
{
|
||||
Utils::InitializeCampbellColorTable(_table);
|
||||
}
|
||||
|
||||
ColorScheme::ColorScheme(winrt::hstring name) :
|
||||
ColorScheme(name, DEFAULT_FOREGROUND, DEFAULT_BACKGROUND, DEFAULT_CURSOR_COLOR)
|
||||
{
|
||||
Utils::InitializeCampbellColorTable(_table);
|
||||
}
|
||||
|
||||
ColorScheme::ColorScheme(winrt::hstring name, til::color defaultFg, til::color defaultBg, til::color cursorColor) :
|
||||
_Name{ name },
|
||||
_Foreground{ defaultFg },
|
||||
_Background{ defaultBg },
|
||||
_SelectionBackground{ DEFAULT_FOREGROUND },
|
||||
_CursorColor{ cursorColor }
|
||||
ColorScheme::ColorScheme(const winrt::hstring& name) noexcept :
|
||||
_Name{ name }
|
||||
{
|
||||
const auto table = Utils::CampbellColorTable();
|
||||
std::copy_n(table.data(), table.size(), _table.data());
|
||||
}
|
||||
|
||||
winrt::com_ptr<ColorScheme> ColorScheme::Copy() const
|
||||
|
@ -79,30 +69,11 @@ winrt::com_ptr<ColorScheme> ColorScheme::Copy() const
|
|||
// Arguments:
|
||||
// - json: an object which should be a serialization of a ColorScheme object.
|
||||
// Return Value:
|
||||
// - a new ColorScheme instance created from the values in `json`
|
||||
// - Returns nullptr for invalid JSON.
|
||||
winrt::com_ptr<ColorScheme> ColorScheme::FromJson(const Json::Value& json)
|
||||
{
|
||||
auto result = winrt::make_self<ColorScheme>();
|
||||
result->LayerJson(json);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns true if we think the provided json object represents an instance of
|
||||
// the same object as this object. If true, we should layer that json object
|
||||
// on us, instead of creating a new object.
|
||||
// Arguments:
|
||||
// - json: The json object to query to see if it's the same
|
||||
// Return Value:
|
||||
// - true iff the json object has the same `name` as we do.
|
||||
bool ColorScheme::ShouldBeLayered(const Json::Value& json) const
|
||||
{
|
||||
std::wstring nameFromJson{};
|
||||
if (JsonUtils::GetValueForKey(json, NameKey, nameFromJson))
|
||||
{
|
||||
return nameFromJson == _Name;
|
||||
}
|
||||
return false;
|
||||
auto result = winrt::make_self<ColorScheme>(uninitialized_t{});
|
||||
return result->_layerJson(json) ? result : nullptr;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -112,21 +83,27 @@ bool ColorScheme::ShouldBeLayered(const Json::Value& json) const
|
|||
// the new json object. Properties that _aren't_ in the json object will _not_
|
||||
// be replaced.
|
||||
// Arguments:
|
||||
// - json: an object which should be a partial serialization of a ColorScheme object.
|
||||
// - json: an object which should be a full serialization of a ColorScheme object.
|
||||
// Return Value:
|
||||
// <none>
|
||||
void ColorScheme::LayerJson(const Json::Value& json)
|
||||
// - Returns true if the given JSON was valid.
|
||||
bool ColorScheme::_layerJson(const Json::Value& json)
|
||||
{
|
||||
JsonUtils::GetValueForKey(json, NameKey, _Name);
|
||||
// Required fields
|
||||
auto isValid = JsonUtils::GetValueForKey(json, NameKey, _Name);
|
||||
|
||||
// Optional fields (they have defaults in ColorScheme.h)
|
||||
JsonUtils::GetValueForKey(json, ForegroundKey, _Foreground);
|
||||
JsonUtils::GetValueForKey(json, BackgroundKey, _Background);
|
||||
JsonUtils::GetValueForKey(json, SelectionBackgroundKey, _SelectionBackground);
|
||||
JsonUtils::GetValueForKey(json, CursorColorKey, _CursorColor);
|
||||
|
||||
// Required fields
|
||||
for (unsigned int i = 0; i < TableColors.size(); ++i)
|
||||
{
|
||||
JsonUtils::GetValueForKey(json, til::at(TableColors, i), _table.at(i));
|
||||
isValid &= JsonUtils::GetValueForKey(json, til::at(TableColors, i), til::at(_table, i));
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -147,7 +124,7 @@ Json::Value ColorScheme::ToJson() const
|
|||
|
||||
for (unsigned int i = 0; i < TableColors.size(); ++i)
|
||||
{
|
||||
JsonUtils::SetValueForKey(json, til::at(TableColors, i), _table.at(i));
|
||||
JsonUtils::SetValueForKey(json, til::at(TableColors, i), til::at(_table, i));
|
||||
}
|
||||
|
||||
return json;
|
||||
|
@ -155,9 +132,7 @@ Json::Value ColorScheme::ToJson() const
|
|||
|
||||
winrt::com_array<winrt::Microsoft::Terminal::Core::Color> ColorScheme::Table() const noexcept
|
||||
{
|
||||
winrt::com_array<winrt::Microsoft::Terminal::Core::Color> result{ base::checked_cast<uint32_t>(_table.size()) };
|
||||
std::transform(_table.begin(), _table.end(), result.begin(), [](til::color c) -> winrt::Microsoft::Terminal::Core::Color { return c; });
|
||||
return result;
|
||||
return winrt::com_array<Core::Color>{ _table };
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -167,44 +142,8 @@ winrt::com_array<winrt::Microsoft::Terminal::Core::Color> ColorScheme::Table() c
|
|||
// - value: the color value we are setting the color table color to
|
||||
// Return Value:
|
||||
// - none
|
||||
void ColorScheme::SetColorTableEntry(uint8_t index, const winrt::Microsoft::Terminal::Core::Color& value) noexcept
|
||||
void ColorScheme::SetColorTableEntry(uint8_t index, const Core::Color& value) noexcept
|
||||
{
|
||||
THROW_HR_IF(E_INVALIDARG, index > _table.size() - 1);
|
||||
THROW_HR_IF(E_INVALIDARG, index >= _table.size());
|
||||
_table[index] = value;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Validates a given color scheme
|
||||
// - A color scheme is valid if it has a name and defines all the colors
|
||||
// Arguments:
|
||||
// - The color scheme to validate
|
||||
// Return Value:
|
||||
// - true if the scheme is valid, false otherwise
|
||||
bool ColorScheme::ValidateColorScheme(const Json::Value& scheme)
|
||||
{
|
||||
for (const auto& key : TableColors)
|
||||
{
|
||||
if (!scheme.isMember(JsonKey(key)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!scheme.isMember(JsonKey(NameKey)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Parse the name from the JSON representation of a ColorScheme.
|
||||
// Arguments:
|
||||
// - json: an object which should be a serialization of a ColorScheme object.
|
||||
// Return Value:
|
||||
// - the name of the color scheme represented by `json` as a std::wstring optional
|
||||
// i.e. the value of the `name` property.
|
||||
// - returns std::nullopt if `json` doesn't have the `name` property
|
||||
std::optional<std::wstring> ColorScheme::GetNameFromJson(const Json::Value& json)
|
||||
{
|
||||
return JsonUtils::GetValueForKey<std::optional<std::wstring>>(json, NameKey);
|
||||
}
|
||||
|
|
|
@ -15,38 +15,28 @@ Author(s):
|
|||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "../../inc/conattrs.hpp"
|
||||
#include "inc/cppwinrt_utils.h"
|
||||
#include "DefaultSettings.h"
|
||||
|
||||
#include "ColorScheme.g.h"
|
||||
|
||||
// fwdecl unittest classes
|
||||
namespace SettingsModelLocalTests
|
||||
{
|
||||
class SettingsTests;
|
||||
class ColorSchemeTests;
|
||||
};
|
||||
|
||||
// Use this macro to quick implement both the getter and setter for a color property.
|
||||
// This should only be used for color types where there's no logic in the
|
||||
// getter/setter beyond just accessing/updating the value.
|
||||
// This takes advantage of til::color
|
||||
#define WINRT_TERMINAL_COLOR_PROPERTY(name, ...) \
|
||||
public: \
|
||||
winrt::Microsoft::Terminal::Core::Color name() const noexcept { return _##name; } \
|
||||
void name(const winrt::Microsoft::Terminal::Core::Color& value) noexcept { _##name = value; } \
|
||||
\
|
||||
private: \
|
||||
til::color _##name{ __VA_ARGS__ };
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
struct ColorScheme : ColorSchemeT<ColorScheme>
|
||||
{
|
||||
// A ColorScheme constructed with uninitialized_t
|
||||
// leaves _table uninitialized.
|
||||
struct uninitialized_t
|
||||
{
|
||||
};
|
||||
|
||||
public:
|
||||
ColorScheme();
|
||||
ColorScheme(hstring name);
|
||||
ColorScheme(hstring name, til::color defaultFg, til::color defaultBg, til::color cursorColor);
|
||||
ColorScheme() noexcept;
|
||||
explicit ColorScheme(uninitialized_t) noexcept {}
|
||||
explicit ColorScheme(const winrt::hstring& name) noexcept;
|
||||
|
||||
com_ptr<ColorScheme> Copy() const;
|
||||
|
||||
hstring ToString()
|
||||
|
@ -55,29 +45,21 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
}
|
||||
|
||||
static com_ptr<ColorScheme> FromJson(const Json::Value& json);
|
||||
bool ShouldBeLayered(const Json::Value& json) const;
|
||||
void LayerJson(const Json::Value& json);
|
||||
|
||||
Json::Value ToJson() const;
|
||||
|
||||
static std::optional<std::wstring> GetNameFromJson(const Json::Value& json);
|
||||
|
||||
com_array<winrt::Microsoft::Terminal::Core::Color> Table() const noexcept;
|
||||
void SetColorTableEntry(uint8_t index, const winrt::Microsoft::Terminal::Core::Color& value) noexcept;
|
||||
|
||||
static bool ValidateColorScheme(const Json::Value& scheme);
|
||||
com_array<Core::Color> Table() const noexcept;
|
||||
void SetColorTableEntry(uint8_t index, const Core::Color& value) noexcept;
|
||||
|
||||
WINRT_PROPERTY(winrt::hstring, Name);
|
||||
WINRT_TERMINAL_COLOR_PROPERTY(Foreground); // defined in constructor
|
||||
WINRT_TERMINAL_COLOR_PROPERTY(Background); // defined in constructor
|
||||
WINRT_TERMINAL_COLOR_PROPERTY(SelectionBackground); // defined in constructor
|
||||
WINRT_TERMINAL_COLOR_PROPERTY(CursorColor); // defined in constructor
|
||||
WINRT_PROPERTY(Core::Color, Foreground, static_cast<Core::Color>(DEFAULT_FOREGROUND));
|
||||
WINRT_PROPERTY(Core::Color, Background, static_cast<Core::Color>(DEFAULT_BACKGROUND));
|
||||
WINRT_PROPERTY(Core::Color, SelectionBackground, static_cast<Core::Color>(DEFAULT_FOREGROUND));
|
||||
WINRT_PROPERTY(Core::Color, CursorColor, static_cast<Core::Color>(DEFAULT_CURSOR_COLOR));
|
||||
|
||||
private:
|
||||
std::array<til::color, COLOR_TABLE_SIZE> _table;
|
||||
bool _layerJson(const Json::Value& json);
|
||||
|
||||
friend class SettingsModelLocalTests::SettingsTests;
|
||||
friend class SettingsModelLocalTests::ColorSchemeTests;
|
||||
std::array<Core::Color, COLOR_TABLE_SIZE> _table;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "DefaultProfileUtils.h"
|
||||
#include "DynamicProfileUtils.h"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
|
||||
static constexpr std::wstring_view PACKAGED_PROFILE_ICON_PATH{ L"ms-appx:///ProfileIcons/" };
|
||||
|
@ -15,20 +15,16 @@ static constexpr std::wstring_view PACKAGED_PROFILE_ICON_EXTENSION{ L".png" };
|
|||
// - name: the name of the new profile.
|
||||
// Return Value:
|
||||
// - A Profile, ready to be filled in
|
||||
winrt::Microsoft::Terminal::Settings::Model::Profile CreateDefaultProfile(const std::wstring_view name)
|
||||
winrt::com_ptr<winrt::Microsoft::Terminal::Settings::Model::implementation::Profile> CreateDynamicProfile(const std::wstring_view& name)
|
||||
{
|
||||
const winrt::guid profileGuid{ Microsoft::Console::Utils::CreateV5Uuid(TERMINAL_PROFILE_NAMESPACE_GUID,
|
||||
gsl::as_bytes(gsl::make_span(name))) };
|
||||
|
||||
auto newProfile = winrt::make_self<winrt::Microsoft::Terminal::Settings::Model::implementation::Profile>(profileGuid);
|
||||
newProfile->Name(winrt::hstring{ name });
|
||||
const auto profileGuid = Microsoft::Console::Utils::CreateV5Uuid(TERMINAL_PROFILE_NAMESPACE_GUID, gsl::as_bytes(gsl::make_span(name)));
|
||||
|
||||
std::wstring iconPath{ PACKAGED_PROFILE_ICON_PATH };
|
||||
iconPath.append(Microsoft::Console::Utils::GuidToString(profileGuid));
|
||||
iconPath.append(PACKAGED_PROFILE_ICON_EXTENSION);
|
||||
|
||||
newProfile->Icon(winrt::hstring{ iconPath });
|
||||
newProfile->Origin(winrt::Microsoft::Terminal::Settings::Model::OriginTag::Generated);
|
||||
|
||||
return *newProfile;
|
||||
auto profile = winrt::make_self<winrt::Microsoft::Terminal::Settings::Model::implementation::Profile>(profileGuid);
|
||||
profile->Name(winrt::hstring{ name });
|
||||
profile->Icon(winrt::hstring{ iconPath });
|
||||
return profile;
|
||||
}
|
|
@ -23,4 +23,4 @@ Author(s):
|
|||
// uuidv5 properties: name format is UTF-16LE bytes
|
||||
static constexpr GUID TERMINAL_PROFILE_NAMESPACE_GUID = { 0x2bde4a90, 0xd05f, 0x401c, { 0x94, 0x92, 0xe4, 0x8, 0x84, 0xea, 0xd1, 0xd8 } };
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::Model::Profile CreateDefaultProfile(const std::wstring_view name);
|
||||
winrt::com_ptr<winrt::Microsoft::Terminal::Settings::Model::implementation::Profile> CreateDynamicProfile(const std::wstring_view& name);
|
|
@ -11,7 +11,7 @@
|
|||
static constexpr std::string_view Utf8Bom{ u8"\uFEFF" };
|
||||
static constexpr std::wstring_view UnpackagedSettingsFolderName{ L"Microsoft\\Windows Terminal\\" };
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
// Returns a path like C:\Users\<username>\AppData\Local\Packages\<packagename>\LocalState
|
||||
// You can put your settings.json or state.json in this directory.
|
||||
|
@ -106,7 +106,7 @@ namespace Microsoft::Terminal::Settings::Model
|
|||
}
|
||||
}
|
||||
|
||||
void WriteUTF8File(const std::filesystem::path& path, const std::string_view content)
|
||||
void WriteUTF8File(const std::filesystem::path& path, const std::string_view& content)
|
||||
{
|
||||
wil::unique_hfile file{ CreateFileW(path.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr) };
|
||||
THROW_LAST_ERROR_IF(!file);
|
||||
|
@ -121,7 +121,7 @@ namespace Microsoft::Terminal::Settings::Model
|
|||
}
|
||||
}
|
||||
|
||||
void WriteUTF8FileAtomic(const std::filesystem::path& path, const std::string_view content)
|
||||
void WriteUTF8FileAtomic(const std::filesystem::path& path, const std::string_view& content)
|
||||
{
|
||||
// GH#10787: rename() will replace symbolic links themselves and not the path they point at.
|
||||
// It's thus important that we first resolve them before generating temporary path.
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
std::filesystem::path GetBaseSettingsPath();
|
||||
std::string ReadUTF8File(const std::filesystem::path& path);
|
||||
std::optional<std::string> ReadUTF8FileIfExists(const std::filesystem::path& path);
|
||||
void WriteUTF8File(const std::filesystem::path& path, const std::string_view content);
|
||||
void WriteUTF8FileAtomic(const std::filesystem::path& path, const std::string_view content);
|
||||
void WriteUTF8File(const std::filesystem::path& path, const std::string_view& content);
|
||||
void WriteUTF8FileAtomic(const std::filesystem::path& path, const std::string_view& content);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "pch.h"
|
||||
#include "FontConfig.h"
|
||||
#include "FontConfig.g.cpp"
|
||||
|
||||
#include "TerminalSettingsSerializationHelpers.h"
|
||||
#include "JsonUtils.h"
|
||||
|
||||
|
@ -25,7 +26,7 @@ winrt::Microsoft::Terminal::Settings::Model::implementation::FontConfig::FontCon
|
|||
{
|
||||
}
|
||||
|
||||
winrt::com_ptr<FontConfig> FontConfig::CopyFontInfo(const winrt::com_ptr<FontConfig> source, winrt::weak_ref<Profile> sourceProfile)
|
||||
winrt::com_ptr<FontConfig> FontConfig::CopyFontInfo(const FontConfig* source, winrt::weak_ref<Profile> sourceProfile)
|
||||
{
|
||||
auto fontInfo{ winrt::make_self<FontConfig>(std::move(sourceProfile)) };
|
||||
fontInfo->_FontFace = source->_FontFace;
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
{
|
||||
public:
|
||||
FontConfig(winrt::weak_ref<Profile> sourceProfile);
|
||||
static winrt::com_ptr<FontConfig> CopyFontInfo(const winrt::com_ptr<FontConfig> source, winrt::weak_ref<Profile> sourceProfile);
|
||||
static winrt::com_ptr<FontConfig> CopyFontInfo(const FontConfig* source, winrt::weak_ref<Profile> sourceProfile);
|
||||
Json::Value ToJson() const;
|
||||
void LayerJson(const Json::Value& json);
|
||||
bool HasAnyOptionSet() const;
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
#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"
|
||||
|
@ -52,6 +50,7 @@ static constexpr std::string_view WindowingBehaviorKey{ "windowingBehavior" };
|
|||
static constexpr std::string_view TrimBlockSelectionKey{ "trimBlockSelection" };
|
||||
static constexpr std::string_view AlwaysShowNotificationIconKey{ "alwaysShowNotificationIcon" };
|
||||
static constexpr std::string_view MinimizeToNotificationAreaKey{ "minimizeToNotificationArea" };
|
||||
static constexpr std::string_view DisabledProfileSourcesKey{ "disabledProfileSources" };
|
||||
|
||||
static constexpr std::string_view DebugFeaturesKey{ "debugFeatures" };
|
||||
|
||||
|
@ -60,26 +59,6 @@ static constexpr std::string_view SoftwareRenderingKey{ "experimental.rendering.
|
|||
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:
|
||||
|
@ -88,13 +67,17 @@ GlobalAppSettings::GlobalAppSettings() :
|
|||
// - <none>
|
||||
void GlobalAppSettings::_FinalizeInheritance()
|
||||
{
|
||||
// Globals only ever has 1 parent
|
||||
FAIL_FAST_IF(_parents.size() > 1);
|
||||
for (auto parent : _parents)
|
||||
for (const auto& parent : _parents)
|
||||
{
|
||||
_actionMap->InsertParent(parent->_actionMap);
|
||||
_keybindingsWarnings = std::move(parent->_keybindingsWarnings);
|
||||
_colorSchemes = std::move(parent->_colorSchemes);
|
||||
_keybindingsWarnings.insert(_keybindingsWarnings.end(), parent->_keybindingsWarnings.begin(), parent->_keybindingsWarnings.end());
|
||||
for (const auto& [k, v] : parent->_colorSchemes)
|
||||
{
|
||||
if (!_colorSchemes.HasKey(k))
|
||||
{
|
||||
_colorSchemes.Insert(k, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,12 +120,12 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
|
|||
globals->_DetectURLs = _DetectURLs;
|
||||
globals->_MinimizeToNotificationArea = _MinimizeToNotificationArea;
|
||||
globals->_AlwaysShowNotificationIcon = _AlwaysShowNotificationIcon;
|
||||
|
||||
globals->_DisabledProfileSources = _DisabledProfileSources;
|
||||
globals->_UnparsedDefaultProfile = _UnparsedDefaultProfile;
|
||||
globals->_validDefaultProfile = _validDefaultProfile;
|
||||
|
||||
globals->_defaultProfile = _defaultProfile;
|
||||
globals->_actionMap = _actionMap->Copy();
|
||||
std::copy(_keybindingsWarnings.begin(), _keybindingsWarnings.end(), std::back_inserter(globals->_keybindingsWarnings));
|
||||
globals->_keybindingsWarnings = _keybindingsWarnings;
|
||||
|
||||
if (_colorSchemes)
|
||||
{
|
||||
|
@ -153,9 +136,7 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
|
|||
}
|
||||
}
|
||||
|
||||
// Globals only ever has 1 parent
|
||||
FAIL_FAST_IF(_parents.size() > 1);
|
||||
for (auto parent : _parents)
|
||||
for (const auto& parent : _parents)
|
||||
{
|
||||
globals->InsertParent(parent->Copy());
|
||||
}
|
||||
|
@ -168,69 +149,18 @@ winrt::Windows::Foundation::Collections::IMapView<winrt::hstring, winrt::Microso
|
|||
}
|
||||
|
||||
#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
|
||||
|
@ -253,92 +183,53 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::FromJson(const Json::Value&
|
|||
|
||||
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, FirstWindowPreferenceKey, _FirstWindowPreference);
|
||||
|
||||
JsonUtils::GetValueForKey(json, LaunchModeKey, _LaunchMode);
|
||||
|
||||
JsonUtils::GetValueForKey(json, LanguageKey, _Language);
|
||||
|
||||
JsonUtils::GetValueForKey(json, ThemeKey, _Theme);
|
||||
|
||||
JsonUtils::GetValueForKey(json, TabWidthModeKey, _TabWidthMode);
|
||||
|
||||
JsonUtils::GetValueForKey(json, UseAcrylicInTabRowKey, _UseAcrylicInTabRow);
|
||||
|
||||
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);
|
||||
|
||||
JsonUtils::GetValueForKey(json, MinimizeToNotificationAreaKey, _MinimizeToNotificationArea);
|
||||
|
||||
JsonUtils::GetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon);
|
||||
JsonUtils::GetValueForKey(json, DisabledProfileSourcesKey, _DisabledProfileSources);
|
||||
|
||||
// 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) {
|
||||
static constexpr std::array bindingsKeys{ LegacyKeybindingsKey, ActionsKey };
|
||||
for (const auto& jsonKey : bindingsKeys)
|
||||
{
|
||||
if (auto bindings{ json[JsonKey(jsonKey)] })
|
||||
{
|
||||
auto warnings = _actionMap->LayerJson(bindings);
|
||||
|
@ -351,9 +242,7 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
|
|||
// list of warnings.
|
||||
_keybindingsWarnings.insert(_keybindingsWarnings.end(), warnings.begin(), warnings.end());
|
||||
}
|
||||
};
|
||||
parseBindings(LegacyKeybindingsKey);
|
||||
parseBindings(ActionsKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -381,7 +270,7 @@ void GlobalAppSettings::RemoveColorScheme(hstring schemeName)
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
std::vector<winrt::Microsoft::Terminal::Settings::Model::SettingsLoadWarnings> GlobalAppSettings::KeybindingsWarnings() const
|
||||
const std::vector<winrt::Microsoft::Terminal::Settings::Model::SettingsLoadWarnings>& GlobalAppSettings::KeybindingsWarnings() const
|
||||
{
|
||||
return _keybindingsWarnings;
|
||||
}
|
||||
|
@ -433,7 +322,8 @@ Json::Value GlobalAppSettings::ToJson() const
|
|||
JsonUtils::SetValueForKey(json, TrimBlockSelectionKey, _TrimBlockSelection);
|
||||
JsonUtils::SetValueForKey(json, DetectURLsKey, _DetectURLs);
|
||||
JsonUtils::SetValueForKey(json, MinimizeToNotificationAreaKey, _MinimizeToNotificationArea);
|
||||
JsonUtils::SetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon);
|
||||
JsonUtils::SetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon);
|
||||
JsonUtils::SetValueForKey(json, DisabledProfileSourcesKey, _DisabledProfileSources);
|
||||
// clang-format on
|
||||
|
||||
json[JsonKey(ActionsKey)] = _actionMap->ToJson();
|
||||
|
|
|
@ -34,7 +34,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
struct GlobalAppSettings : GlobalAppSettingsT<GlobalAppSettings>, IInheritable<GlobalAppSettings>
|
||||
{
|
||||
public:
|
||||
GlobalAppSettings();
|
||||
void _FinalizeInheritance() override;
|
||||
com_ptr<GlobalAppSettings> Copy() const;
|
||||
|
||||
|
@ -49,16 +48,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
|
||||
Json::Value ToJson() const;
|
||||
|
||||
std::vector<SettingsLoadWarnings> KeybindingsWarnings() const;
|
||||
const std::vector<SettingsLoadWarnings>& KeybindingsWarnings() const;
|
||||
|
||||
// These are implemented manually to handle the string/GUID exchange
|
||||
// by higher layers in the app.
|
||||
// This DefaultProfile() setter is called by CascadiaSettings,
|
||||
// when it parses UnparsedDefaultProfile in _finalizeSettings().
|
||||
void DefaultProfile(const guid& defaultProfile) noexcept;
|
||||
guid DefaultProfile() const;
|
||||
bool HasUnparsedDefaultProfile() const;
|
||||
winrt::hstring UnparsedDefaultProfile() const;
|
||||
void UnparsedDefaultProfile(const hstring& value);
|
||||
void ClearUnparsedDefaultProfile();
|
||||
|
||||
// TODO GH#9207: Remove this once we have a GlobalAppSettingsViewModel in TerminalSettingsEditor
|
||||
void SetInvertedDisableAnimationsValue(bool invertedDisableAnimationsValue)
|
||||
|
@ -90,7 +85,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ForceFullRepaintRendering, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, SoftwareRendering, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, ForceVTInput, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, DebugFeaturesEnabled, _getDefaultDebugFeaturesValue());
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, DebugFeaturesEnabled, debugFeaturesDefault);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, StartOnUserLogin, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysOnTop, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, Model::TabSwitcherMode, TabSwitcherMode, Model::TabSwitcherMode::InOrder);
|
||||
|
@ -102,21 +97,19 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, DetectURLs, true);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, MinimizeToNotificationArea, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysShowNotificationIcon, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, winrt::Windows::Foundation::Collections::IVector<winrt::hstring>, DisabledProfileSources, nullptr);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, UnparsedDefaultProfile, L"");
|
||||
|
||||
private:
|
||||
guid _defaultProfile;
|
||||
std::optional<hstring> _UnparsedDefaultProfile{ std::nullopt };
|
||||
bool _validDefaultProfile;
|
||||
#ifdef NDEBUG
|
||||
static constexpr bool debugFeaturesDefault{ false };
|
||||
#else
|
||||
static constexpr bool debugFeaturesDefault{ true };
|
||||
#endif
|
||||
|
||||
com_ptr<implementation::ActionMap> _actionMap;
|
||||
winrt::guid _defaultProfile;
|
||||
winrt::com_ptr<implementation::ActionMap> _actionMap{ winrt::make_self<implementation::ActionMap>() };
|
||||
std::vector<SettingsLoadWarnings> _keybindingsWarnings;
|
||||
|
||||
Windows::Foundation::Collections::IMap<hstring, Model::ColorScheme> _colorSchemes;
|
||||
|
||||
std::optional<hstring> _getUnparsedDefaultProfileImpl() const;
|
||||
static bool _getDefaultDebugFeaturesValue();
|
||||
|
||||
friend class SettingsModelLocalTests::DeserializationTests;
|
||||
friend class SettingsModelLocalTests::ColorSchemeTests;
|
||||
Windows::Foundation::Collections::IMap<winrt::hstring, Model::ColorScheme> _colorSchemes{ winrt::single_threaded_map<winrt::hstring, Model::ColorScheme>() };
|
||||
};
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
INHERITABLE_SETTING(Boolean, DetectURLs);
|
||||
INHERITABLE_SETTING(Boolean, MinimizeToNotificationArea);
|
||||
INHERITABLE_SETTING(Boolean, AlwaysShowNotificationIcon);
|
||||
INHERITABLE_SETTING(IVector<String>, DisabledProfileSources);
|
||||
|
||||
Windows.Foundation.Collections.IMapView<String, ColorScheme> ColorSchemes();
|
||||
void AddColorScheme(ColorScheme scheme);
|
||||
|
|
|
@ -51,5 +51,6 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
INHERITABLE_APPEARANCE_SETTING(Boolean, RetroTerminalEffect);
|
||||
INHERITABLE_APPEARANCE_SETTING(String, PixelShaderPath);
|
||||
INHERITABLE_APPEARANCE_SETTING(IntenseStyle, IntenseTextStyle);
|
||||
INHERITABLE_APPEARANCE_SETTING(Double, Opacity);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -20,18 +20,16 @@ Author(s):
|
|||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Profile.h"
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
class IDynamicProfileGenerator;
|
||||
class IDynamicProfileGenerator
|
||||
{
|
||||
public:
|
||||
virtual ~IDynamicProfileGenerator(){};
|
||||
virtual std::wstring_view GetNamespace() const noexcept = 0;
|
||||
virtual void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const = 0;
|
||||
};
|
||||
};
|
||||
|
||||
class Microsoft::Terminal::Settings::Model::IDynamicProfileGenerator
|
||||
{
|
||||
public:
|
||||
virtual ~IDynamicProfileGenerator() = 0;
|
||||
virtual std::wstring_view GetNamespace() = 0;
|
||||
virtual std::vector<winrt::Microsoft::Terminal::Settings::Model::Profile> GenerateProfiles() = 0;
|
||||
};
|
||||
inline Microsoft::Terminal::Settings::Model::IDynamicProfileGenerator::~IDynamicProfileGenerator() {}
|
||||
|
|
|
@ -48,13 +48,13 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
|
||||
void InsertParent(com_ptr<T> parent)
|
||||
{
|
||||
_parents.push_back(parent);
|
||||
_parents.emplace_back(std::move(parent));
|
||||
}
|
||||
|
||||
void InsertParent(size_t index, com_ptr<T> parent)
|
||||
{
|
||||
auto pos{ _parents.begin() + index };
|
||||
_parents.insert(pos, parent);
|
||||
_parents.emplace(pos, std::move(parent));
|
||||
}
|
||||
|
||||
const std::vector<com_ptr<T>>& Parents()
|
||||
|
|
|
@ -678,7 +678,7 @@ namespace Microsoft::Terminal::Settings::Model::JsonUtils
|
|||
{
|
||||
GUID FromJson(const Json::Value& json)
|
||||
{
|
||||
return ::Microsoft::Console::Utils::GuidFromString(til::u8u16(Detail::GetStringView(json)));
|
||||
return ::Microsoft::Console::Utils::GuidFromString(til::u8u16(Detail::GetStringView(json)).c_str());
|
||||
}
|
||||
|
||||
bool CanConvert(const Json::Value& json)
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
<ClInclude Include="Command.h">
|
||||
<DependentUpon>Command.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DefaultProfileUtils.h" />
|
||||
<ClInclude Include="DynamicProfileUtils.h" />
|
||||
<ClInclude Include="FileUtils.h" />
|
||||
<ClInclude Include="GlobalAppSettings.h">
|
||||
<DependentUpon>GlobalAppSettings.idl</DependentUpon>
|
||||
|
@ -123,7 +123,7 @@
|
|||
<ClCompile Include="Command.cpp">
|
||||
<DependentUpon>Command.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DefaultProfileUtils.cpp" />
|
||||
<ClCompile Include="DynamicProfileUtils.cpp" />
|
||||
<ClCompile Include="FileUtils.cpp" />
|
||||
<ClCompile Include="GlobalAppSettings.cpp">
|
||||
<DependentUpon>GlobalAppSettings.idl</DependentUpon>
|
||||
|
@ -241,28 +241,29 @@
|
|||
</ItemDefinitionGroup>
|
||||
<!-- ========================= Globals ======================== -->
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets'))" />
|
||||
</Target>
|
||||
<!-- This target will take our defaults.json and stamp it into a .h file that
|
||||
we can include in the code directly. This way, we don't need to worry about
|
||||
failing to load the default settings at runtime. -->
|
||||
<Target Name="_TerminalAppGenerateDefaultsH" Inputs="defaults.json" Outputs="Generated Files\defaults.h" BeforeTargets="BeforeClCompile">
|
||||
<Exec Command="powershell.exe -noprofile –ExecutionPolicy Unrestricted $(OpenConsoleDir)\tools\GenerateHeaderForJson.ps1 -JsonFile defaults.json -OutPath '"Generated Files\defaults.h"' -VariableName DefaultJson" />
|
||||
<Exec Command="pwsh.exe -NoProfile –ExecutionPolicy Unrestricted $(OpenConsoleDir)\tools\GenerateHeaderForJson.ps1 -JsonFile defaults.json -OutPath "Generated Files\defaults.h" -VariableName DefaultJson" />
|
||||
</Target>
|
||||
<!-- A different set of defaults for Universal variant -->
|
||||
<Target Name="_TerminalAppGenerateDefaultsUniversalH" Inputs="defaults-universal.json" Outputs="Generated Files\defaults-universal.h" BeforeTargets="BeforeClCompile">
|
||||
<Exec Command="powershell.exe -noprofile –ExecutionPolicy Unrestricted $(OpenConsoleDir)\tools\GenerateHeaderForJson.ps1 -JsonFile defaults-universal.json -OutPath '"Generated Files\defaults-universal.h"' -VariableName DefaultUniversalJson" />
|
||||
<Exec Command="pwsh.exe -NoProfile –ExecutionPolicy Unrestricted $(OpenConsoleDir)\tools\GenerateHeaderForJson.ps1 -JsonFile defaults-universal.json -OutPath "Generated Files\defaults-universal.h" -VariableName DefaultUniversalJson" />
|
||||
</Target>
|
||||
<!-- Same as above, but for the default settings.json template -->
|
||||
<Target Name="_TerminalAppGenerateUserSettingsH" Inputs="userDefaults.json" Outputs="Generated Files\userDefaults.h" BeforeTargets="BeforeClCompile">
|
||||
<Exec Command="powershell.exe -noprofile –ExecutionPolicy Unrestricted $(OpenConsoleDir)\tools\GenerateHeaderForJson.ps1 -JsonFile userDefaults.json -OutPath '"Generated Files\userDefaults.h"' -VariableName UserSettingsJson" />
|
||||
<Exec Command="pwsh.exe -NoProfile –ExecutionPolicy Unrestricted $(OpenConsoleDir)\tools\GenerateHeaderForJson.ps1 -JsonFile userDefaults.json -OutPath "Generated Files\userDefaults.h" -VariableName UserSettingsJson" />
|
||||
</Target>
|
||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||
<Import Project="..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets" Condition="Exists('..\..\..\packages\Microsoft.VisualStudio.Setup.Configuration.Native.2.3.2262\build\native\Microsoft.VisualStudio.Setup.Configuration.Native.targets')" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<ClCompile Include="KeyChordSerialization.cpp" />
|
||||
<ClCompile Include="Profile.cpp" />
|
||||
<ClCompile Include="ColorScheme.cpp" />
|
||||
<ClCompile Include="DefaultProfileUtils.cpp">
|
||||
<ClCompile Include="DynamicProfileUtils.cpp">
|
||||
<Filter>profileGeneration</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(OpenConsoleDir)\dep\jsoncpp\jsoncpp.cpp">
|
||||
|
@ -69,7 +69,7 @@
|
|||
<ClInclude Include="SettingsTypes.h" />
|
||||
<ClInclude Include="TerminalWarnings.h" />
|
||||
<ClInclude Include="ColorScheme.h" />
|
||||
<ClInclude Include="DefaultProfileUtils.h">
|
||||
<ClInclude Include="DynamicProfileUtils.h">
|
||||
<Filter>profileGeneration</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="JsonUtils.h">
|
||||
|
@ -123,4 +123,4 @@
|
|||
<UniqueIdentifier>{81a6314f-aa5b-4533-a499-13bc3a5c4af0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "../../types/inc/utils.hpp"
|
||||
#include "../../inc/DefaultSettings.h"
|
||||
#include "Utils.h"
|
||||
#include "DefaultProfileUtils.h"
|
||||
#include "DynamicProfileUtils.h"
|
||||
|
||||
// These four are headers we do not want proliferating, so they're not in the PCH.
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
|
@ -289,7 +289,7 @@ static std::vector<PowerShellInstance> _collectPowerShellInstances()
|
|||
// - PowerShell Core 574e775e-4f2a-5b96-ac1e-a2962a402336
|
||||
static constexpr winrt::guid PowershellCoreGuid{ 0x574e775e, 0x4f2a, 0x5b96, { 0xac, 0x1e, 0xa2, 0x96, 0x2a, 0x40, 0x23, 0x36 } };
|
||||
|
||||
std::wstring_view PowershellCoreProfileGenerator::GetNamespace()
|
||||
std::wstring_view PowershellCoreProfileGenerator::GetNamespace() const noexcept
|
||||
{
|
||||
return PowershellCoreGeneratorNamespace;
|
||||
}
|
||||
|
@ -300,34 +300,33 @@ std::wstring_view PowershellCoreProfileGenerator::GetNamespace()
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - a vector with the PowerShell Core profile, if available.
|
||||
std::vector<Profile> PowershellCoreProfileGenerator::GenerateProfiles()
|
||||
void PowershellCoreProfileGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const
|
||||
{
|
||||
std::vector<Profile> profiles;
|
||||
const auto psInstances = _collectPowerShellInstances();
|
||||
bool first = true;
|
||||
|
||||
auto psInstances = _collectPowerShellInstances();
|
||||
for (const auto& psI : psInstances)
|
||||
{
|
||||
const auto name = psI.Name();
|
||||
auto profile{ CreateDefaultProfile(name) };
|
||||
profile.Commandline(psI.executablePath.wstring());
|
||||
profile.StartingDirectory(DEFAULT_STARTING_DIRECTORY);
|
||||
profile.DefaultAppearance().ColorSchemeName(L"Campbell");
|
||||
auto profile{ CreateDynamicProfile(name) };
|
||||
profile->Commandline(winrt::hstring{ psI.executablePath.native() });
|
||||
profile->StartingDirectory(winrt::hstring{ DEFAULT_STARTING_DIRECTORY });
|
||||
profile->DefaultAppearance().ColorSchemeName(L"Campbell");
|
||||
profile->Icon(winrt::hstring{ WI_IsFlagSet(psI.flags, PowerShellFlags::Preview) ? POWERSHELL_PREVIEW_ICON : POWERSHELL_ICON });
|
||||
|
||||
if (first)
|
||||
{
|
||||
// Give the first ("algorithmically best") profile the official, and original, "PowerShell Core" GUID.
|
||||
// This will turn the anchored default profile into "PowerShell Core Latest for Native Architecture through Store"
|
||||
// (or the closest approximation thereof). It may choose a preview instance as the "best" if it is a higher version.
|
||||
profile->Guid(PowershellCoreGuid);
|
||||
profile->Name(winrt::hstring{ POWERSHELL_PREFERRED_PROFILE_NAME });
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
profile.Icon(WI_IsFlagSet(psI.flags, PowerShellFlags::Preview) ? POWERSHELL_PREVIEW_ICON : POWERSHELL_ICON);
|
||||
profiles.emplace_back(std::move(profile));
|
||||
}
|
||||
|
||||
if (profiles.size() > 0)
|
||||
{
|
||||
// Give the first ("algorithmically best") profile the official, and original, "PowerShell Core" GUID.
|
||||
// This will turn the anchored default profile into "PowerShell Core Latest for Native Architecture through Store"
|
||||
// (or the closest approximation thereof). It may choose a preview instance as the "best" if it is a higher version.
|
||||
auto firstProfile = profiles.begin();
|
||||
firstProfile->Guid(PowershellCoreGuid);
|
||||
firstProfile->Name(POWERSHELL_PREFERRED_PROFILE_NAME);
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
|
|
|
@ -18,17 +18,14 @@ Author(s):
|
|||
|
||||
#include "IDynamicProfileGenerator.h"
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
class PowershellCoreProfileGenerator : public Microsoft::Terminal::Settings::Model::IDynamicProfileGenerator
|
||||
class PowershellCoreProfileGenerator final : public IDynamicProfileGenerator
|
||||
{
|
||||
public:
|
||||
static const std::wstring_view GetPreferredPowershellProfileName();
|
||||
|
||||
PowershellCoreProfileGenerator() = default;
|
||||
~PowershellCoreProfileGenerator() = default;
|
||||
std::wstring_view GetNamespace() override;
|
||||
|
||||
std::vector<winrt::Microsoft::Terminal::Settings::Model::Profile> GenerateProfiles() override;
|
||||
std::wstring_view GetNamespace() const noexcept override;
|
||||
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const override;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
#include "Profile.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "../../types/inc/Utils.hpp"
|
||||
#include <DefaultSettings.h>
|
||||
|
||||
#include "LegacyProfileGeneratorNamespaces.h"
|
||||
#include "TerminalSettingsSerializationHelpers.h"
|
||||
#include "AppearanceConfig.h"
|
||||
#include "FontConfig.h"
|
||||
|
@ -22,6 +20,7 @@ using namespace winrt::Windows::UI::Xaml;
|
|||
using namespace winrt::Windows::Foundation;
|
||||
using namespace ::Microsoft::Console;
|
||||
|
||||
static constexpr std::string_view UpdatesKey{ "updates" };
|
||||
static constexpr std::string_view NameKey{ "name" };
|
||||
static constexpr std::string_view GuidKey{ "guid" };
|
||||
static constexpr std::string_view SourceKey{ "source" };
|
||||
|
@ -36,7 +35,6 @@ static constexpr std::string_view AltGrAliasingKey{ "altGrAliasing" };
|
|||
static constexpr std::string_view ConnectionTypeKey{ "connectionType" };
|
||||
static constexpr std::string_view CommandlineKey{ "commandline" };
|
||||
static constexpr std::string_view FontInfoKey{ "font" };
|
||||
static constexpr std::string_view AcrylicTransparencyKey{ "acrylicOpacity" };
|
||||
static constexpr std::string_view UseAcrylicKey{ "useAcrylic" };
|
||||
static constexpr std::string_view ScrollbarStateKey{ "scrollbarState" };
|
||||
static constexpr std::string_view CloseOnExitKey{ "closeOnExit" };
|
||||
|
@ -48,13 +46,7 @@ static constexpr std::string_view TabColorKey{ "tabColor" };
|
|||
static constexpr std::string_view BellStyleKey{ "bellStyle" };
|
||||
static constexpr std::string_view UnfocusedAppearanceKey{ "unfocusedAppearance" };
|
||||
|
||||
static constexpr std::wstring_view DesktopWallpaperEnum{ L"desktopWallpaper" };
|
||||
|
||||
Profile::Profile()
|
||||
{
|
||||
}
|
||||
|
||||
Profile::Profile(guid guid) :
|
||||
Profile::Profile(guid guid) noexcept :
|
||||
_Guid(guid)
|
||||
{
|
||||
}
|
||||
|
@ -80,62 +72,81 @@ void Profile::DeleteUnfocusedAppearance()
|
|||
_UnfocusedAppearance = std::nullopt;
|
||||
}
|
||||
|
||||
winrt::com_ptr<Profile> Profile::CopySettings(winrt::com_ptr<Profile> source)
|
||||
// See CopyInheritanceGraph (singular) for more information.
|
||||
// This does the same, but runs it on a list of graph nodes and clones each sub-graph.
|
||||
void Profile::CopyInheritanceGraphs(std::unordered_map<const Profile*, winrt::com_ptr<Profile>>& visited, const std::vector<winrt::com_ptr<Profile>>& source, std::vector<winrt::com_ptr<Profile>>& target)
|
||||
{
|
||||
auto profile{ winrt::make_self<Profile>() };
|
||||
for (const auto& sourceProfile : source)
|
||||
{
|
||||
target.emplace_back(sourceProfile->CopyInheritanceGraph(visited));
|
||||
}
|
||||
}
|
||||
|
||||
profile->_Deleted = source->_Deleted;
|
||||
profile->_Guid = source->_Guid;
|
||||
profile->_Name = source->_Name;
|
||||
profile->_Source = source->_Source;
|
||||
profile->_Hidden = source->_Hidden;
|
||||
profile->_Icon = source->_Icon;
|
||||
profile->_CloseOnExit = source->_CloseOnExit;
|
||||
profile->_TabTitle = source->_TabTitle;
|
||||
profile->_TabColor = source->_TabColor;
|
||||
profile->_SuppressApplicationTitle = source->_SuppressApplicationTitle;
|
||||
profile->_UseAcrylic = source->_UseAcrylic;
|
||||
profile->_AcrylicOpacity = source->_AcrylicOpacity;
|
||||
profile->_ScrollState = source->_ScrollState;
|
||||
profile->_Padding = source->_Padding;
|
||||
profile->_Commandline = source->_Commandline;
|
||||
profile->_StartingDirectory = source->_StartingDirectory;
|
||||
profile->_AntialiasingMode = source->_AntialiasingMode;
|
||||
profile->_ForceFullRepaintRendering = source->_ForceFullRepaintRendering;
|
||||
profile->_SoftwareRendering = source->_SoftwareRendering;
|
||||
profile->_HistorySize = source->_HistorySize;
|
||||
profile->_SnapOnInput = source->_SnapOnInput;
|
||||
profile->_AltGrAliasing = source->_AltGrAliasing;
|
||||
profile->_BellStyle = source->_BellStyle;
|
||||
profile->_ConnectionType = source->_ConnectionType;
|
||||
profile->_Origin = source->_Origin;
|
||||
// A profile and its IInheritable parents basically behave like a directed acyclic graph (DAG).
|
||||
// Cloning a DAG requires us to prevent the duplication of already cloned nodes (or profiles).
|
||||
// This is where "visited" comes into play: It contains previously cloned sub-graphs of profiles and "interns" them.
|
||||
winrt::com_ptr<Profile>& Profile::CopyInheritanceGraph(std::unordered_map<const Profile*, winrt::com_ptr<Profile>>& visited) const
|
||||
{
|
||||
// The operator[] is usually considered to suck, because it implicitly creates entries
|
||||
// in maps/sets if the entry doesn't exist yet, which is often an unwanted behavior.
|
||||
// But in this case it's just perfect. We want to return a reference to the profile if it's
|
||||
// been created before and create a cloned profile if it doesn't. With the operator[]
|
||||
// we can just assign the returned reference allowing us to write some lean code.
|
||||
auto& clone = visited[this];
|
||||
|
||||
// Copy over the font info
|
||||
const auto weakRefToProfile = weak_ref<Model::Profile>(*profile);
|
||||
winrt::com_ptr<FontConfig> sourceFontInfoImpl;
|
||||
sourceFontInfoImpl.copy_from(winrt::get_self<FontConfig>(source->_FontInfo));
|
||||
auto copiedFontInfo = FontConfig::CopyFontInfo(sourceFontInfoImpl, weakRefToProfile);
|
||||
profile->_FontInfo = *copiedFontInfo;
|
||||
if (!clone)
|
||||
{
|
||||
clone = CopySettings();
|
||||
CopyInheritanceGraphs(visited, _parents, clone->_parents);
|
||||
clone->_FinalizeInheritance();
|
||||
}
|
||||
|
||||
// Copy over the appearance
|
||||
winrt::com_ptr<AppearanceConfig> sourceDefaultAppearanceImpl;
|
||||
sourceDefaultAppearanceImpl.copy_from(winrt::get_self<AppearanceConfig>(source->_DefaultAppearance));
|
||||
auto copiedDefaultAppearance = AppearanceConfig::CopyAppearance(sourceDefaultAppearanceImpl, weakRefToProfile);
|
||||
profile->_DefaultAppearance = *copiedDefaultAppearance;
|
||||
return clone;
|
||||
}
|
||||
|
||||
if (source->_UnfocusedAppearance.has_value())
|
||||
winrt::com_ptr<Profile> Profile::CopySettings() const
|
||||
{
|
||||
const auto profile = winrt::make_self<Profile>();
|
||||
const auto weakProfile = winrt::make_weak<Model::Profile>(*profile);
|
||||
const auto fontInfo = FontConfig::CopyFontInfo(winrt::get_self<FontConfig>(_FontInfo), weakProfile);
|
||||
const auto defaultAppearance = AppearanceConfig::CopyAppearance(winrt::get_self<AppearanceConfig>(_DefaultAppearance), weakProfile);
|
||||
|
||||
profile->_Deleted = _Deleted;
|
||||
profile->_Updates = _Updates;
|
||||
profile->_Guid = _Guid;
|
||||
profile->_Name = _Name;
|
||||
profile->_Source = _Source;
|
||||
profile->_Hidden = _Hidden;
|
||||
profile->_Icon = _Icon;
|
||||
profile->_CloseOnExit = _CloseOnExit;
|
||||
profile->_TabTitle = _TabTitle;
|
||||
profile->_TabColor = _TabColor;
|
||||
profile->_SuppressApplicationTitle = _SuppressApplicationTitle;
|
||||
profile->_UseAcrylic = _UseAcrylic;
|
||||
profile->_ScrollState = _ScrollState;
|
||||
profile->_Padding = _Padding;
|
||||
profile->_Commandline = _Commandline;
|
||||
profile->_StartingDirectory = _StartingDirectory;
|
||||
profile->_AntialiasingMode = _AntialiasingMode;
|
||||
profile->_ForceFullRepaintRendering = _ForceFullRepaintRendering;
|
||||
profile->_SoftwareRendering = _SoftwareRendering;
|
||||
profile->_HistorySize = _HistorySize;
|
||||
profile->_SnapOnInput = _SnapOnInput;
|
||||
profile->_AltGrAliasing = _AltGrAliasing;
|
||||
profile->_BellStyle = _BellStyle;
|
||||
profile->_ConnectionType = _ConnectionType;
|
||||
profile->_Origin = _Origin;
|
||||
profile->_FontInfo = *fontInfo;
|
||||
profile->_DefaultAppearance = *defaultAppearance;
|
||||
|
||||
if (_UnfocusedAppearance)
|
||||
{
|
||||
Model::AppearanceConfig unfocused{ nullptr };
|
||||
if (source->_UnfocusedAppearance.value() != nullptr)
|
||||
if (*_UnfocusedAppearance)
|
||||
{
|
||||
// Copy over the unfocused appearance
|
||||
winrt::com_ptr<AppearanceConfig> sourceUnfocusedAppearanceImpl;
|
||||
sourceUnfocusedAppearanceImpl.copy_from(winrt::get_self<AppearanceConfig>(source->_UnfocusedAppearance.value()));
|
||||
auto copiedUnfocusedAppearance = AppearanceConfig::CopyAppearance(sourceUnfocusedAppearanceImpl, weakRefToProfile);
|
||||
|
||||
// Make sure to add the default appearance as a parent
|
||||
copiedUnfocusedAppearance->InsertParent(copiedDefaultAppearance);
|
||||
unfocused = *copiedUnfocusedAppearance;
|
||||
const auto appearance = AppearanceConfig::CopyAppearance(winrt::get_self<AppearanceConfig>(*_UnfocusedAppearance), weakProfile);
|
||||
appearance->InsertParent(defaultAppearance);
|
||||
unfocused = *appearance;
|
||||
}
|
||||
profile->_UnfocusedAppearance = unfocused;
|
||||
}
|
||||
|
@ -143,104 +154,6 @@ winrt::com_ptr<Profile> Profile::CopySettings(winrt::com_ptr<Profile> source)
|
|||
return profile;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Creates a copy of the inheritance graph by performing a depth-first traversal recursively.
|
||||
// Profiles are recorded as visited via the "visited" parameter.
|
||||
// Unvisited Profiles are copied into the "cloneGraph" parameter, then marked as visited.
|
||||
// Arguments:
|
||||
// - sourceGraph - the graph of Profile's we're cloning
|
||||
// - cloneGraph - the clone of sourceGraph that is being constructed
|
||||
// - visited - a map of which Profiles have been visited, and, if so, a reference to the Profile's clone
|
||||
// Return Value:
|
||||
// - a clone in both inheritance structure and Profile values of sourceGraph
|
||||
winrt::com_ptr<Profile> Profile::CloneInheritanceGraph(winrt::com_ptr<Profile> sourceGraph, winrt::com_ptr<Profile> cloneGraph, std::unordered_map<void*, winrt::com_ptr<Profile>>& visited)
|
||||
{
|
||||
// If this is an unexplored Profile
|
||||
// and we have parents...
|
||||
if (visited.find(sourceGraph.get()) == visited.end() && !sourceGraph->_parents.empty())
|
||||
{
|
||||
// iterate through all of our parents to copy them
|
||||
for (const auto& sourceParent : sourceGraph->_parents)
|
||||
{
|
||||
// If we visited this Profile already...
|
||||
auto kv{ visited.find(sourceParent.get()) };
|
||||
if (kv != visited.end())
|
||||
{
|
||||
// add this Profile's clone as a parent
|
||||
InsertParentHelper(cloneGraph, kv->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have not visited this Profile yet,
|
||||
// copy contents of sourceParent to clone
|
||||
winrt::com_ptr<Profile> clone{ CopySettings(sourceParent) };
|
||||
|
||||
// add the new copy to the cloneGraph
|
||||
InsertParentHelper(cloneGraph, clone);
|
||||
|
||||
// copy the sub-graph at "clone"
|
||||
CloneInheritanceGraph(sourceParent, clone, visited);
|
||||
|
||||
// mark clone as "visited"
|
||||
// save it to the map in case somebody else references it
|
||||
visited[sourceParent.get()] = clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we have no more to explore down this path.
|
||||
return cloneGraph;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Inserts a parent profile into a child profile, at the specified index if one was provided
|
||||
// - Makes sure to call _FinalizeInheritance after inserting the parent
|
||||
// Arguments:
|
||||
// - child: the child profile to insert the parent into
|
||||
// - parent: the parent profile to insert into the child
|
||||
// - index: an optional index value to insert the parent into
|
||||
void Profile::InsertParentHelper(winrt::com_ptr<Profile> child, winrt::com_ptr<Profile> parent, std::optional<size_t> index)
|
||||
{
|
||||
if (index)
|
||||
{
|
||||
child->InsertParent(index.value(), parent);
|
||||
}
|
||||
else
|
||||
{
|
||||
child->InsertParent(parent);
|
||||
}
|
||||
child->_FinalizeInheritance();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Generates a Json::Value which is a "stub" of this profile. This stub will
|
||||
// have enough information that it could be layered with this profile.
|
||||
// - This method is used during dynamic profile generation - if a profile is
|
||||
// ever generated that didn't already exist in the user's settings, we'll add
|
||||
// this stub to the user's settings file, so the user has an easy point to
|
||||
// modify the generated profile.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - A json::Value with a guid, name and source (if applicable).
|
||||
Json::Value Profile::GenerateStub() const
|
||||
{
|
||||
Json::Value stub;
|
||||
|
||||
///// Profile-specific settings /////
|
||||
stub[JsonKey(GuidKey)] = winrt::to_string(Utils::GuidToString(Guid()));
|
||||
|
||||
stub[JsonKey(NameKey)] = winrt::to_string(Name());
|
||||
|
||||
const auto source{ Source() };
|
||||
if (!source.empty())
|
||||
{
|
||||
stub[JsonKey(SourceKey)] = winrt::to_string(source);
|
||||
}
|
||||
|
||||
return stub;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Create a new instance of this class from a serialized JsonObject.
|
||||
// Arguments:
|
||||
|
@ -254,71 +167,6 @@ winrt::com_ptr<winrt::Microsoft::Terminal::Settings::Model::implementation::Prof
|
|||
return result;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns true if we think the provided json object represents an instance of
|
||||
// the same object as this object. If true, we should layer that json object
|
||||
// on us, instead of creating a new object.
|
||||
// Arguments:
|
||||
// - json: The json object to query to see if it's the same
|
||||
// Return Value:
|
||||
// - true iff the json object has the same `GUID` as we do.
|
||||
bool Profile::ShouldBeLayered(const Json::Value& json) const
|
||||
{
|
||||
// First, check that GUIDs match. This is easy. If they don't match, they
|
||||
// should _definitely_ not layer.
|
||||
const auto otherGuid{ JsonUtils::GetValueForKey<std::optional<winrt::guid>>(json, GuidKey) };
|
||||
const auto otherSource{ JsonUtils::GetValueForKey<std::optional<winrt::hstring>>(json, SourceKey) };
|
||||
if (otherGuid)
|
||||
{
|
||||
if (otherGuid.value() != Guid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the other json object didn't have a GUID,
|
||||
// check if we auto-generate the same guid using the name and source.
|
||||
const auto otherName{ JsonUtils::GetValueForKey<std::optional<winrt::hstring>>(json, NameKey) };
|
||||
if (Guid() != _GenerateGuidForProfile(otherName ? *otherName : L"Default", otherSource ? *otherSource : L""))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// For profiles with a `source`, also check the `source` property.
|
||||
bool sourceMatches = false;
|
||||
const auto mySource{ Source() };
|
||||
if (!mySource.empty())
|
||||
{
|
||||
if (otherSource.has_value())
|
||||
{
|
||||
// If we have a source and the other has a source, compare them!
|
||||
sourceMatches = *otherSource == mySource;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Special case the legacy dynamic profiles here. In this case,
|
||||
// `this` is a dynamic profile with a source, and our _source is one
|
||||
// of the legacy DPG namespaces. We're looking to see if the other
|
||||
// json object has the same guid, but _no_ "source"
|
||||
if (mySource == WslGeneratorNamespace ||
|
||||
mySource == AzureGeneratorNamespace ||
|
||||
mySource == PowershellCoreGeneratorNamespace)
|
||||
{
|
||||
sourceMatches = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We do not have a source. The only way we match is if source is unset or set to "".
|
||||
sourceMatches = (!otherSource.has_value() || otherSource.value() == L"");
|
||||
}
|
||||
|
||||
return sourceMatches;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Layer values from the given json object on top of the existing properties
|
||||
// of this object. For any keys we're expecting to be able to parse in the
|
||||
|
@ -343,6 +191,7 @@ void Profile::LayerJson(const Json::Value& json)
|
|||
|
||||
// Profile-specific Settings
|
||||
JsonUtils::GetValueForKey(json, NameKey, _Name);
|
||||
JsonUtils::GetValueForKey(json, UpdatesKey, _Updates);
|
||||
JsonUtils::GetValueForKey(json, GuidKey, _Guid);
|
||||
JsonUtils::GetValueForKey(json, HiddenKey, _Hidden);
|
||||
JsonUtils::GetValueForKey(json, SourceKey, _Source);
|
||||
|
@ -356,7 +205,6 @@ void Profile::LayerJson(const Json::Value& json)
|
|||
// Control Settings
|
||||
JsonUtils::GetValueForKey(json, ConnectionTypeKey, _ConnectionType);
|
||||
JsonUtils::GetValueForKey(json, CommandlineKey, _Commandline);
|
||||
JsonUtils::GetValueForKey(json, AcrylicTransparencyKey, _AcrylicOpacity);
|
||||
JsonUtils::GetValueForKey(json, UseAcrylicKey, _UseAcrylic);
|
||||
JsonUtils::GetValueForKey(json, SuppressApplicationTitleKey, _SuppressApplicationTitle);
|
||||
JsonUtils::GetValueForKey(json, CloseOnExitKey, _CloseOnExit);
|
||||
|
@ -462,27 +310,13 @@ std::wstring Profile::EvaluateStartingDirectory(const std::wstring& directory)
|
|||
return wil::ExpandEnvironmentStringsW<std::wstring>(directory.c_str());
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Returns true if the given JSON object represents a dynamic profile object.
|
||||
// If it is a dynamic profile object, we should make sure to only layer the
|
||||
// object on a matching profile from a dynamic source.
|
||||
// Arguments:
|
||||
// - json: the partial serialization of a profile object to check
|
||||
// Return Value:
|
||||
// - true iff the object has a non-null `source` property
|
||||
bool Profile::IsDynamicProfileObject(const Json::Value& json)
|
||||
{
|
||||
const auto& source = json.isMember(JsonKey(SourceKey)) ? json[JsonKey(SourceKey)] : Json::Value::null;
|
||||
return !source.isNull();
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Generates a unique guid for a profile, given the name. For an given name, will always return the same GUID.
|
||||
// Arguments:
|
||||
// - name: The name to generate a unique GUID from
|
||||
// Return Value:
|
||||
// - a uuidv5 GUID generated from the given name.
|
||||
winrt::guid Profile::_GenerateGuidForProfile(const hstring& name, const hstring& source) noexcept
|
||||
winrt::guid Profile::_GenerateGuidForProfile(const std::wstring_view& name, const std::wstring_view& source) noexcept
|
||||
{
|
||||
// If we have a _source, then we can from a dynamic profile generator. Use
|
||||
// our source to build the namespace guid, instead of using the default GUID.
|
||||
|
@ -496,27 +330,6 @@ winrt::guid Profile::_GenerateGuidForProfile(const hstring& name, const hstring&
|
|||
return { Utils::CreateV5Uuid(namespaceGuid, gsl::as_bytes(gsl::make_span(name))) };
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Parses the given JSON object to get its GUID. If the json object does not
|
||||
// have a `guid` set, we'll generate one, using the `name` field.
|
||||
// Arguments:
|
||||
// - json: the JSON object to get a GUID from, or generate a unique GUID for
|
||||
// (given the `name`)
|
||||
// Return Value:
|
||||
// - The json's `guid`, or a guid synthesized for it.
|
||||
winrt::guid Profile::GetGuidOrGenerateForJson(const Json::Value& json) noexcept
|
||||
{
|
||||
if (const auto guid{ JsonUtils::GetValueForKey<std::optional<GUID>>(json, GuidKey) })
|
||||
{
|
||||
return { guid.value() };
|
||||
}
|
||||
|
||||
const auto name{ JsonUtils::GetValueForKey<hstring>(json, NameKey) };
|
||||
const auto source{ JsonUtils::GetValueForKey<hstring>(json, SourceKey) };
|
||||
|
||||
return Profile::_GenerateGuidForProfile(name, source);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Create a new serialized JsonObject from an instance of this class
|
||||
// Arguments:
|
||||
|
@ -548,7 +361,6 @@ Json::Value Profile::ToJson() const
|
|||
// Control Settings
|
||||
JsonUtils::SetValueForKey(json, ConnectionTypeKey, _ConnectionType);
|
||||
JsonUtils::SetValueForKey(json, CommandlineKey, _Commandline);
|
||||
JsonUtils::SetValueForKey(json, AcrylicTransparencyKey, _AcrylicOpacity);
|
||||
JsonUtils::SetValueForKey(json, UseAcrylicKey, _UseAcrylic);
|
||||
JsonUtils::SetValueForKey(json, SuppressApplicationTitleKey, _SuppressApplicationTitle);
|
||||
JsonUtils::SetValueForKey(json, CloseOnExitKey, _CloseOnExit);
|
||||
|
|
|
@ -76,8 +76,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
struct Profile : ProfileT<Profile>, IInheritable<Profile>
|
||||
{
|
||||
public:
|
||||
Profile();
|
||||
Profile(guid guid);
|
||||
Profile() noexcept = default;
|
||||
Profile(guid guid) noexcept;
|
||||
|
||||
void CreateUnfocusedAppearance();
|
||||
void DeleteUnfocusedAppearance();
|
||||
|
@ -87,19 +87,15 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
return Name();
|
||||
}
|
||||
|
||||
static com_ptr<Profile> CloneInheritanceGraph(com_ptr<Profile> oldProfile, com_ptr<Profile> newProfile, std::unordered_map<void*, com_ptr<Profile>>& visited);
|
||||
static com_ptr<Profile> CopySettings(com_ptr<Profile> source);
|
||||
static void InsertParentHelper(com_ptr<Profile> child, com_ptr<Profile> parent, std::optional<size_t> index = std::nullopt);
|
||||
static void CopyInheritanceGraphs(std::unordered_map<const Profile*, winrt::com_ptr<Profile>>& visited, const std::vector<winrt::com_ptr<Profile>>& source, std::vector<winrt::com_ptr<Profile>>& target);
|
||||
winrt::com_ptr<Profile>& CopyInheritanceGraph(std::unordered_map<const Profile*, winrt::com_ptr<Profile>>& visited) const;
|
||||
winrt::com_ptr<Profile> CopySettings() const;
|
||||
|
||||
Json::Value GenerateStub() const;
|
||||
static com_ptr<Profile> FromJson(const Json::Value& json);
|
||||
bool ShouldBeLayered(const Json::Value& json) const;
|
||||
void LayerJson(const Json::Value& json);
|
||||
static bool IsDynamicProfileObject(const Json::Value& json);
|
||||
Json::Value ToJson() const;
|
||||
|
||||
hstring EvaluatedStartingDirectory() const;
|
||||
static guid GetGuidOrGenerateForJson(const Json::Value& json) noexcept;
|
||||
|
||||
Model::IAppearanceConfig DefaultAppearance();
|
||||
Model::FontConfig FontInfo();
|
||||
|
@ -109,6 +105,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
WINRT_PROPERTY(bool, Deleted, false);
|
||||
WINRT_PROPERTY(OriginTag, Origin, OriginTag::None);
|
||||
|
||||
WINRT_PROPERTY(guid, Updates);
|
||||
INHERITABLE_SETTING(Model::Profile, guid, Guid, _GenerateGuidForProfile(Name(), Source()));
|
||||
INHERITABLE_SETTING(Model::Profile, hstring, Name, L"Default");
|
||||
INHERITABLE_SETTING(Model::Profile, hstring, Source);
|
||||
|
@ -124,7 +121,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
INHERITABLE_SETTING(Model::Profile, bool, SuppressApplicationTitle, false);
|
||||
|
||||
INHERITABLE_SETTING(Model::Profile, bool, UseAcrylic, false);
|
||||
INHERITABLE_SETTING(Model::Profile, double, AcrylicOpacity, 0.5);
|
||||
INHERITABLE_SETTING(Model::Profile, Microsoft::Terminal::Control::ScrollbarState, ScrollState, Microsoft::Terminal::Control::ScrollbarState::Visible);
|
||||
|
||||
INHERITABLE_SETTING(Model::Profile, hstring, Padding, DEFAULT_PADDING);
|
||||
|
@ -149,7 +145,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
Model::FontConfig _FontInfo{ winrt::make<FontConfig>(weak_ref<Model::Profile>(*this)) };
|
||||
static std::wstring EvaluateStartingDirectory(const std::wstring& directory);
|
||||
|
||||
static guid _GenerateGuidForProfile(const hstring& name, const hstring& source) noexcept;
|
||||
static guid _GenerateGuidForProfile(const std::wstring_view& name, const std::wstring_view& source) noexcept;
|
||||
|
||||
friend class SettingsModelLocalTests::DeserializationTests;
|
||||
friend class SettingsModelLocalTests::ProfileTests;
|
||||
|
|
|
@ -50,24 +50,17 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
Boolean Deleted { get; };
|
||||
OriginTag Origin { get; };
|
||||
|
||||
INHERITABLE_PROFILE_SETTING(Guid, Guid);
|
||||
INHERITABLE_PROFILE_SETTING(String, Name);
|
||||
|
||||
Boolean HasGuid();
|
||||
Guid Guid;
|
||||
|
||||
INHERITABLE_PROFILE_SETTING(String, Source);
|
||||
|
||||
Boolean HasConnectionType();
|
||||
Guid ConnectionType;
|
||||
|
||||
INHERITABLE_PROFILE_SETTING(Boolean, Hidden);
|
||||
INHERITABLE_PROFILE_SETTING(Guid, ConnectionType);
|
||||
INHERITABLE_PROFILE_SETTING(String, Icon);
|
||||
INHERITABLE_PROFILE_SETTING(CloseOnExitMode, CloseOnExit);
|
||||
INHERITABLE_PROFILE_SETTING(String, TabTitle);
|
||||
INHERITABLE_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, TabColor);
|
||||
INHERITABLE_PROFILE_SETTING(Boolean, SuppressApplicationTitle);
|
||||
INHERITABLE_PROFILE_SETTING(Boolean, UseAcrylic);
|
||||
INHERITABLE_PROFILE_SETTING(Double, AcrylicOpacity);
|
||||
INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.ScrollbarState, ScrollState);
|
||||
INHERITABLE_PROFILE_SETTING(String, Padding);
|
||||
INHERITABLE_PROFILE_SETTING(String, Commandline);
|
||||
|
|
|
@ -201,6 +201,16 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
|
||||
_IntenseIsBold = WI_IsFlagSet(appearance.IntenseTextStyle(), Microsoft::Terminal::Settings::Model::IntenseStyle::Bold);
|
||||
_IntenseIsBright = WI_IsFlagSet(appearance.IntenseTextStyle(), Microsoft::Terminal::Settings::Model::IntenseStyle::Bright);
|
||||
|
||||
// If the user set an opacity, then just use that. Otherwise, change the
|
||||
// default value based off of whether useAcrylic was set or not. If they
|
||||
// want acrylic, then default to 50%. Otherwise, default to 100% (fully
|
||||
// opaque)
|
||||
_Opacity = appearance.HasOpacity() ?
|
||||
appearance.Opacity() :
|
||||
UseAcrylic() ?
|
||||
.5 :
|
||||
1.0;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -273,7 +283,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
// Fill in the remaining properties from the profile
|
||||
_ProfileName = profile.Name();
|
||||
_UseAcrylic = profile.UseAcrylic();
|
||||
_TintOpacity = profile.AcrylicOpacity();
|
||||
|
||||
_FontFace = profile.FontInfo().FontFace();
|
||||
_FontSize = profile.FontInfo().FontSize();
|
||||
|
|
|
@ -118,7 +118,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, hstring, ProfileName);
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, bool, UseAcrylic, false);
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, double, TintOpacity, 0.5);
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, double, Opacity, UseAcrylic() ? 0.5 : 1.0);
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, hstring, Padding, DEFAULT_PADDING);
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, hstring, FontFace, DEFAULT_FONT_FACE);
|
||||
INHERITABLE_SETTING(Model::TerminalSettings, int32_t, FontSize, DEFAULT_FONT_SIZE);
|
||||
|
|
|
@ -342,6 +342,34 @@ struct ::Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait<::winr
|
|||
}
|
||||
};
|
||||
|
||||
struct IntAsFloatPercentConversionTrait : ::Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait<double>
|
||||
{
|
||||
double FromJson(const Json::Value& json)
|
||||
{
|
||||
return ::base::saturated_cast<double>(json.asUInt()) / 100.0;
|
||||
}
|
||||
|
||||
bool CanConvert(const Json::Value& json)
|
||||
{
|
||||
if (!json.isUInt())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const auto value = json.asUInt();
|
||||
return value >= 0 && value <= 100;
|
||||
}
|
||||
|
||||
Json::Value ToJson(const double& val)
|
||||
{
|
||||
return std::clamp(::base::saturated_cast<uint32_t>(std::round(val * 100.0)), 0u, 100u);
|
||||
}
|
||||
|
||||
std::string TypeDescription() const
|
||||
{
|
||||
return "number (>= 0, <=100)";
|
||||
}
|
||||
};
|
||||
|
||||
// Possible FocusDirection values
|
||||
JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::FocusDirection)
|
||||
{
|
||||
|
|
|
@ -8,20 +8,19 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
enum SettingsLoadWarnings
|
||||
{
|
||||
MissingDefaultProfile = 0,
|
||||
DuplicateProfile = 1,
|
||||
UnknownColorScheme = 2,
|
||||
InvalidBackgroundImage = 3,
|
||||
InvalidIcon = 4,
|
||||
AtLeastOneKeybindingWarning = 5,
|
||||
TooManyKeysForChord = 6,
|
||||
MissingRequiredParameter = 7,
|
||||
LegacyGlobalsProperty = 8,
|
||||
FailedToParseCommandJson = 9,
|
||||
FailedToWriteToSettings = 10,
|
||||
InvalidColorSchemeInCmd = 11,
|
||||
InvalidSplitSize = 12,
|
||||
FailedToParseStartupActions = 13,
|
||||
FailedToParseSubCommands = 14,
|
||||
DuplicateProfile,
|
||||
UnknownColorScheme,
|
||||
InvalidBackgroundImage,
|
||||
InvalidIcon,
|
||||
AtLeastOneKeybindingWarning,
|
||||
TooManyKeysForChord,
|
||||
MissingRequiredParameter,
|
||||
FailedToParseCommandJson,
|
||||
FailedToWriteToSettings,
|
||||
InvalidColorSchemeInCmd,
|
||||
InvalidSplitSize,
|
||||
FailedToParseStartupActions,
|
||||
FailedToParseSubCommands,
|
||||
WARNINGS_SIZE // IMPORTANT: This MUST be the last value in this enum. It's an unused placeholder.
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "pch.h"
|
||||
#include "VsDevCmdGenerator.h"
|
||||
|
||||
using namespace Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
std::wstring VsDevCmdGenerator::GetProfileName(const VsSetupConfiguration::VsSetupInstance& instance) const
|
||||
{
|
||||
|
|
|
@ -16,12 +16,12 @@ Author(s):
|
|||
#pragma once
|
||||
#include "BaseVisualStudioGenerator.h"
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
class VsDevCmdGenerator : public BaseVisualStudioGenerator
|
||||
class VsDevCmdGenerator final : public BaseVisualStudioGenerator
|
||||
{
|
||||
public:
|
||||
std::wstring_view GetNamespace() override
|
||||
std::wstring_view GetNamespace() const noexcept override
|
||||
{
|
||||
return std::wstring_view{ L"Windows.Terminal.VisualStudio.CommandPrompt" };
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "VsDevShellGenerator.h"
|
||||
#include "VsSetupConfiguration.h"
|
||||
|
||||
using namespace Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
std::wstring VsDevShellGenerator::GetProfileName(const VsSetupConfiguration::VsSetupInstance& instance) const
|
||||
{
|
||||
|
|
|
@ -16,12 +16,12 @@ Author(s):
|
|||
#pragma once
|
||||
#include "BaseVisualStudioGenerator.h"
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
class VsDevShellGenerator : public BaseVisualStudioGenerator
|
||||
class VsDevShellGenerator final : public BaseVisualStudioGenerator
|
||||
{
|
||||
public:
|
||||
std::wstring_view GetNamespace() override
|
||||
std::wstring_view GetNamespace() const noexcept override
|
||||
{
|
||||
return std::wstring_view{ L"Windows.Terminal.VisualStudio.Powershell" };
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "pch.h"
|
||||
#include "VsSetupConfiguration.h"
|
||||
|
||||
using namespace Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
std::vector<VsSetupConfiguration::VsSetupInstance> VsSetupConfiguration::QueryInstances()
|
||||
{
|
||||
|
|
|
@ -17,7 +17,7 @@ Author(s):
|
|||
|
||||
#include "Setup.Configuration.h"
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
/// <summary>
|
||||
/// See https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.setup.configuration?view=visualstudiosdk-2019
|
||||
|
|
|
@ -5,13 +5,11 @@
|
|||
|
||||
#include "WslDistroGenerator.h"
|
||||
#include "LegacyProfileGeneratorNamespaces.h"
|
||||
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "../../inc/DefaultSettings.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include "DefaultProfileUtils.h"
|
||||
#include "DynamicProfileUtils.h"
|
||||
|
||||
static constexpr std::wstring_view DockerDistributionPrefix{ L"docker-desktop" };
|
||||
|
||||
|
@ -31,21 +29,29 @@ using namespace winrt::Microsoft::Terminal::Settings::Model;
|
|||
// - Alpine 1777cdf0-b2c4-5a63-a204-eb60f349ea7c
|
||||
// - Ubuntu-18.04 c6eaf9f4-32a7-5fdc-b5cf-066e8a4b1e40
|
||||
|
||||
std::wstring_view WslDistroGenerator::GetNamespace()
|
||||
std::wstring_view WslDistroGenerator::GetNamespace() const noexcept
|
||||
{
|
||||
return WslGeneratorNamespace;
|
||||
}
|
||||
|
||||
static winrt::com_ptr<implementation::Profile> makeProfile(const std::wstring& distName)
|
||||
{
|
||||
const auto WSLDistro{ CreateDynamicProfile(distName) };
|
||||
WSLDistro->Commandline(winrt::hstring{ L"wsl.exe -d " + distName });
|
||||
WSLDistro->DefaultAppearance().ColorSchemeName(L"Campbell");
|
||||
WSLDistro->StartingDirectory(winrt::hstring{ DEFAULT_STARTING_DIRECTORY });
|
||||
WSLDistro->Icon(L"ms-appx:///ProfileIcons/{9acb9455-ca41-5af7-950f-6bca1bc9722f}.png");
|
||||
return WSLDistro;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Enumerates all the installed WSL distros to create profiles for them.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - a vector with all distros for all the installed WSL distros
|
||||
static std::vector<Profile> legacyGenerate()
|
||||
static void legacyGenerate(std::vector<winrt::com_ptr<implementation::Profile>>& profiles)
|
||||
{
|
||||
std::vector<Profile> profiles;
|
||||
|
||||
wil::unique_handle readPipe;
|
||||
wil::unique_handle writePipe;
|
||||
SECURITY_ATTRIBUTES sa{ sizeof(sa), nullptr, true };
|
||||
|
@ -77,7 +83,7 @@ static std::vector<Profile> legacyGenerate()
|
|||
break;
|
||||
case WAIT_ABANDONED:
|
||||
case WAIT_TIMEOUT:
|
||||
return profiles;
|
||||
return;
|
||||
case WAIT_FAILED:
|
||||
THROW_LAST_ERROR();
|
||||
default:
|
||||
|
@ -90,7 +96,7 @@ static std::vector<Profile> legacyGenerate()
|
|||
}
|
||||
else if (exitCode != 0)
|
||||
{
|
||||
return profiles;
|
||||
return;
|
||||
}
|
||||
DWORD bytesAvailable;
|
||||
THROW_IF_WIN32_BOOL_FALSE(PeekNamedPipe(readPipe.get(), nullptr, NULL, nullptr, &bytesAvailable, nullptr));
|
||||
|
@ -117,7 +123,7 @@ static std::vector<Profile> legacyGenerate()
|
|||
std::wstring distName;
|
||||
std::getline(wlinestream, distName, L'\r');
|
||||
|
||||
if (distName.substr(0, std::min(distName.size(), DockerDistributionPrefix.size())) == DockerDistributionPrefix)
|
||||
if (til::starts_with(distName, DockerDistributionPrefix))
|
||||
{
|
||||
// Docker for Windows creates some utility distributions to handle Docker commands.
|
||||
// Pursuant to GH#3556, because they are _not_ user-facing we want to hide them.
|
||||
|
@ -131,17 +137,10 @@ static std::vector<Profile> legacyGenerate()
|
|||
{
|
||||
distName.resize(firstChar);
|
||||
}
|
||||
auto WSLDistro{ CreateDefaultProfile(distName) };
|
||||
|
||||
WSLDistro.Commandline(L"wsl.exe -d " + distName);
|
||||
WSLDistro.DefaultAppearance().ColorSchemeName(L"Campbell");
|
||||
WSLDistro.StartingDirectory(DEFAULT_STARTING_DIRECTORY);
|
||||
WSLDistro.Icon(L"ms-appx:///ProfileIcons/{9acb9455-ca41-5af7-950f-6bca1bc9722f}.png");
|
||||
profiles.emplace_back(WSLDistro);
|
||||
profiles.emplace_back(makeProfile(distName));
|
||||
}
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
|
@ -151,9 +150,8 @@ static std::vector<Profile> legacyGenerate()
|
|||
// - names: a list of distro names to turn into profiles
|
||||
// Return Value:
|
||||
// - the list of profiles we've generated.
|
||||
static std::vector<Profile> namesToProfiles(const std::vector<std::wstring>& names)
|
||||
static void namesToProfiles(const std::vector<std::wstring>& names, std::vector<winrt::com_ptr<implementation::Profile>>& profiles)
|
||||
{
|
||||
std::vector<Profile> profiles;
|
||||
for (const auto& distName : names)
|
||||
{
|
||||
if (til::starts_with(distName, DockerDistributionPrefix))
|
||||
|
@ -163,15 +161,8 @@ static std::vector<Profile> namesToProfiles(const std::vector<std::wstring>& nam
|
|||
continue;
|
||||
}
|
||||
|
||||
auto WSLDistro{ CreateDefaultProfile(distName) };
|
||||
|
||||
WSLDistro.Commandline(L"wsl.exe -d " + distName);
|
||||
WSLDistro.DefaultAppearance().ColorSchemeName(L"Campbell");
|
||||
WSLDistro.StartingDirectory(DEFAULT_STARTING_DIRECTORY);
|
||||
WSLDistro.Icon(L"ms-appx:///ProfileIcons/{9acb9455-ca41-5af7-950f-6bca1bc9722f}.png");
|
||||
profiles.emplace_back(WSLDistro);
|
||||
profiles.emplace_back(makeProfile(distName));
|
||||
}
|
||||
return profiles;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
|
@ -304,7 +295,7 @@ static bool getWslNames(const wil::unique_hkey& wslRootKey,
|
|||
// - <none>
|
||||
// Return Value:
|
||||
// - A list of WSL profiles.
|
||||
std::vector<Profile> WslDistroGenerator::GenerateProfiles()
|
||||
void WslDistroGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const
|
||||
{
|
||||
wil::unique_hkey wslRootKey{ openWslRegKey() };
|
||||
if (wslRootKey)
|
||||
|
@ -316,10 +307,10 @@ std::vector<Profile> WslDistroGenerator::GenerateProfiles()
|
|||
names.reserve(guidStrings.size());
|
||||
if (getWslNames(wslRootKey, guidStrings, names))
|
||||
{
|
||||
return namesToProfiles(names);
|
||||
return namesToProfiles(names, profiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return legacyGenerate();
|
||||
legacyGenerate(profiles);
|
||||
}
|
||||
|
|
|
@ -15,16 +15,15 @@ Author(s):
|
|||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IDynamicProfileGenerator.h"
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
class WslDistroGenerator : public Microsoft::Terminal::Settings::Model::IDynamicProfileGenerator
|
||||
class WslDistroGenerator final : public IDynamicProfileGenerator
|
||||
{
|
||||
public:
|
||||
WslDistroGenerator() = default;
|
||||
~WslDistroGenerator() = default;
|
||||
std::wstring_view GetNamespace() override;
|
||||
std::vector<winrt::Microsoft::Terminal::Settings::Model::Profile> GenerateProfiles() override;
|
||||
std::wstring_view GetNamespace() const noexcept override;
|
||||
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const override;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -101,12 +101,12 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
|
|
|
@ -1,75 +1,31 @@
|
|||
// This file was initially generated by %PRODUCT% %VERSION%
|
||||
// It should still be usable in newer versions, but newer versions might have additional
|
||||
// settings, help text, or changes that you will not see unless you clear this file
|
||||
// and let us generate a new one for you.
|
||||
|
||||
// To view the default settings, hold "alt" while clicking on the "Settings" button.
|
||||
// For documentation on these settings, see: https://aka.ms/terminal-documentation
|
||||
{
|
||||
"$schema": "https://aka.ms/terminal-profiles-schema",
|
||||
|
||||
"defaultProfile": "%DEFAULT_PROFILE%",
|
||||
|
||||
// You can add more global application settings here.
|
||||
// To learn more about global settings, visit https://aka.ms/terminal-global-settings
|
||||
|
||||
// If enabled, selections are automatically copied to your clipboard.
|
||||
// "defaultProfile" is filled in by CascadiaSettings, depending on
|
||||
// what dynamic profiles are present during the first launch.
|
||||
"copyOnSelect": false,
|
||||
|
||||
// If enabled, formatted data is also copied to your clipboard
|
||||
"copyFormatting": false,
|
||||
|
||||
// A profile specifies a command to execute paired with information about how it should look and feel.
|
||||
// Each one of them will appear in the 'New Tab' dropdown,
|
||||
// and can be invoked from the commandline with `wt.exe -p xxx`
|
||||
// To learn more about profiles, visit https://aka.ms/terminal-profile-settings
|
||||
"profiles":
|
||||
{
|
||||
"defaults":
|
||||
{
|
||||
// Put settings here that you want to apply to all profiles.
|
||||
},
|
||||
"list":
|
||||
[
|
||||
{
|
||||
// Make changes here to the powershell.exe profile.
|
||||
"guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
|
||||
"name": "Windows PowerShell",
|
||||
"commandline": "powershell.exe",
|
||||
"hidden": false
|
||||
},
|
||||
{
|
||||
// Make changes here to the cmd.exe profile.
|
||||
// "name" is filled in by CascadiaSettings as a localized string.
|
||||
"guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
|
||||
"name": "%COMMAND_PROMPT_LOCALIZED_NAME%",
|
||||
"commandline": "cmd.exe",
|
||||
"hidden": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// Add custom color schemes to this array.
|
||||
// To learn more about color schemes, visit https://aka.ms/terminal-color-schemes
|
||||
"schemes": [],
|
||||
|
||||
// Add custom actions and keybindings to this array.
|
||||
// To unbind a key combination from your defaults.json, set the command to "unbound".
|
||||
// To learn more about actions and keybindings, visit https://aka.ms/terminal-keybindings
|
||||
"actions":
|
||||
[
|
||||
// Copy and paste are bound to Ctrl+Shift+C and Ctrl+Shift+V in your defaults.json.
|
||||
// These two lines additionally bind them to Ctrl+C and Ctrl+V.
|
||||
// To learn more about selection, visit https://aka.ms/terminal-selection
|
||||
{ "command": {"action": "copy", "singleLine": false }, "keys": "ctrl+c" },
|
||||
{ "command": "paste", "keys": "ctrl+v" },
|
||||
|
||||
// Press Ctrl+Shift+F to open the search box
|
||||
{ "command": "find", "keys": "ctrl+shift+f" },
|
||||
|
||||
// Press Alt+Shift+D to open a new pane.
|
||||
// - "split": "auto" makes this pane open in the direction that provides the most surface area.
|
||||
// - "splitMode": "duplicate" makes the new pane use the focused pane's profile.
|
||||
// To learn more about panes, visit https://aka.ms/terminal-panes
|
||||
{ "command": { "action": "splitPane", "split": "auto", "splitMode": "duplicate" }, "keys": "alt+shift+d" }
|
||||
]
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue