Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions src/cascadia/TerminalSettingsAppAdapterLib/TerminalSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "winrt/Windows.UI.ViewManagement.h"
#include "../../types/inc/colorTable.hpp"

#include <random>

using namespace winrt::Microsoft::Terminal::Control;
using namespace winrt::Microsoft::Terminal::Settings;
using namespace Microsoft::Console::Utils;
Expand Down Expand Up @@ -211,16 +213,61 @@ namespace winrt::Microsoft::Terminal::Settings
winrt::Windows::UI::Xaml::ElementTheme::Light;
}

// GH#9422: The special "_random" token causes us to randomly select
// a color scheme from the set of available schemes each time a new
// tab or pane is created.
static constexpr std::wstring_view RandomSchemeToken{ L"_random" };

// Helper to pick a random scheme from the available schemes map.
const auto pickRandomScheme = [&]() -> Model::ColorScheme {
const auto size = schemes.Size();
if (size == 0)
{
return nullptr;
}
// Use a random_device for non-deterministic seeding so each
// tab gets a truly random color scheme.
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<uint32_t> dist(0, size - 1);
const auto index = dist(gen);

uint32_t i = 0;
for (const auto& [name, scheme] : schemes)
{
if (i == index)
{
return scheme;
}
++i;
}
return nullptr;
};

switch (requestedTheme)
{
case winrt::Windows::UI::Xaml::ElementTheme::Light:
if (const auto scheme = schemes.TryLookup(appearance.LightColorSchemeName()))
if (appearance.LightColorSchemeName() == RandomSchemeToken)
{
if (const auto scheme = pickRandomScheme())
{
ApplyColorScheme(scheme);
}
}
else if (const auto scheme = schemes.TryLookup(appearance.LightColorSchemeName()))
{
ApplyColorScheme(scheme);
}
break;
case winrt::Windows::UI::Xaml::ElementTheme::Dark:
if (const auto scheme = schemes.TryLookup(appearance.DarkColorSchemeName()))
if (appearance.DarkColorSchemeName() == RandomSchemeToken)
{
if (const auto scheme = pickRandomScheme())
{
ApplyColorScheme(scheme);
}
}
else if (const auto scheme = schemes.TryLookup(appearance.DarkColorSchemeName()))
{
ApplyColorScheme(scheme);
}
Expand Down
15 changes: 13 additions & 2 deletions src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ using namespace winrt::Microsoft::Terminal::Control;
using namespace winrt::Windows::Foundation::Collections;
using namespace Microsoft::Console;

// The special token used to indicate that a random color scheme should be
// selected each time a new tab or pane is created. GH#9422
static constexpr std::wstring_view RandomSchemeToken{ L"_random" };

// Creating a child of a profile requires us to copy certain
// required attributes. This method handles those attributes.
//
Expand Down Expand Up @@ -466,13 +470,20 @@ void CascadiaSettings::_validateAllSchemesExist()
{
for (const auto& appearance : std::array{ profile.DefaultAppearance(), profile.UnfocusedAppearance() })
{
if (appearance && !colorSchemes.HasKey(appearance.DarkColorSchemeName()))
// GH#9422: Don't clear the color scheme name if it's set to
// "_random" - that's a special token that will be resolved
// at runtime to a randomly chosen scheme.
if (appearance &&
appearance.DarkColorSchemeName() != RandomSchemeToken &&
!colorSchemes.HasKey(appearance.DarkColorSchemeName()))
{
// Clear the user set dark color scheme. We'll just fallback instead.
appearance.ClearDarkColorSchemeName();
foundInvalidDarkScheme = true;
}
if (appearance && !colorSchemes.HasKey(appearance.LightColorSchemeName()))
if (appearance &&
appearance.LightColorSchemeName() != RandomSchemeToken &&
!colorSchemes.HasKey(appearance.LightColorSchemeName()))
{
// Clear the user set light color scheme. We'll just fallback instead.
appearance.ClearLightColorSchemeName();
Expand Down
Loading