Rely more on profile objects and less on GUIDs (#10982)

Right now, we store GUIDs in panes and most of the functions for interacting
with profiles on the settings model take GUIDs and look up profiles.

This pull request changes how we store and look up profiles to prefer profile
objects. Panes store strong references to their originating profiles, which
simplifies settings lookup for CloseOnExit and the bell settings. In fact,
deleting a pane's profile no longer causes it to forget which CloseOnExit
setting applies to it. Duplicating a pane that is hosting a deleted profile
(#5047) now duplicates the profile, even though it is otherwise unreachable.

This makes the world more consistent and allows us to _eventually_ support panes
hosting profiles that do not have GUIDs that can be looked up in the profile
list. This is a gateway to #6776 and #10669, and consolidating the profile
lookup logic will help with #10952.

PR #10588 introduced TerminalSettings::CreateWithProfile and made
...CreateWithProfileByID a thin wrapper over top it, which looked up the profile
by GUID before proceeding. It has also been removed, as its last caller is gone.

Closes #5047
This commit is contained in:
Dustin L. Howett 2021-08-23 10:11:53 -07:00 committed by GitHub
parent f681d3a1c1
commit f6f5598c9c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 141 additions and 182 deletions

View file

@ -37,7 +37,7 @@ namespace SettingsModelLocalTests
TEST_METHOD(TestTerminalArgsForBinding); TEST_METHOD(TestTerminalArgsForBinding);
TEST_METHOD(MakeSettingsForProfileThatDoesntExist); TEST_METHOD(MakeSettingsForProfile);
TEST_METHOD(MakeSettingsForDefaultProfileThatDoesntExist); TEST_METHOD(MakeSettingsForDefaultProfileThatDoesntExist);
TEST_METHOD(TestLayerProfileOnColorScheme); TEST_METHOD(TestLayerProfileOnColorScheme);
@ -126,10 +126,10 @@ namespace SettingsModelLocalTests
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty()); VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty()); VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) }; const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) }; const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings(); const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid0, guid); VERIFY_ARE_EQUAL(guid0, profile.Guid());
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline()); VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(1, termSettings.HistorySize()); VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
} }
@ -148,10 +148,10 @@ namespace SettingsModelLocalTests
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty()); VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}", realArgs.TerminalArgs().Profile()); VERIFY_ARE_EQUAL(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}", realArgs.TerminalArgs().Profile());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) }; const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) }; const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings(); const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid1, guid); VERIFY_ARE_EQUAL(guid1, profile.Guid());
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline()); VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(2, termSettings.HistorySize()); VERIFY_ARE_EQUAL(2, termSettings.HistorySize());
} }
@ -170,10 +170,10 @@ namespace SettingsModelLocalTests
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty()); VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile()); VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) }; const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) }; const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings(); const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid1, guid); VERIFY_ARE_EQUAL(guid1, profile.Guid());
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline()); VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(2, termSettings.HistorySize()); VERIFY_ARE_EQUAL(2, termSettings.HistorySize());
} }
@ -192,10 +192,10 @@ namespace SettingsModelLocalTests
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty()); VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile()); VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) }; const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) }; const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings(); const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(profile2Guid, guid); VERIFY_ARE_EQUAL(profile2Guid, profile.Guid());
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline()); VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(3, termSettings.HistorySize()); VERIFY_ARE_EQUAL(3, termSettings.HistorySize());
} }
@ -214,10 +214,10 @@ namespace SettingsModelLocalTests
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty()); VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"foo.exe", realArgs.TerminalArgs().Commandline()); VERIFY_ARE_EQUAL(L"foo.exe", realArgs.TerminalArgs().Commandline());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) }; const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) }; const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings(); const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid0, guid); VERIFY_ARE_EQUAL(guid0, profile.Guid());
VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline()); VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(1, termSettings.HistorySize()); VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
} }
@ -237,10 +237,10 @@ namespace SettingsModelLocalTests
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile()); VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
VERIFY_ARE_EQUAL(L"foo.exe", realArgs.TerminalArgs().Commandline()); VERIFY_ARE_EQUAL(L"foo.exe", realArgs.TerminalArgs().Commandline());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) }; const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) }; const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings(); const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid1, guid); VERIFY_ARE_EQUAL(guid1, profile.Guid());
VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline()); VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(2, termSettings.HistorySize()); VERIFY_ARE_EQUAL(2, termSettings.HistorySize());
} }
@ -257,10 +257,10 @@ namespace SettingsModelLocalTests
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty()); VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty()); VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) }; const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) }; const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings(); const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid0, guid); VERIFY_ARE_EQUAL(guid0, profile.Guid());
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline()); VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(1, termSettings.HistorySize()); VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
} }
@ -278,10 +278,10 @@ namespace SettingsModelLocalTests
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty()); VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory()); VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) }; const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) }; const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings(); const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid0, guid); VERIFY_ARE_EQUAL(guid0, profile.Guid());
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline()); VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(L"c:\\foo", termSettings.StartingDirectory()); VERIFY_ARE_EQUAL(L"c:\\foo", termSettings.StartingDirectory());
VERIFY_ARE_EQUAL(1, termSettings.HistorySize()); VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
@ -301,10 +301,10 @@ namespace SettingsModelLocalTests
VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory()); VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile()); VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) }; const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) }; const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings(); const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(profile2Guid, guid); VERIFY_ARE_EQUAL(profile2Guid, profile.Guid());
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline()); VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(L"c:\\foo", termSettings.StartingDirectory()); VERIFY_ARE_EQUAL(L"c:\\foo", termSettings.StartingDirectory());
VERIFY_ARE_EQUAL(3, termSettings.HistorySize()); VERIFY_ARE_EQUAL(3, termSettings.HistorySize());
@ -323,10 +323,10 @@ namespace SettingsModelLocalTests
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty()); VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle()); VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) }; const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) }; const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings(); const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid0, guid); VERIFY_ARE_EQUAL(guid0, profile.Guid());
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline()); VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(L"bar", termSettings.StartingTitle()); VERIFY_ARE_EQUAL(L"bar", termSettings.StartingTitle());
VERIFY_ARE_EQUAL(1, termSettings.HistorySize()); VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
@ -346,10 +346,10 @@ namespace SettingsModelLocalTests
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle()); VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile()); VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) }; const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) }; const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings(); const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(profile2Guid, guid); VERIFY_ARE_EQUAL(profile2Guid, profile.Guid());
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline()); VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(L"bar", termSettings.StartingTitle()); VERIFY_ARE_EQUAL(L"bar", termSettings.StartingTitle());
VERIFY_ARE_EQUAL(3, termSettings.HistorySize()); VERIFY_ARE_EQUAL(3, termSettings.HistorySize());
@ -371,10 +371,10 @@ namespace SettingsModelLocalTests
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle()); VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile()); VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) }; const auto profile{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) }; const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings(); const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid1, guid); VERIFY_ARE_EQUAL(guid1, profile.Guid());
VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline()); VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(L"bar", termSettings.StartingTitle()); VERIFY_ARE_EQUAL(L"bar", termSettings.StartingTitle());
VERIFY_ARE_EQUAL(L"c:\\foo", termSettings.StartingDirectory()); VERIFY_ARE_EQUAL(L"c:\\foo", termSettings.StartingDirectory());
@ -382,9 +382,9 @@ namespace SettingsModelLocalTests
} }
} }
void TerminalSettingsTests::MakeSettingsForProfileThatDoesntExist() void TerminalSettingsTests::MakeSettingsForProfile()
{ {
// Test that making settings throws when the GUID doesn't exist // Test that making settings generally works.
const std::string settingsString{ R"( const std::string settingsString{ R"(
{ {
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}", "defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
@ -405,32 +405,32 @@ namespace SettingsModelLocalTests
const auto guid1 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}"); 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 guid2 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-2222-49a3-80bd-e8fdd045185c}");
const auto guid3 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-3333-49a3-80bd-e8fdd045185c}");
const auto profile1 = settings.FindProfile(guid1);
const auto profile2 = settings.FindProfile(guid2);
try try
{ {
auto terminalSettings{ TerminalSettings::CreateWithProfileByID(settings, guid1, nullptr) }; auto terminalSettings{ TerminalSettings::CreateWithProfile(settings, profile1, nullptr) };
VERIFY_ARE_NOT_EQUAL(nullptr, terminalSettings); VERIFY_ARE_NOT_EQUAL(nullptr, terminalSettings);
VERIFY_ARE_EQUAL(1, terminalSettings.DefaultSettings().HistorySize()); VERIFY_ARE_EQUAL(1, terminalSettings.DefaultSettings().HistorySize());
} }
catch (...) catch (...)
{ {
VERIFY_IS_TRUE(false, L"This call to CreateWithProfileByID should succeed"); VERIFY_IS_TRUE(false, L"This call to CreateWithProfile should succeed");
} }
try try
{ {
auto terminalSettings{ TerminalSettings::CreateWithProfileByID(settings, guid2, nullptr) }; auto terminalSettings{ TerminalSettings::CreateWithProfile(settings, profile2, nullptr) };
VERIFY_ARE_NOT_EQUAL(nullptr, terminalSettings); VERIFY_ARE_NOT_EQUAL(nullptr, terminalSettings);
VERIFY_ARE_EQUAL(2, terminalSettings.DefaultSettings().HistorySize()); VERIFY_ARE_EQUAL(2, terminalSettings.DefaultSettings().HistorySize());
} }
catch (...) catch (...)
{ {
VERIFY_IS_TRUE(false, L"This call to CreateWithProfileByID should succeed"); VERIFY_IS_TRUE(false, L"This call to CreateWithProfile should succeed");
} }
VERIFY_THROWS(auto terminalSettings = TerminalSettings::CreateWithProfileByID(settings, guid3, nullptr), wil::ResultException, L"This call to constructor should fail");
try try
{ {
const auto termSettings{ TerminalSettings::CreateWithNewTerminalArgs(settings, nullptr, nullptr) }; const auto termSettings{ TerminalSettings::CreateWithNewTerminalArgs(settings, nullptr, nullptr) };

View file

@ -430,7 +430,7 @@ namespace TerminalAppLocalTests
Log::Comment(L"Duplicate the tab, and don't crash"); Log::Comment(L"Duplicate the tab, and don't crash");
result = RunOnUIThread([&page]() { result = RunOnUIThread([&page]() {
page->_DuplicateFocusedTab(); page->_DuplicateFocusedTab();
VERIFY_ARE_EQUAL(2u, page->_tabs.Size(), L"We should gracefully do nothing here - the profile no longer exists."); VERIFY_ARE_EQUAL(3u, page->_tabs.Size(), L"We should successfully duplicate a tab hosting a deleted profile.");
}); });
VERIFY_SUCCEEDED(result); VERIFY_SUCCEEDED(result);
} }
@ -530,9 +530,9 @@ namespace TerminalAppLocalTests
VERIFY_ARE_EQUAL(1u, page->_tabs.Size()); VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
VERIFY_ARE_EQUAL(2, VERIFY_ARE_EQUAL(3,
tab->GetLeafPaneCount(), tab->GetLeafPaneCount(),
L"We should gracefully do nothing here - the profile no longer exists."); L"We should successfully duplicate a pane hosting a deleted profile.");
}); });
VERIFY_SUCCEEDED(result); VERIFY_SUCCEEDED(result);

View file

@ -753,11 +753,10 @@ namespace winrt::TerminalApp::implementation
newTerminalArgs = NewTerminalArgs(); newTerminalArgs = NewTerminalArgs();
} }
const auto profileGuid{ _settings.GetProfileForArgs(newTerminalArgs) }; const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings) };
// Manually fill in the evaluated profile. // Manually fill in the evaluated profile.
newTerminalArgs.Profile(::Microsoft::Console::Utils::GuidToString(profileGuid)); newTerminalArgs.Profile(::Microsoft::Console::Utils::GuidToString(profile.Guid()));
_OpenNewWindow(false, newTerminalArgs); _OpenNewWindow(false, newTerminalArgs);
actionArgs.Handled(true); actionArgs.Handled(true);
} }

View file

@ -34,7 +34,7 @@ static const Duration AnimationDuration = DurationHelper::FromTimeSpan(winrt::Wi
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_focusedBorderBrush = { nullptr }; winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_focusedBorderBrush = { nullptr };
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_unfocusedBorderBrush = { nullptr }; winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_unfocusedBorderBrush = { nullptr };
Pane::Pane(const GUID& profile, const TermControl& control, const bool lastFocused) : Pane::Pane(const Profile& profile, const TermControl& control, const bool lastFocused) :
_control{ control }, _control{ control },
_lastActive{ lastFocused }, _lastActive{ lastFocused },
_profile{ profile } _profile{ profile }
@ -758,11 +758,9 @@ void Pane::_ControlConnectionStateChangedHandler(const winrt::Windows::Foundatio
return; return;
} }
const auto settings{ winrt::TerminalApp::implementation::AppLogic::CurrentAppSettings() }; if (_profile)
auto paneProfile = settings.FindProfile(_profile.value());
if (paneProfile)
{ {
auto mode = paneProfile.CloseOnExit(); const auto mode = _profile.CloseOnExit();
if ((mode == CloseOnExitMode::Always) || if ((mode == CloseOnExitMode::Always) ||
(mode == CloseOnExitMode::Graceful && newConnectionState == ConnectionState::Closed)) (mode == CloseOnExitMode::Graceful && newConnectionState == ConnectionState::Closed))
{ {
@ -786,27 +784,25 @@ void Pane::_ControlWarningBellHandler(const winrt::Windows::Foundation::IInspect
{ {
return; return;
} }
const auto settings{ winrt::TerminalApp::implementation::AppLogic::CurrentAppSettings() }; if (_profile)
auto paneProfile = settings.FindProfile(_profile.value());
if (paneProfile)
{ {
// We don't want to do anything if nothing is set, so check for that first // We don't want to do anything if nothing is set, so check for that first
if (static_cast<int>(paneProfile.BellStyle()) != 0) if (static_cast<int>(_profile.BellStyle()) != 0)
{ {
if (WI_IsFlagSet(paneProfile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Audible)) if (WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Audible))
{ {
// Audible is set, play the sound // Audible is set, play the sound
const auto soundAlias = reinterpret_cast<LPCTSTR>(SND_ALIAS_SYSTEMHAND); const auto soundAlias = reinterpret_cast<LPCTSTR>(SND_ALIAS_SYSTEMHAND);
PlaySound(soundAlias, NULL, SND_ALIAS_ID | SND_ASYNC | SND_SENTRY); PlaySound(soundAlias, NULL, SND_ALIAS_ID | SND_ASYNC | SND_SENTRY);
} }
if (WI_IsFlagSet(paneProfile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Window)) if (WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Window))
{ {
_control.BellLightOn(); _control.BellLightOn();
} }
// raise the event with the bool value corresponding to the taskbar flag // raise the event with the bool value corresponding to the taskbar flag
_PaneRaiseBellHandlers(nullptr, WI_IsFlagSet(paneProfile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Taskbar)); _PaneRaiseBellHandlers(nullptr, WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Taskbar));
} }
} }
} }
@ -947,18 +943,18 @@ void Pane::SetActive()
} }
// Method Description: // Method Description:
// - Returns nullopt if no children of this pane were the last control to be // - Returns nullptr if no children of this pane were the last control to be
// focused, or the GUID of the profile of the last control to be focused (if // focused, or the profile of the last control to be focused (if there was
// there was one). // one).
// Arguments: // Arguments:
// - <none> // - <none>
// Return Value: // Return Value:
// - nullopt if no children of this pane were the last control to be // - nullptr if no children of this pane were the last control to be
// focused, else the GUID of the profile of the last control to be focused // focused, else the profile of the last control to be focused
std::optional<GUID> Pane::GetFocusedProfile() Profile Pane::GetFocusedProfile()
{ {
auto lastFocused = GetActivePane(); auto lastFocused = GetActivePane();
return lastFocused ? lastFocused->_profile : std::nullopt; return lastFocused ? lastFocused->_profile : nullptr;
} }
// Method Description: // Method Description:
@ -1059,10 +1055,10 @@ void Pane::_FocusFirstChild()
// * If we're not a leaf, we'll recurse on our children. // * If we're not a leaf, we'll recurse on our children.
// Arguments: // Arguments:
// - settings: The new TerminalSettings to apply to any matching controls // - settings: The new TerminalSettings to apply to any matching controls
// - profile: The GUID of the profile these settings should apply to. // - profile: The profile from which these settings originated.
// Return Value: // Return Value:
// - <none> // - <none>
void Pane::UpdateSettings(const TerminalSettingsCreateResult& settings, const GUID& profile) void Pane::UpdateSettings(const TerminalSettingsCreateResult& settings, const Profile& profile)
{ {
if (!_IsLeaf()) if (!_IsLeaf())
{ {
@ -1071,8 +1067,13 @@ void Pane::UpdateSettings(const TerminalSettingsCreateResult& settings, const GU
} }
else else
{ {
if (profile == _profile) // Because this call may be coming in with a different settings tree,
// we want to map the incoming profile based on its GUID.
// Failure to find a matching profile will result in a pane holding
// a reference to a deleted profile (which is okay!).
if (profile.Guid() == _profile.Guid())
{ {
_profile = profile;
auto controlSettings = _control.Settings().as<TerminalSettings>(); auto controlSettings = _control.Settings().as<TerminalSettings>();
// Update the parent of the control's settings object (and not the object itself) so // Update the parent of the control's settings object (and not the object itself) so
// that any overrides made by the control don't get affected by the reload // that any overrides made by the control don't get affected by the reload
@ -1879,13 +1880,13 @@ std::optional<bool> Pane::PreCalculateCanSplit(const std::shared_ptr<Pane> targe
// we'll create two new children, and place them side-by-side in our Grid. // we'll create two new children, and place them side-by-side in our Grid.
// Arguments: // Arguments:
// - splitType: what type of split we want to create. // - splitType: what type of split we want to create.
// - profile: The profile GUID to associate with the newly created pane. // - profile: The profile to associate with the newly created pane.
// - control: A TermControl to use in the new pane. // - control: A TermControl to use in the new pane.
// Return Value: // Return Value:
// - The two newly created Panes // - The two newly created Panes
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::Split(SplitState splitType, std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::Split(SplitState splitType,
const float splitSize, const float splitSize,
const GUID& profile, const Profile& profile,
const TermControl& control) const TermControl& control)
{ {
if (!_IsLeaf()) if (!_IsLeaf())
@ -2015,9 +2016,9 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitState
// Create two new Panes // Create two new Panes
// Move our control, guid into the first one. // Move our control, guid into the first one.
// Move the new guid, control into the second. // Move the new guid, control into the second.
_firstChild = std::make_shared<Pane>(_profile.value(), _control); _firstChild = std::make_shared<Pane>(_profile, _control);
_firstChild->_connectionState = std::exchange(_connectionState, ConnectionState::NotConnected); _firstChild->_connectionState = std::exchange(_connectionState, ConnectionState::NotConnected);
_profile = std::nullopt; _profile = nullptr;
_control = { nullptr }; _control = { nullptr };
_secondChild = newPane; _secondChild = newPane;

View file

@ -47,13 +47,13 @@ DEFINE_ENUM_FLAG_OPERATORS(Borders);
class Pane : public std::enable_shared_from_this<Pane> class Pane : public std::enable_shared_from_this<Pane>
{ {
public: public:
Pane(const GUID& profile, Pane(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
const winrt::Microsoft::Terminal::Control::TermControl& control, const winrt::Microsoft::Terminal::Control::TermControl& control,
const bool lastFocused = false); const bool lastFocused = false);
std::shared_ptr<Pane> GetActivePane(); std::shared_ptr<Pane> GetActivePane();
winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl(); winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl();
std::optional<GUID> GetFocusedProfile(); winrt::Microsoft::Terminal::Settings::Model::Profile GetFocusedProfile();
winrt::Windows::UI::Xaml::Controls::Grid GetRootElement(); winrt::Windows::UI::Xaml::Controls::Grid GetRootElement();
@ -63,7 +63,7 @@ public:
void SetActive(); void SetActive();
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings, void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings,
const GUID& profile); const winrt::Microsoft::Terminal::Settings::Model::Profile& profile);
void ResizeContent(const winrt::Windows::Foundation::Size& newSize); void ResizeContent(const winrt::Windows::Foundation::Size& newSize);
void Relayout(); void Relayout();
bool ResizePane(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction); bool ResizePane(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
@ -75,7 +75,7 @@ public:
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Split(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType, std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Split(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
const float splitSize, const float splitSize,
const GUID& profile, const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
const winrt::Microsoft::Terminal::Control::TermControl& control); const winrt::Microsoft::Terminal::Control::TermControl& control);
bool ToggleSplitOrientation(); bool ToggleSplitOrientation();
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const; float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
@ -160,7 +160,7 @@ private:
std::optional<uint32_t> _id; std::optional<uint32_t> _id;
bool _lastActive{ false }; bool _lastActive{ false };
std::optional<GUID> _profile{ std::nullopt }; winrt::Microsoft::Terminal::Settings::Model::Profile _profile{ nullptr };
winrt::event_token _connectionStateChangedToken{ 0 }; winrt::event_token _connectionStateChangedToken{ 0 };
winrt::event_token _firstClosedToken{ 0 }; winrt::event_token _firstClosedToken{ 0 };
winrt::event_token _secondClosedToken{ 0 }; winrt::event_token _secondClosedToken{ 0 };

View file

@ -59,10 +59,10 @@ namespace winrt::TerminalApp::implementation
HRESULT TerminalPage::_OpenNewTab(const NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection) HRESULT TerminalPage::_OpenNewTab(const NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection)
try try
{ {
const auto profileGuid{ _settings.GetProfileForArgs(newTerminalArgs) }; const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings) }; const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings) };
_CreateNewTabFromSettings(profileGuid, settings, existingConnection); _CreateNewTabWithProfileAndSettings(profile, settings, existingConnection);
const uint32_t tabCount = _tabs.Size(); const uint32_t tabCount = _tabs.Size();
const bool usedManualProfile = (newTerminalArgs != nullptr) && const bool usedManualProfile = (newTerminalArgs != nullptr) &&
@ -70,7 +70,7 @@ namespace winrt::TerminalApp::implementation
newTerminalArgs.Profile().empty()); newTerminalArgs.Profile().empty());
// Lookup the name of the color scheme used by this profile. // Lookup the name of the color scheme used by this profile.
const auto scheme = _settings.GetColorSchemeForProfile(profileGuid); const auto scheme = _settings.GetColorSchemeForProfile(profile);
// If they explicitly specified `null` as the scheme (indicating _no_ scheme), log // If they explicitly specified `null` as the scheme (indicating _no_ scheme), log
// that as the empty string. // that as the empty string.
const auto schemeName = scheme ? scheme.Name() : L"\0"; const auto schemeName = scheme ? scheme.Name() : L"\0";
@ -82,7 +82,7 @@ namespace winrt::TerminalApp::implementation
TraceLoggingUInt32(1u, "EventVer", "Version of this event"), TraceLoggingUInt32(1u, "EventVer", "Version of this event"),
TraceLoggingUInt32(tabCount, "TabCount", "Count of tabs currently opened in TerminalApp"), TraceLoggingUInt32(tabCount, "TabCount", "Count of tabs currently opened in TerminalApp"),
TraceLoggingBool(usedManualProfile, "ProfileSpecified", "Whether the new tab specified a profile explicitly"), TraceLoggingBool(usedManualProfile, "ProfileSpecified", "Whether the new tab specified a profile explicitly"),
TraceLoggingGuid(profileGuid, "ProfileGuid", "The GUID of the profile spawned in the new tab"), 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"), TraceLoggingBool(settings.DefaultSettings().UseAcrylic(), "UseAcrylic", "The acrylic preference from the settings"),
TraceLoggingFloat64(settings.DefaultSettings().TintOpacity(), "TintOpacity", "Opacity preference from the settings"), TraceLoggingFloat64(settings.DefaultSettings().TintOpacity(), "TintOpacity", "Opacity preference from the settings"),
TraceLoggingWideString(settings.DefaultSettings().FontFace().c_str(), "FontFace", "Font face chosen in the settings"), TraceLoggingWideString(settings.DefaultSettings().FontFace().c_str(), "FontFace", "Font face chosen in the settings"),
@ -175,10 +175,9 @@ namespace winrt::TerminalApp::implementation
_tabView.TabItems().Append(tabViewItem); _tabView.TabItems().Append(tabViewItem);
// Set this tab's icon to the icon from the user's profile // Set this tab's icon to the icon from the user's profile
if (const auto profileGuid = newTabImpl->GetFocusedProfile()) if (const auto profile{ newTabImpl->GetFocusedProfile() })
{ {
const auto profile = _settings.FindProfile(profileGuid.value()); if (!profile.Icon().empty())
if (profile != nullptr && !profile.Icon().empty())
{ {
newTabImpl->UpdateIcon(profile.Icon()); newTabImpl->UpdateIcon(profile.Icon());
} }
@ -233,14 +232,14 @@ namespace winrt::TerminalApp::implementation
// - Creates a new tab with the given settings. If the tab bar is not being // - Creates a new tab with the given settings. If the tab bar is not being
// currently displayed, it will be shown. // currently displayed, it will be shown.
// Arguments: // Arguments:
// - profileGuid: ID to use to lookup profile settings for this connection // - profile: profile settings for this connection
// - settings: the TerminalSettings object to use to create the TerminalControl with. // - settings: the TerminalSettings object to use to create the TerminalControl with.
// - existingConnection: optionally receives a connection from the outside world instead of attempting to create one // - existingConnection: optionally receives a connection from the outside world instead of attempting to create one
void TerminalPage::_CreateNewTabFromSettings(GUID profileGuid, const TerminalSettingsCreateResult& settings, TerminalConnection::ITerminalConnection existingConnection) void TerminalPage::_CreateNewTabWithProfileAndSettings(const Profile& profile, const TerminalSettingsCreateResult& settings, TerminalConnection::ITerminalConnection existingConnection)
{ {
// Initialize the new tab // Initialize the new tab
// Create a connection based on the values in our settings object if we weren't given one. // Create a connection based on the values in our settings object if we weren't given one.
auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profileGuid, settings.DefaultSettings()); auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profile, settings.DefaultSettings());
// If we had an `existingConnection`, then this is an inbound handoff from somewhere else. // If we had an `existingConnection`, then this is an inbound handoff from somewhere else.
// We need to tell it about our size information so it can match the dimensions of what // We need to tell it about our size information so it can match the dimensions of what
@ -268,7 +267,7 @@ namespace winrt::TerminalApp::implementation
// This way, when we do a settings reload we just update the parent and the overrides remain // This way, when we do a settings reload we just update the parent and the overrides remain
auto term = _InitControl(settings, connection); auto term = _InitControl(settings, connection);
auto newTabImpl = winrt::make_self<TerminalTab>(profileGuid, term); auto newTabImpl = winrt::make_self<TerminalTab>(profile, term);
_RegisterTerminalEvents(term); _RegisterTerminalEvents(term);
_InitializeTab(newTabImpl); _InitializeTab(newTabImpl);
@ -277,7 +276,7 @@ namespace winrt::TerminalApp::implementation
auto newControl = _InitControl(settings, debugConnection); auto newControl = _InitControl(settings, debugConnection);
_RegisterTerminalEvents(newControl); _RegisterTerminalEvents(newControl);
// Split (auto) with the debug tap. // Split (auto) with the debug tap.
newTabImpl->SplitPane(SplitState::Automatic, 0.5f, profileGuid, newControl); newTabImpl->SplitPane(SplitState::Automatic, 0.5f, profile, newControl);
} }
} }
@ -288,19 +287,9 @@ namespace winrt::TerminalApp::implementation
// - tab: the Tab to update the title for. // - tab: the Tab to update the title for.
void TerminalPage::_UpdateTabIcon(TerminalTab& tab) void TerminalPage::_UpdateTabIcon(TerminalTab& tab)
{ {
const auto lastFocusedProfileOpt = tab.GetFocusedProfile(); if (const auto profile = tab.GetFocusedProfile())
if (lastFocusedProfileOpt.has_value())
{ {
const auto lastFocusedProfile = lastFocusedProfileOpt.value(); tab.UpdateIcon(profile.Icon());
const auto matchingProfile = _settings.FindProfile(lastFocusedProfile);
if (matchingProfile)
{
tab.UpdateIcon(matchingProfile.Icon());
}
else
{
tab.UpdateIcon({});
}
} }
} }
@ -354,23 +343,16 @@ namespace winrt::TerminalApp::implementation
{ {
try try
{ {
// TODO: GH#5047 - In the future, we should get the Profile of // TODO: GH#5047 - We're duplicating the whole profile, which might
// the focused pane, and use that to build a new instance of the // be a dangling reference to old settings.
// settings so we can duplicate this tab/pane.
// //
// Currently, if the profile doesn't exist anymore in our // In the future, it may be preferable to just duplicate the
// settings, we'll silently do nothing. // current control's live settings (which will include changes
// // made through VT).
// In the future, it will be preferable to just duplicate the
// current control's settings, but we can't do that currently,
// because we won't be able to create a new instance of the
// connection without keeping an instance of the original Profile
// object around.
const auto& profileGuid = tab.GetFocusedProfile(); if (const auto profile = tab.GetFocusedProfile())
if (profileGuid.has_value())
{ {
const auto settingsCreateResult{ TerminalSettings::CreateWithProfileByID(_settings, profileGuid.value(), *_bindings) }; const auto settingsCreateResult{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory(); const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory();
const auto validWorkingDirectory = !workingDirectory.empty(); const auto validWorkingDirectory = !workingDirectory.empty();
if (validWorkingDirectory) if (validWorkingDirectory)
@ -378,7 +360,7 @@ namespace winrt::TerminalApp::implementation
settingsCreateResult.DefaultSettings().StartingDirectory(workingDirectory); settingsCreateResult.DefaultSettings().StartingDirectory(workingDirectory);
} }
_CreateNewTabFromSettings(profileGuid.value(), settingsCreateResult); _CreateNewTabWithProfileAndSettings(profile, settingsCreateResult);
const auto runtimeTabText{ tab.GetTabText() }; const auto runtimeTabText{ tab.GetTabText() };
if (!runtimeTabText.empty()) if (!runtimeTabText.empty())

View file

@ -771,7 +771,12 @@ namespace winrt::TerminalApp::implementation
// Manually fill in the evaluated profile. // Manually fill in the evaluated profile.
if (newTerminalArgs.ProfileIndex() != nullptr) if (newTerminalArgs.ProfileIndex() != nullptr)
{ {
newTerminalArgs.Profile(::Microsoft::Console::Utils::GuidToString(this->_settings.GetProfileForArgs(newTerminalArgs))); // We want to promote the index to a GUID because there is no "launch to profile index" command.
const auto profile = _settings.GetProfileForArgs(newTerminalArgs);
if (profile)
{
newTerminalArgs.Profile(::Microsoft::Console::Utils::GuidToString(profile.Guid()));
}
} }
this->_OpenNewWindow(false, newTerminalArgs); this->_OpenNewWindow(false, newTerminalArgs);
} }
@ -794,14 +799,18 @@ namespace winrt::TerminalApp::implementation
// Method Description: // Method Description:
// - Creates a new connection based on the profile settings // - Creates a new connection based on the profile settings
// Arguments: // Arguments:
// - the profile GUID we want the settings from // - the profile we want the settings from
// - the terminal settings // - the terminal settings
// Return value: // Return value:
// - the desired connection // - the desired connection
TerminalConnection::ITerminalConnection TerminalPage::_CreateConnectionFromSettings(GUID profileGuid, TerminalConnection::ITerminalConnection TerminalPage::_CreateConnectionFromSettings(Profile profile,
TerminalSettings settings) TerminalSettings settings)
{ {
const auto profile = _settings.FindProfile(profileGuid); if (!profile)
{
// Use the default profile if we didn't get one as an argument.
profile = _settings.FindProfile(_settings.GlobalSettings().DefaultProfile());
}
TerminalConnection::ITerminalConnection connection{ nullptr }; TerminalConnection::ITerminalConnection connection{ nullptr };
@ -826,7 +835,8 @@ namespace winrt::TerminalApp::implementation
else else
{ {
std::wstring guidWString = Utils::GuidToString(profileGuid); // profile is guaranteed to exist here
std::wstring guidWString = Utils::GuidToString(profile.Guid());
StringMap envMap{}; StringMap envMap{};
envMap.Insert(L"WT_PROFILE_ID", guidWString); envMap.Insert(L"WT_PROFILE_ID", guidWString);
@ -875,7 +885,7 @@ namespace winrt::TerminalApp::implementation
"ConnectionCreated", "ConnectionCreated",
TraceLoggingDescription("Event emitted upon the creation of a connection"), TraceLoggingDescription("Event emitted upon the creation of a connection"),
TraceLoggingGuid(connectionType, "ConnectionTypeGuid", "The type of the connection"), TraceLoggingGuid(connectionType, "ConnectionTypeGuid", "The type of the connection"),
TraceLoggingGuid(profileGuid, "ProfileGuid", "The profile's GUID"), TraceLoggingGuid(profile.Guid(), "ProfileGuid", "The profile's GUID"),
TraceLoggingGuid(sessionGuid, "SessionGuid", "The WT_SESSION's GUID"), TraceLoggingGuid(sessionGuid, "SessionGuid", "The WT_SESSION's GUID"),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance)); TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
@ -1344,23 +1354,20 @@ namespace winrt::TerminalApp::implementation
try try
{ {
TerminalSettingsCreateResult controlSettings{ nullptr }; TerminalSettingsCreateResult controlSettings{ nullptr };
GUID realGuid; Profile profile{ nullptr };
bool profileFound = false;
if (splitMode == SplitType::Duplicate) if (splitMode == SplitType::Duplicate)
{ {
std::optional<GUID> current_guid = tab.GetFocusedProfile(); profile = tab.GetFocusedProfile();
if (current_guid) if (profile)
{ {
profileFound = true; controlSettings = TerminalSettings::CreateWithProfile(_settings, profile, *_bindings);
controlSettings = TerminalSettings::CreateWithProfileByID(_settings, current_guid.value(), *_bindings);
const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory(); const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory();
const auto validWorkingDirectory = !workingDirectory.empty(); const auto validWorkingDirectory = !workingDirectory.empty();
if (validWorkingDirectory) if (validWorkingDirectory)
{ {
controlSettings.DefaultSettings().StartingDirectory(workingDirectory); controlSettings.DefaultSettings().StartingDirectory(workingDirectory);
} }
realGuid = current_guid.value();
} }
// TODO: GH#5047 - In the future, we should get the Profile of // TODO: GH#5047 - In the future, we should get the Profile of
// the focused pane, and use that to build a new instance of the // the focused pane, and use that to build a new instance of the
@ -1375,13 +1382,13 @@ namespace winrt::TerminalApp::implementation
// connection without keeping an instance of the original Profile // connection without keeping an instance of the original Profile
// object around. // object around.
} }
if (!profileFound) if (!profile)
{ {
realGuid = _settings.GetProfileForArgs(newTerminalArgs); profile = _settings.GetProfileForArgs(newTerminalArgs);
controlSettings = TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings); controlSettings = TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings);
} }
const auto controlConnection = _CreateConnectionFromSettings(realGuid, controlSettings.DefaultSettings()); const auto controlConnection = _CreateConnectionFromSettings(profile, controlSettings.DefaultSettings());
const float contentWidth = ::base::saturated_cast<float>(_tabContent.ActualWidth()); const float contentWidth = ::base::saturated_cast<float>(_tabContent.ActualWidth());
const float contentHeight = ::base::saturated_cast<float>(_tabContent.ActualHeight()); const float contentHeight = ::base::saturated_cast<float>(_tabContent.ActualHeight());
@ -1406,7 +1413,7 @@ namespace winrt::TerminalApp::implementation
_UnZoomIfNeeded(); _UnZoomIfNeeded();
tab.SplitPane(realSplitType, splitSize, realGuid, newControl); tab.SplitPane(realSplitType, splitSize, profile, newControl);
} }
CATCH_LOG(); CATCH_LOG();
} }
@ -1992,19 +1999,15 @@ namespace winrt::TerminalApp::implementation
auto profiles = _settings.ActiveProfiles(); auto profiles = _settings.ActiveProfiles();
for (const auto& profile : profiles) for (const auto& profile : profiles)
{ {
const auto profileGuid = profile.Guid();
try try
{ {
// This can throw an exception if the profileGuid does auto settings{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
// not belong to an actual profile in the list of profiles.
auto settings{ TerminalSettings::CreateWithProfileByID(_settings, profileGuid, *_bindings) };
for (auto tab : _tabs) for (auto tab : _tabs)
{ {
if (auto terminalTab = _GetTerminalTabImpl(tab)) if (auto terminalTab = _GetTerminalTabImpl(tab))
{ {
terminalTab->UpdateSettings(settings, profileGuid); terminalTab->UpdateSettings(settings, profile);
} }
} }
} }

View file

@ -189,8 +189,8 @@ namespace winrt::TerminalApp::implementation
void _OpenNewTabDropdown(); void _OpenNewTabDropdown();
HRESULT _OpenNewTab(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr); HRESULT _OpenNewTab(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
void _CreateNewTabFromPane(std::shared_ptr<Pane> pane); void _CreateNewTabFromPane(std::shared_ptr<Pane> pane);
void _CreateNewTabFromSettings(GUID profileGuid, const Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr); void _CreateNewTabWithProfileAndSettings(const Microsoft::Terminal::Settings::Model::Profile& profile, const Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr);
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(GUID profileGuid, Microsoft::Terminal::Settings::Model::TerminalSettings settings); winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(Microsoft::Terminal::Settings::Model::Profile profile, Microsoft::Terminal::Settings::Model::TerminalSettings settings);
winrt::fire_and_forget _OpenNewWindow(const bool elevate, const Microsoft::Terminal::Settings::Model::NewTerminalArgs newTerminalArgs); winrt::fire_and_forget _OpenNewWindow(const bool elevate, const Microsoft::Terminal::Settings::Model::NewTerminalArgs newTerminalArgs);

View file

@ -25,7 +25,7 @@ namespace winrt
namespace winrt::TerminalApp::implementation namespace winrt::TerminalApp::implementation
{ {
TerminalTab::TerminalTab(const GUID& profile, const TermControl& control) TerminalTab::TerminalTab(const Profile& profile, const TermControl& control)
{ {
_rootPane = std::make_shared<Pane>(profile, control, true); _rootPane = std::make_shared<Pane>(profile, control, true);
@ -257,7 +257,7 @@ namespace winrt::TerminalApp::implementation
// Return Value: // Return Value:
// - nullopt if no children of this tab were the last control to be // - nullopt if no children of this tab were the last control to be
// focused, else the GUID of the profile of the last control to be focused // focused, else the GUID of the profile of the last control to be focused
std::optional<GUID> TerminalTab::GetFocusedProfile() const noexcept Profile TerminalTab::GetFocusedProfile() const noexcept
{ {
return _activePane->GetFocusedProfile(); return _activePane->GetFocusedProfile();
} }
@ -269,7 +269,7 @@ namespace winrt::TerminalApp::implementation
// - profile: The GUID of the profile these settings should apply to. // - profile: The GUID of the profile these settings should apply to.
// Return Value: // Return Value:
// - <none> // - <none>
void TerminalTab::UpdateSettings(const TerminalSettingsCreateResult& settings, const GUID& profile) void TerminalTab::UpdateSettings(const TerminalSettingsCreateResult& settings, const Profile& profile)
{ {
_rootPane->UpdateSettings(settings, profile); _rootPane->UpdateSettings(settings, profile);
@ -451,7 +451,7 @@ namespace winrt::TerminalApp::implementation
// - <none> // - <none>
void TerminalTab::SplitPane(SplitState splitType, void TerminalTab::SplitPane(SplitState splitType,
const float splitSize, const float splitSize,
const GUID& profile, const Profile& profile,
TermControl& control) TermControl& control)
{ {
// Make sure to take the ID before calling Split() - Split() will clear out the active pane's ID // Make sure to take the ID before calling Split() - Split() will clear out the active pane's ID

View file

@ -21,14 +21,14 @@ namespace winrt::TerminalApp::implementation
struct TerminalTab : TerminalTabT<TerminalTab, TabBase> struct TerminalTab : TerminalTabT<TerminalTab, TabBase>
{ {
public: public:
TerminalTab(const GUID& profile, const winrt::Microsoft::Terminal::Control::TermControl& control); TerminalTab(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile, const winrt::Microsoft::Terminal::Control::TermControl& control);
TerminalTab(std::shared_ptr<Pane> rootPane); TerminalTab(std::shared_ptr<Pane> rootPane);
// Called after construction to perform the necessary setup, which relies on weak_ptr // Called after construction to perform the necessary setup, which relies on weak_ptr
void Initialize(); void Initialize();
winrt::Microsoft::Terminal::Control::TermControl GetActiveTerminalControl() const; winrt::Microsoft::Terminal::Control::TermControl GetActiveTerminalControl() const;
std::optional<GUID> GetFocusedProfile() const noexcept; winrt::Microsoft::Terminal::Settings::Model::Profile GetFocusedProfile() const noexcept;
void Focus(winrt::Windows::UI::Xaml::FocusState focusState) override; void Focus(winrt::Windows::UI::Xaml::FocusState focusState) override;
@ -40,7 +40,7 @@ namespace winrt::TerminalApp::implementation
void SplitPane(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType, void SplitPane(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
const float splitSize, const float splitSize,
const GUID& profile, const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
winrt::Microsoft::Terminal::Control::TermControl& control); winrt::Microsoft::Terminal::Control::TermControl& control);
void ToggleSplitOrientation(); void ToggleSplitOrientation();
@ -62,7 +62,7 @@ namespace winrt::TerminalApp::implementation
bool SwapPane(const winrt::Microsoft::Terminal::Settings::Model::FocusDirection& direction); bool SwapPane(const winrt::Microsoft::Terminal::Settings::Model::FocusDirection& direction);
bool FocusPane(const uint32_t id); bool FocusPane(const uint32_t id);
void UpdateSettings(const Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings, const GUID& profile); void UpdateSettings(const Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings, const winrt::Microsoft::Terminal::Settings::Model::Profile& profile);
winrt::fire_and_forget UpdateTitle(); winrt::fire_and_forget UpdateTitle();
void Shutdown() override; void Shutdown() override;

View file

@ -136,13 +136,12 @@ void CascadiaSettings::_CopyProfileInheritanceTree(winrt::com_ptr<CascadiaSettin
// - Finds a profile that matches the given GUID. If there is no profile in this // - Finds a profile that matches the given GUID. If there is no profile in this
// settings object that matches, returns nullptr. // settings object that matches, returns nullptr.
// Arguments: // Arguments:
// - profileGuid: the GUID of the profile to return. // - guid: the GUID of the profile to return.
// Return Value: // Return Value:
// - a non-ownership pointer to the profile matching the given guid, or nullptr // - a strong reference to the profile matching the given guid, or nullptr
// if there is no match. // if there is no match.
winrt::Microsoft::Terminal::Settings::Model::Profile CascadiaSettings::FindProfile(winrt::guid profileGuid) const noexcept winrt::Microsoft::Terminal::Settings::Model::Profile CascadiaSettings::FindProfile(const winrt::guid& guid) const noexcept
{ {
const winrt::guid guid{ profileGuid };
for (const auto& profile : _allProfiles) for (const auto& profile : _allProfiles)
{ {
try try
@ -805,7 +804,7 @@ void CascadiaSettings::_ValidateMediaResources()
// and attempt to look the profile up by name instead. // and attempt to look the profile up by name instead.
// Return Value: // Return Value:
// - the GUID of the profile corresponding to this combination of index and NewTerminalArgs // - the GUID of the profile corresponding to this combination of index and NewTerminalArgs
winrt::guid CascadiaSettings::GetProfileForArgs(const Model::NewTerminalArgs& newTerminalArgs) const winrt::Microsoft::Terminal::Settings::Model::Profile CascadiaSettings::GetProfileForArgs(const Model::NewTerminalArgs& newTerminalArgs) const
{ {
std::optional<winrt::guid> profileByIndex, profileByName; std::optional<winrt::guid> profileByIndex, profileByName;
if (newTerminalArgs) if (newTerminalArgs)
@ -818,7 +817,7 @@ winrt::guid CascadiaSettings::GetProfileForArgs(const Model::NewTerminalArgs& ne
profileByName = _GetProfileGuidByName(newTerminalArgs.Profile()); profileByName = _GetProfileGuidByName(newTerminalArgs.Profile());
} }
return til::coalesce_value(profileByName, profileByIndex, _globals->DefaultProfile()); return FindProfile(til::coalesce_value(profileByName, profileByIndex, _globals->DefaultProfile()));
} }
// Method Description: // Method Description:
@ -1043,9 +1042,8 @@ std::string CascadiaSettings::_ApplyFirstRunChangesToSettingsTemplate(std::strin
// - profileGuid: the GUID of the profile to find the scheme for. // - profileGuid: the GUID of the profile to find the scheme for.
// Return Value: // Return Value:
// - a non-owning pointer to the scheme. // - a non-owning pointer to the scheme.
winrt::Microsoft::Terminal::Settings::Model::ColorScheme CascadiaSettings::GetColorSchemeForProfile(const winrt::guid profileGuid) const winrt::Microsoft::Terminal::Settings::Model::ColorScheme CascadiaSettings::GetColorSchemeForProfile(const Model::Profile& profile) const
{ {
auto profile = FindProfile(profileGuid);
if (!profile) if (!profile)
{ {
return nullptr; return nullptr;

View file

@ -86,8 +86,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static winrt::hstring ApplicationVersion(); static winrt::hstring ApplicationVersion();
Model::Profile CreateNewProfile(); Model::Profile CreateNewProfile();
Model::Profile FindProfile(guid profileGuid) const noexcept; Model::Profile FindProfile(const guid& profileGuid) const noexcept;
Model::ColorScheme GetColorSchemeForProfile(const guid profileGuid) const; Model::ColorScheme GetColorSchemeForProfile(const Model::Profile& profile) const;
void UpdateColorSchemeReferences(const hstring oldName, const hstring newName); void UpdateColorSchemeReferences(const hstring oldName, const hstring newName);
Windows::Foundation::Collections::IVectorView<SettingsLoadWarnings> Warnings(); Windows::Foundation::Collections::IVectorView<SettingsLoadWarnings> Warnings();
@ -96,7 +96,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
Windows::Foundation::IReference<SettingsLoadErrors> GetLoadingError(); Windows::Foundation::IReference<SettingsLoadErrors> GetLoadingError();
hstring GetSerializationErrorMessage(); hstring GetSerializationErrorMessage();
winrt::guid GetProfileForArgs(const Model::NewTerminalArgs& newTerminalArgs) const; Model::Profile GetProfileForArgs(const Model::NewTerminalArgs& newTerminalArgs) const;
Model::Profile DuplicateProfile(const Model::Profile& source); Model::Profile DuplicateProfile(const Model::Profile& source);
void RefreshDefaultTerminals(); void RefreshDefaultTerminals();

View file

@ -41,10 +41,10 @@ namespace Microsoft.Terminal.Settings.Model
Profile CreateNewProfile(); Profile CreateNewProfile();
Profile FindProfile(Guid profileGuid); Profile FindProfile(Guid profileGuid);
ColorScheme GetColorSchemeForProfile(Guid profileGuid); ColorScheme GetColorSchemeForProfile(Profile profile);
void UpdateColorSchemeReferences(String oldName, String newName); void UpdateColorSchemeReferences(String oldName, String newName);
Guid GetProfileForArgs(NewTerminalArgs newTerminalArgs); Profile GetProfileForArgs(NewTerminalArgs newTerminalArgs);
void RefreshDefaultTerminals(); void RefreshDefaultTerminals();
static Boolean IsDefaultTerminalAvailable { get; }; static Boolean IsDefaultTerminalAvailable { get; };

View file

@ -83,25 +83,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return winrt::make<TerminalSettingsCreateResult>(*settings, child); return winrt::make<TerminalSettingsCreateResult>(*settings, child);
} }
// Method Description:
// - Create a TerminalSettingsCreateResult for the provided profile guid. We'll
// use the guid to look up the profile that should be used to
// create these TerminalSettings. Then, we'll apply settings contained in the
// global and profile settings to the instance.
// Arguments:
// - appSettings: the set of settings being used to construct the new terminal
// - profileGuid: the unique identifier (guid) of the profile
// - keybindings: the keybinding handler
// Return Value:
// - A TerminalSettingsCreateResult, which contains a pair of TerminalSettings objects,
// one for when the terminal is focused and the other for when the terminal is unfocused
Model::TerminalSettingsCreateResult TerminalSettings::CreateWithProfileByID(const Model::CascadiaSettings& appSettings, winrt::guid profileGuid, const IKeyBindings& keybindings)
{
const auto profile = appSettings.FindProfile(profileGuid);
THROW_HR_IF_NULL(E_INVALIDARG, profile);
return CreateWithProfile(appSettings, profile, keybindings);
}
// Method Description: // Method Description:
// - Create a TerminalSettings object for the provided newTerminalArgs. We'll // - Create a TerminalSettings object for the provided newTerminalArgs. We'll
// use the newTerminalArgs to look up the profile that should be used to // use the newTerminalArgs to look up the profile that should be used to
@ -124,8 +105,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
const NewTerminalArgs& newTerminalArgs, const NewTerminalArgs& newTerminalArgs,
const IKeyBindings& keybindings) const IKeyBindings& keybindings)
{ {
const guid profileGuid = appSettings.GetProfileForArgs(newTerminalArgs); const auto profile = appSettings.GetProfileForArgs(newTerminalArgs);
auto settingsPair{ CreateWithProfileByID(appSettings, profileGuid, keybindings) }; auto settingsPair{ CreateWithProfile(appSettings, profile, keybindings) };
auto defaultSettings = settingsPair.DefaultSettings(); auto defaultSettings = settingsPair.DefaultSettings();
if (newTerminalArgs) if (newTerminalArgs)

View file

@ -60,10 +60,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
const Model::Profile& profile, const Model::Profile& profile,
const Control::IKeyBindings& keybindings); const Control::IKeyBindings& keybindings);
static Model::TerminalSettingsCreateResult CreateWithProfileByID(const Model::CascadiaSettings& appSettings,
guid profileGuid,
const Control::IKeyBindings& keybindings);
static Model::TerminalSettingsCreateResult CreateWithNewTerminalArgs(const Model::CascadiaSettings& appSettings, static Model::TerminalSettingsCreateResult CreateWithNewTerminalArgs(const Model::CascadiaSettings& appSettings,
const Model::NewTerminalArgs& newTerminalArgs, const Model::NewTerminalArgs& newTerminalArgs,
const Control::IKeyBindings& keybindings); const Control::IKeyBindings& keybindings);

View file

@ -27,7 +27,6 @@ namespace Microsoft.Terminal.Settings.Model
TerminalSettings(); TerminalSettings();
static TerminalSettingsCreateResult CreateWithProfile(CascadiaSettings appSettings, Profile profile, Microsoft.Terminal.Control.IKeyBindings keybindings); static TerminalSettingsCreateResult CreateWithProfile(CascadiaSettings appSettings, Profile profile, Microsoft.Terminal.Control.IKeyBindings keybindings);
static TerminalSettingsCreateResult CreateWithProfileByID(CascadiaSettings appSettings, Guid profileGuid, Microsoft.Terminal.Control.IKeyBindings keybindings);
static TerminalSettingsCreateResult CreateWithNewTerminalArgs(CascadiaSettings appSettings, NewTerminalArgs newTerminalArgs, Microsoft.Terminal.Control.IKeyBindings keybindings); static TerminalSettingsCreateResult CreateWithNewTerminalArgs(CascadiaSettings appSettings, NewTerminalArgs newTerminalArgs, Microsoft.Terminal.Control.IKeyBindings keybindings);
static TerminalSettingsCreateResult CreateWithParent(TerminalSettingsCreateResult parent); static TerminalSettingsCreateResult CreateWithParent(TerminalSettingsCreateResult parent);