diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index a5011bb980c..4a3a9cf775e 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -2008,6 +2008,24 @@ } } }, + "PaneTheme": { + "additionalProperties": false, + "description": "A set of properties for customizing the appearance of the panes", + "properties": { + "activeBorderColor": { + "description": "The color of the pane border when the pane is active", + "$ref": "#/$defs/ThemeColor" + }, + "inactiveBorderColor": { + "description": "The color of the pane border when the pane is inactive", + "$ref": "#/$defs/ThemeColor" + }, + "broadcastBorderColor": { + "description": "The color of the pane border when broadcasted", + "$ref": "#/$defs/ThemeColor" + } + } + }, "WindowTheme": { "additionalProperties": false, "description": "A set of properties for customizing the appearance of the window itself", @@ -2064,6 +2082,9 @@ }, "window": { "$ref": "#/$defs/WindowTheme" + }, + "pane": { + "$ref": "#/$defs/PaneTheme" } } }, diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 1de587c26fc..c5331f7a965 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -4604,11 +4604,21 @@ namespace winrt::TerminalApp::implementation } const auto theme = _settings.GlobalSettings().CurrentTheme(); - auto requestedTheme{ theme.RequestedTheme() }; - + const auto requestedTheme{ theme.RequestedTheme() }; + Media::Brush terminalBrush{ nullptr }; + if (const auto tab{ _GetFocusedTabImpl() }) { - _updatePaneResources(requestedTheme); + if (const auto& pane{ tab->GetActivePane() }) + { + if (const auto& lastContent{ pane->GetLastFocusedContent() }) + { + terminalBrush = lastContent.BackgroundBrush(); + } + } + } + { + _updatePaneResources(requestedTheme, theme.Pane(), terminalBrush); for (const auto& tab : _tabs) { if (auto terminalTab{ _GetTerminalTabImpl(tab) }) @@ -4630,18 +4640,6 @@ namespace winrt::TerminalApp::implementation til::color bgColor = backgroundSolidBrush.Color(); - Media::Brush terminalBrush{ nullptr }; - if (const auto tab{ _GetFocusedTabImpl() }) - { - if (const auto& pane{ tab->GetActivePane() }) - { - if (const auto& lastContent{ pane->GetLastFocusedContent() }) - { - terminalBrush = lastContent.BackgroundBrush(); - } - } - } - if (_settings.GlobalSettings().UseAcrylicInTabRow()) { const auto acrylicBrush = Media::AcrylicBrush(); @@ -4711,6 +4709,56 @@ namespace winrt::TerminalApp::implementation } } + Color TerminalPage::_colorFromKey(const ResourceDictionary& resourceDictionary, const ElementTheme& requestedTheme, const IInspectable& colorKey) + { + const auto defaultColor = Colors::Black(); + if (!resourceDictionary.HasKey(colorKey)) + { + return defaultColor; + } + return winrt::unbox_value_or( + ThemeLookup(resourceDictionary, requestedTheme, colorKey), + defaultColor); + } + + Color TerminalPage::_parseThemeColorToColor( + const ThemeColor& colorToCopy, + const ResourceDictionary& resourceDictionary, + const ElementTheme& requestedTheme, + const IInspectable& accentKey, + const Media::Brush& backgroundBrush) + { + switch (colorToCopy.ColorType()) + { + case ThemeColorType::Accent: + { + return _colorFromKey(resourceDictionary, requestedTheme, accentKey); + } + case ThemeColorType::Color: + const auto rawColor = colorToCopy.Color(); + return Color{ + rawColor.A, + rawColor.R, + rawColor.G, + rawColor.B + }; + case ThemeColorType::TerminalBackground: + { + const auto themeBrush{ colorToCopy.Evaluate(resourceDictionary, backgroundBrush, false) }; + auto terminalBg = ThemeColor::ColorFromBrush(themeBrush); + return Color{ + terminalBg.A, + terminalBg.R, + terminalBg.G, + terminalBg.B + }; + } + default: + assert(false && "unknown type for color type in theme color"); // should never be reached + return winrt::Windows::UI::Color{}; + } + } + // Function Description: // - Attempts to load some XAML resources that Panes will need. This includes: // * The Color they'll use for active Panes's borders - SystemAccentColor @@ -4718,60 +4766,32 @@ namespace winrt::TerminalApp::implementation // color of the titlebar) // Arguments: // - requestedTheme: this should be the currently active Theme for the app + // - activeBorderColor: the pane's border color for the application when it is active + // - inactiveBorderColor: the pane's border color for the application when it is inactive + // - broadcastBorderColor: the pane's border color for the application when it is broadcast // Return Value: // - - void TerminalPage::_updatePaneResources(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme) + void TerminalPage::_updatePaneResources(const ElementTheme& requestedTheme, const PaneTheme& paneTheme, const Media::Brush& backgroundBrush) { + const auto paneActiveBorderColor = paneTheme ? paneTheme.ActiveBorderColor() : nullptr; + const auto paneInactiveBorderColor = paneTheme ? paneTheme.InactiveBorderColor() : nullptr; + const auto broadcastBorderColor = paneTheme ? paneTheme.BroadcastBorderColor() : nullptr; const auto res = Application::Current().Resources(); - const auto accentColorKey = winrt::box_value(L"SystemAccentColor"); - if (res.HasKey(accentColorKey)) - { - const auto colorFromResources = ThemeLookup(res, requestedTheme, accentColorKey); - // If SystemAccentColor is _not_ a Color for some reason, use - // Transparent as the color, so we don't do this process again on - // the next pane (by leaving s_focusedBorderBrush nullptr) - auto actualColor = winrt::unbox_value_or(colorFromResources, Colors::Black()); - _paneResources.focusedBorderBrush = SolidColorBrush(actualColor); - } - else - { - // DON'T use Transparent here - if it's "Transparent", then it won't - // be able to hittest for clicks, and then clicking on the border - // will eat focus. - _paneResources.focusedBorderBrush = SolidColorBrush{ Colors::Black() }; - } - - const auto unfocusedBorderBrushKey = winrt::box_value(L"UnfocusedBorderBrush"); - if (res.HasKey(unfocusedBorderBrushKey)) - { - // MAKE SURE TO USE ThemeLookup, so that we get the correct resource for - // the requestedTheme, not just the value from the resources (which - // might not respect the settings' requested theme) - auto obj = ThemeLookup(res, requestedTheme, unfocusedBorderBrushKey); - _paneResources.unfocusedBorderBrush = obj.try_as(); - } - else - { - // DON'T use Transparent here - if it's "Transparent", then it won't - // be able to hittest for clicks, and then clicking on the border - // will eat focus. - _paneResources.unfocusedBorderBrush = SolidColorBrush{ Colors::Black() }; - } - - const auto broadcastColorKey = winrt::box_value(L"BroadcastPaneBorderColor"); - if (res.HasKey(broadcastColorKey)) - { - // MAKE SURE TO USE ThemeLookup - auto obj = ThemeLookup(res, requestedTheme, broadcastColorKey); - _paneResources.broadcastBorderBrush = obj.try_as(); - } - else - { - // DON'T use Transparent here - if it's "Transparent", then it won't - // be able to hittest for clicks, and then clicking on the border - // will eat focus. - _paneResources.broadcastBorderBrush = SolidColorBrush{ Colors::Black() }; - } + const IInspectable accentKey = winrt::box_value(L"SystemAccentColor"); + const auto parseRelevantColorForKeyAndTheme = [this, res, requestedTheme, backgroundBrush, accentKey](const winrt::param::hstring& keyString, ThemeColor paneTheme) { + const IInspectable key = winrt::box_value(keyString); + return paneTheme ? _parseThemeColorToColor(paneTheme, res, requestedTheme, accentKey, backgroundBrush) : _colorFromKey(res, requestedTheme, key); + }; + const auto activeBrushColor = parseRelevantColorForKeyAndTheme(L"SystemAccentColor", paneActiveBorderColor); + const auto inactiveBrushColor = parseRelevantColorForKeyAndTheme(L"UnfocusedBorderBrush", paneInactiveBorderColor); + const auto broadcastBrushColor = parseRelevantColorForKeyAndTheme(L"BroadcastPaneBorderColor", broadcastBorderColor); + // For the following brushes: + // DON'T use Transparent here - if it's "Transparent", then it won't + // be able to hittest for clicks, and then clicking on the border + // will eat focus. + _paneResources.focusedBorderBrush = SolidColorBrush(activeBrushColor); + _paneResources.unfocusedBorderBrush = SolidColorBrush(inactiveBrushColor); + _paneResources.broadcastBorderBrush = SolidColorBrush(broadcastBrushColor); } void TerminalPage::WindowActivated(const bool activated) diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 4879f65fc6a..e43f43d2f4f 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -515,7 +515,9 @@ namespace winrt::TerminalApp::implementation void _updateThemeColors(); void _updateAllTabCloseButtons(); - void _updatePaneResources(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme); + winrt::Windows::UI::Color _colorFromKey(const winrt::Windows::UI::Xaml::ResourceDictionary& resourceDictionary, const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme, const winrt::Windows::Foundation::IInspectable& colorKey); + winrt::Windows::UI::Color _parseThemeColorToColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& colorToCopy, const winrt::Windows::UI::Xaml::ResourceDictionary& resourceDictionary, const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme, const winrt::Windows::Foundation::IInspectable& accentKey, const winrt::Windows::UI::Xaml::Media::Brush& backgroundBrush); + void _updatePaneResources(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme, const winrt::Microsoft::Terminal::Settings::Model::PaneTheme& paneTheme, const winrt::Windows::UI::Xaml::Media::Brush& backgroundBrush); safe_void_coroutine _ControlCompletionsChangedHandler(const winrt::Windows::Foundation::IInspectable sender, const winrt::Microsoft::Terminal::Control::CompletionsChangedEventArgs args); diff --git a/src/cascadia/TerminalSettingsModel/MTSMSettings.h b/src/cascadia/TerminalSettingsModel/MTSMSettings.h index 01bd5ce5c81..57505344368 100644 --- a/src/cascadia/TerminalSettingsModel/MTSMSettings.h +++ b/src/cascadia/TerminalSettingsModel/MTSMSettings.h @@ -147,7 +147,8 @@ Author(s): X(winrt::Microsoft::Terminal::Settings::Model::WindowTheme, Window, "window", nullptr) \ X(winrt::Microsoft::Terminal::Settings::Model::SettingsTheme, Settings, "settings", nullptr) \ X(winrt::Microsoft::Terminal::Settings::Model::TabRowTheme, TabRow, "tabRow", nullptr) \ - X(winrt::Microsoft::Terminal::Settings::Model::TabTheme, Tab, "tab", nullptr) + X(winrt::Microsoft::Terminal::Settings::Model::TabTheme, Tab, "tab", nullptr) \ + X(winrt::Microsoft::Terminal::Settings::Model::PaneTheme, Pane, "pane", nullptr) #define MTSM_THEME_WINDOW_SETTINGS(X) \ X(winrt::Windows::UI::Xaml::ElementTheme, RequestedTheme, "applicationTheme", winrt::Windows::UI::Xaml::ElementTheme::Default) \ @@ -163,6 +164,11 @@ Author(s): X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, Background, "background", nullptr) \ X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, UnfocusedBackground, "unfocusedBackground", nullptr) +#define MTSM_THEME_PANE_SETTINGS(X) \ + X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, ActiveBorderColor, "activeBorderColor", nullptr) \ + X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, InactiveBorderColor, "inactiveBorderColor", nullptr) \ + X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, BroadcastBorderColor, "broadcastBorderColor", nullptr) + #define MTSM_THEME_TAB_SETTINGS(X) \ X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, Background, "background", nullptr) \ X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, UnfocusedBackground, "unfocusedBackground", nullptr) \ diff --git a/src/cascadia/TerminalSettingsModel/Theme.cpp b/src/cascadia/TerminalSettingsModel/Theme.cpp index 3b79b5297d7..ebe9d5f1c28 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.cpp +++ b/src/cascadia/TerminalSettingsModel/Theme.cpp @@ -12,6 +12,7 @@ #include "SettingsTheme.g.h" #include "ThemeColor.g.cpp" #include "WindowTheme.g.cpp" +#include "PaneTheme.g.cpp" #include "TabRowTheme.g.cpp" #include "TabTheme.g.cpp" #include "ThemePair.g.cpp" @@ -60,6 +61,7 @@ THEME_OBJECT(WindowTheme, MTSM_THEME_WINDOW_SETTINGS); THEME_OBJECT(SettingsTheme, MTSM_THEME_SETTINGS_SETTINGS); THEME_OBJECT(TabRowTheme, MTSM_THEME_TABROW_SETTINGS); THEME_OBJECT(TabTheme, MTSM_THEME_TAB_SETTINGS); +THEME_OBJECT(PaneTheme, MTSM_THEME_PANE_SETTINGS); #undef THEME_SETTINGS_COPY #undef THEME_SETTINGS_TO_JSON @@ -224,6 +226,7 @@ THEME_OBJECT_CONVERTER(winrt::Microsoft::Terminal::Settings::Model, WindowTheme, THEME_OBJECT_CONVERTER(winrt::Microsoft::Terminal::Settings::Model, SettingsTheme, MTSM_THEME_SETTINGS_SETTINGS); THEME_OBJECT_CONVERTER(winrt::Microsoft::Terminal::Settings::Model, TabRowTheme, MTSM_THEME_TABROW_SETTINGS); THEME_OBJECT_CONVERTER(winrt::Microsoft::Terminal::Settings::Model, TabTheme, MTSM_THEME_TAB_SETTINGS); +THEME_OBJECT_CONVERTER(winrt::Microsoft::Terminal::Settings::Model, PaneTheme, MTSM_THEME_PANE_SETTINGS); #undef THEME_SETTINGS_FROM_JSON #undef THEME_SETTINGS_TO_JSON @@ -254,6 +257,10 @@ winrt::com_ptr Theme::Copy() const { theme->_Tab = *winrt::get_self(_Tab)->Copy(); } + if (_Pane) + { + theme->_Pane = *winrt::get_self(_Pane)->Copy(); + } if (_Settings) { theme->_Settings = *winrt::get_self(_Settings)->Copy(); @@ -334,6 +341,13 @@ void Theme::LogSettingChanges(std::set& changes, const std::string_ const auto outerJsonKey = outerTabJsonKey; MTSM_THEME_TAB_SETTINGS(LOG_IF_SET) } + + if (isPaneSet) + { + const auto obj = _Pane; + const auto outerJsonKey = outerPaneJsonKey; + MTSM_THEME_PANE_SETTINGS(LOG_IF_SET); + } #undef LOG_IF_SET #undef GENERATE_SET_CHECK_AND_JSON_KEYS #pragma warning(pop) diff --git a/src/cascadia/TerminalSettingsModel/Theme.h b/src/cascadia/TerminalSettingsModel/Theme.h index e0892733ae8..16b6d0d14b8 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.h +++ b/src/cascadia/TerminalSettingsModel/Theme.h @@ -23,6 +23,7 @@ Author(s): #include "WindowTheme.g.h" #include "TabRowTheme.g.h" #include "TabTheme.g.h" +#include "PaneTheme.g.h" #include "ThemePair.g.h" #include "Theme.g.h" @@ -85,6 +86,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation THEME_OBJECT(SettingsTheme, MTSM_THEME_SETTINGS_SETTINGS); THEME_OBJECT(TabRowTheme, MTSM_THEME_TABROW_SETTINGS); THEME_OBJECT(TabTheme, MTSM_THEME_TAB_SETTINGS); + THEME_OBJECT(PaneTheme, MTSM_THEME_PANE_SETTINGS); struct Theme : ThemeT { diff --git a/src/cascadia/TerminalSettingsModel/Theme.idl b/src/cascadia/TerminalSettingsModel/Theme.idl index 9cf0806f25d..a221f4ee46d 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.idl +++ b/src/cascadia/TerminalSettingsModel/Theme.idl @@ -71,6 +71,12 @@ namespace Microsoft.Terminal.Settings.Model ThemeColor UnfocusedBackground { get; }; } + runtimeclass PaneTheme { + ThemeColor ActiveBorderColor { get; }; + ThemeColor InactiveBorderColor { get; }; + ThemeColor BroadcastBorderColor { get; }; + } + runtimeclass TabTheme { ThemeColor Background { get; }; ThemeColor UnfocusedBackground { get; }; @@ -93,6 +99,9 @@ namespace Microsoft.Terminal.Settings.Model // tabRow.* Namespace TabRowTheme TabRow { get; }; + // pane.* Namespace + PaneTheme Pane { get; }; + // tab.* Namespace TabTheme Tab { get; };