PRE-MERGE #18953 Setting to set pane highlight active, inactive and broadcast color

This commit is contained in:
Carlos Zamora 2025-06-10 10:30:17 -07:00
commit 533e48dad6
7 changed files with 132 additions and 36 deletions

View File

@ -2000,6 +2000,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",
@ -2056,6 +2074,9 @@
},
"window": {
"$ref": "#/$defs/WindowTheme"
},
"pane": {
"$ref": "#/$defs/PaneTheme"
}
}
},

View File

@ -4695,10 +4695,13 @@ namespace winrt::TerminalApp::implementation
}
const auto theme = _settings.GlobalSettings().CurrentTheme();
auto requestedTheme{ theme.RequestedTheme() };
const auto paneActiveBorderColor = theme.Pane() ? theme.Pane().ActiveBorderColor() : nullptr;
const auto paneInactiveBorderColor = theme.Pane() ? theme.Pane().InactiveBorderColor() : nullptr;
const auto broadcastBorderColor = theme.Pane() ? theme.Pane().BroadcastBorderColor() : nullptr;
const auto requestedTheme{ theme.RequestedTheme() };
{
_updatePaneResources(requestedTheme);
_updatePaneResources(requestedTheme, paneActiveBorderColor, paneInactiveBorderColor, broadcastBorderColor);
for (const auto& tab : _tabs)
{
@ -4802,6 +4805,49 @@ namespace winrt::TerminalApp::implementation
}
}
Color TerminalPage::_colorFromKey(const ResourceDictionary& resourceDictionary, const ElementTheme& requestedTheme, const IInspectable& colorKey)
{
const auto colorFromResources = ThemeLookup(resourceDictionary, requestedTheme, colorKey);
// 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)
return winrt::unbox_value_or<Color>(colorFromResources, Colors::Black());
}
Color TerminalPage::_parseThemeColorToColor(
const ThemeColor& colorToCopy,
const ResourceDictionary& resourceDictionary,
const ElementTheme& requestedTheme,
const IInspectable& colorKey
)
{
switch (colorToCopy.ColorType())
{
case ThemeColorType::Accent:
return _colorFromKey(resourceDictionary, requestedTheme, colorKey);
case ThemeColorType::Color:
const auto rawColor = colorToCopy.Color();
return Color{
rawColor.A,
rawColor.R,
rawColor.G,
rawColor.B
};
case ThemeColorType::TerminalBackground:
const auto terminalBg = ThemeColor::FromTerminalBackground().Color();
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
@ -4809,60 +4855,56 @@ 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:
// - <none>
void TerminalPage::_updatePaneResources(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme)
void TerminalPage::_updatePaneResources(const ElementTheme& requestedTheme, const ThemeColor& activeBorderColor, const ThemeColor& inactiveBorderColor, const ThemeColor& broadcastBorderColor)
{
const auto res = Application::Current().Resources();
const auto accentColorKey = winrt::box_value(L"SystemAccentColor");
auto activeBrushColor = Colors::Black(), inactiveBrushColor = Colors::Black(), broadcastBrushColor = Colors::Black();
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<Color>(colorFromResources, Colors::Black());
_paneResources.focusedBorderBrush = SolidColorBrush(actualColor);
activeBrushColor = _colorFromKey(res, requestedTheme, accentColorKey);
}
else
// Overwrites the accent above (or the black default color if there was no accent color)
if (activeBorderColor)
{
// 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() };
activeBrushColor = _parseThemeColorToColor(activeBorderColor, res, requestedTheme, accentColorKey);
}
// 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);
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<winrt::Windows::UI::Xaml::Media::SolidColorBrush>();
inactiveBrushColor = _colorFromKey(res, requestedTheme, unfocusedBorderBrushKey);
}
else
// Overwrites the above (or the black default color if there was no unfocusedBorderBrushKey)
if (inactiveBorderColor)
{
// 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() };
inactiveBrushColor = _parseThemeColorToColor(inactiveBorderColor, res, requestedTheme, unfocusedBorderBrushKey);
}
// 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(inactiveBrushColor);
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<winrt::Windows::UI::Xaml::Media::SolidColorBrush>();
_colorFromKey(res, requestedTheme, broadcastColorKey);
}
else
if (broadcastBorderColor)
{
// 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() };
broadcastBrushColor = _parseThemeColorToColor(broadcastBorderColor, res, requestedTheme, broadcastColorKey);
}
// 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(broadcastBrushColor);
}
void TerminalPage::WindowActivated(const bool activated)

View File

@ -521,7 +521,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& colorKey);
void _updatePaneResources(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme, const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& activeBorderColor, const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& inactiveBorderColor, const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& broadcastBorderColor);
safe_void_coroutine _ControlCompletionsChangedHandler(const winrt::Windows::Foundation::IInspectable sender, const winrt::Microsoft::Terminal::Control::CompletionsChangedEventArgs args);

View File

@ -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) \

View File

@ -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> Theme::Copy() const
{
theme->_Tab = *winrt::get_self<implementation::TabTheme>(_Tab)->Copy();
}
if (_Pane)
{
theme->_Pane = *winrt::get_self<implementation::PaneTheme>(_Pane)->Copy();
}
if (_Settings)
{
theme->_Settings = *winrt::get_self<implementation::SettingsTheme>(_Settings)->Copy();
@ -334,6 +341,13 @@ void Theme::LogSettingChanges(std::set<std::string>& 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)

View File

@ -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<Theme>
{

View File

@ -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; };