mirror of
https://github.com/microsoft/terminal.git
synced 2026-02-04 05:35:20 +00:00
Merge branch 'dev/migrie/b/13554-new-default-theme' into dev/migrie/b/13684-inactiveTabBg
This commit is contained in:
@@ -149,10 +149,13 @@
|
||||
See GH #12356 for more history on the subject.
|
||||
-->
|
||||
<SolidColorBrush x:Key="TabViewBackground"
|
||||
Color="#0a0a0a" />
|
||||
Color="#2e2e2e" />
|
||||
|
||||
<StaticResource x:Key="UnfocusedBorderBrush"
|
||||
ResourceKey="ApplicationPageBackgroundThemeBrush" />
|
||||
|
||||
<SolidColorBrush x:Key="SettingsUiTabBrush"
|
||||
Color="#0c0c0c" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="Light">
|
||||
@@ -162,10 +165,13 @@
|
||||
GH #12398 has more history on this value, as well as GH #12400
|
||||
-->
|
||||
<SolidColorBrush x:Key="TabViewBackground"
|
||||
Color="#dadada" />
|
||||
Color="#e8e8e8" />
|
||||
|
||||
<StaticResource x:Key="UnfocusedBorderBrush"
|
||||
ResourceKey="ApplicationPageBackgroundThemeBrush" />
|
||||
|
||||
<SolidColorBrush x:Key="SettingsUiTabBrush"
|
||||
Color="#ffffff" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
@@ -183,6 +189,9 @@
|
||||
-->
|
||||
<StaticResource x:Key="TabViewBackground"
|
||||
ResourceKey="SystemColorButtonFaceColorBrush" />
|
||||
|
||||
<StaticResource x:Key="SettingsUiTabBrush"
|
||||
ResourceKey="SystemControlBackgroundBaseLowBrush" />
|
||||
</ResourceDictionary>
|
||||
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
@@ -36,6 +36,10 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
auto settingsUI{ Content().as<MainPage>() };
|
||||
settingsUI.UpdateSettings(settings);
|
||||
|
||||
// Stash away the current requested theme of the app. We'll need that in
|
||||
// _BackgroundBrush() to do a theme-aware resource lookup
|
||||
_requestedTheme = settings.GlobalSettings().CurrentTheme().RequestedTheme();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -105,4 +109,16 @@ namespace winrt::TerminalApp::implementation
|
||||
TabViewItem().IconSource(IconPathConverter::IconSourceMUX(glyph));
|
||||
}
|
||||
}
|
||||
|
||||
winrt::Windows::UI::Xaml::Media::Brush SettingsTab::_BackgroundBrush()
|
||||
{
|
||||
// Look up the color we should use for the settings tab item from our
|
||||
// resources. This should only be used for when "terminalBackground" is
|
||||
// requested.
|
||||
static const auto key = winrt::box_value(L"SettingsUiTabBrush");
|
||||
// You can't just do a Application::Current().Resources().TryLookup
|
||||
// lookup, cause the app theme never changes! Do the hacky version
|
||||
// instead.
|
||||
return ThemeLookup(Application::Current().Resources(), _requestedTheme, key).try_as<winrt::Windows::UI::Xaml::Media::Brush>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,11 @@ namespace winrt::TerminalApp::implementation
|
||||
std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs> BuildStartupActions() const override;
|
||||
|
||||
private:
|
||||
winrt::Windows::UI::Xaml::ElementTheme _requestedTheme;
|
||||
|
||||
void _MakeTabViewItem() override;
|
||||
winrt::fire_and_forget _CreateIcon();
|
||||
|
||||
virtual winrt::Windows::UI::Xaml::Media::Brush _BackgroundBrush() override;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <LibraryResources.h>
|
||||
#include "TabBase.h"
|
||||
#include "TabBase.g.cpp"
|
||||
#include "Utils.h"
|
||||
#include "ColorHelper.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
@@ -252,4 +254,285 @@ namespace winrt::TerminalApp::implementation
|
||||
});
|
||||
}
|
||||
|
||||
std::optional<winrt::Windows::UI::Color> TabBase::GetTabColor()
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void TabBase::ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused,
|
||||
const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused,
|
||||
const til::color& tabRowColor)
|
||||
{
|
||||
_themeColor = focused;
|
||||
_unfocusedThemeColor = unfocused;
|
||||
_tabRowColor = tabRowColor;
|
||||
_RecalculateAndApplyTabColor();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This function dispatches a function to the UI thread to recalculate
|
||||
// what this tab's current background color should be. If a color is set,
|
||||
// it will apply the given color to the tab's background. Otherwise, it
|
||||
// will clear the tab's background color.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TabBase::_RecalculateAndApplyTabColor()
|
||||
{
|
||||
auto weakThis{ get_weak() };
|
||||
|
||||
TabViewItem().Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [weakThis]() {
|
||||
auto ptrTab = weakThis.get();
|
||||
if (!ptrTab)
|
||||
return;
|
||||
|
||||
auto tab{ ptrTab };
|
||||
|
||||
// GetTabColor will return the color set by the color picker, or the
|
||||
// color specified in the profile. If neither of those were set,
|
||||
// then look to _themeColor to see if there's a value there.
|
||||
// Otherwise, clear our color, falling back to the TabView defaults.
|
||||
auto currentColor = tab->GetTabColor();
|
||||
if (currentColor.has_value())
|
||||
{
|
||||
tab->_ApplyTabColor(currentColor.value());
|
||||
}
|
||||
else if (tab->_themeColor != nullptr)
|
||||
{
|
||||
// Safely get the active control's brush.
|
||||
Media::Brush terminalBrush{ tab->_BackgroundBrush() };
|
||||
|
||||
if (const auto themeBrush{ tab->_themeColor.Evaluate(Application::Current().Resources(), terminalBrush, false) })
|
||||
{
|
||||
// ThemeColor.Evaluate will get us a Brush (because the
|
||||
// TermControl could have an acrylic BG, for example). Take
|
||||
// that brush, and get the color out of it. We don't really
|
||||
// want to have the tab items themselves be acrylic.
|
||||
tab->_ApplyTabColor(til::color{ ThemeColor::ColorFromBrush(themeBrush) });
|
||||
}
|
||||
else
|
||||
{
|
||||
tab->_ClearTabBackgroundColor();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tab->_ClearTabBackgroundColor();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Applies the given color to the background of this tab's TabViewItem.
|
||||
// - Sets the tab foreground color depending on the luminance of
|
||||
// the background color
|
||||
// - This method should only be called on the UI thread.
|
||||
// Arguments:
|
||||
// - color: the color the user picked for their tab
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TabBase::_ApplyTabColor(const winrt::Windows::UI::Color& color)
|
||||
{
|
||||
Media::SolidColorBrush selectedTabBrush{};
|
||||
Media::SolidColorBrush deselectedTabBrush{};
|
||||
Media::SolidColorBrush fontBrush{};
|
||||
Media::SolidColorBrush deselectedFontBrush{};
|
||||
Media::SolidColorBrush secondaryFontBrush{};
|
||||
Media::SolidColorBrush hoverTabBrush{};
|
||||
Media::SolidColorBrush subtleFillColorSecondaryBrush;
|
||||
Media::SolidColorBrush subtleFillColorTertiaryBrush;
|
||||
// calculate the luminance of the current color and select a font
|
||||
// color based on that
|
||||
// see https://www.w3.org/TR/WCAG20/#relativeluminancedef
|
||||
if (TerminalApp::ColorHelper::IsBrightColor(color))
|
||||
{
|
||||
fontBrush.Color(winrt::Windows::UI::Colors::Black());
|
||||
auto secondaryFontColor = winrt::Windows::UI::Colors::Black();
|
||||
// For alpha value see: https://github.com/microsoft/microsoft-ui-xaml/blob/7a33ad772d77d908aa6b316ec24e6d2eb3ebf571/dev/CommonStyles/Common_themeresources_any.xaml#L269
|
||||
secondaryFontColor.A = 0x9E;
|
||||
secondaryFontBrush.Color(secondaryFontColor);
|
||||
auto subtleFillColorSecondary = winrt::Windows::UI::Colors::Black();
|
||||
subtleFillColorSecondary.A = 0x09;
|
||||
subtleFillColorSecondaryBrush.Color(subtleFillColorSecondary);
|
||||
auto subtleFillColorTertiary = winrt::Windows::UI::Colors::Black();
|
||||
subtleFillColorTertiary.A = 0x06;
|
||||
subtleFillColorTertiaryBrush.Color(subtleFillColorTertiary);
|
||||
}
|
||||
else
|
||||
{
|
||||
fontBrush.Color(winrt::Windows::UI::Colors::White());
|
||||
auto secondaryFontColor = winrt::Windows::UI::Colors::White();
|
||||
// For alpha value see: https://github.com/microsoft/microsoft-ui-xaml/blob/7a33ad772d77d908aa6b316ec24e6d2eb3ebf571/dev/CommonStyles/Common_themeresources_any.xaml#L14
|
||||
secondaryFontColor.A = 0xC5;
|
||||
secondaryFontBrush.Color(secondaryFontColor);
|
||||
auto subtleFillColorSecondary = winrt::Windows::UI::Colors::White();
|
||||
subtleFillColorSecondary.A = 0x0F;
|
||||
subtleFillColorSecondaryBrush.Color(subtleFillColorSecondary);
|
||||
auto subtleFillColorTertiary = winrt::Windows::UI::Colors::White();
|
||||
subtleFillColorTertiary.A = 0x0A;
|
||||
subtleFillColorTertiaryBrush.Color(subtleFillColorTertiary);
|
||||
}
|
||||
|
||||
selectedTabBrush.Color(color);
|
||||
|
||||
// Start with the current tab color, set to Opacity=.3
|
||||
til::color deselectedTabColor{ color };
|
||||
deselectedTabColor = deselectedTabColor.with_alpha(77); // 255 * .3 = 77
|
||||
// If we have a unfocused color in the theme:
|
||||
if (_unfocusedThemeColor != nullptr)
|
||||
{
|
||||
// Safely get the active control's brush.
|
||||
Media::Brush terminalBrush{ _BackgroundBrush() };
|
||||
|
||||
// Get the color of the brush.
|
||||
if (const auto themeBrush{ _unfocusedThemeColor.Evaluate(Application::Current().Resources(), terminalBrush, false) })
|
||||
{
|
||||
// We did figure out the brush. Get the color out of it. If it
|
||||
// was "accent" or "terminalBackground", then we're gonna set
|
||||
// the alpha to .3 manually here.
|
||||
// (ThemeColor::UnfocusedTabOpacity will do this for us). If the
|
||||
// user sets both unfocused and focused tab.background to
|
||||
// terminalBackground, this will allow for some differentiation
|
||||
// (and is generally just sensible).
|
||||
deselectedTabColor = til::color{ ThemeColor::ColorFromBrush(themeBrush) }.with_alpha(_unfocusedThemeColor.UnfocusedTabOpacity());
|
||||
}
|
||||
}
|
||||
|
||||
// currently if a tab has a custom color, a deselected state is
|
||||
// signified by using the same color with a bit of transparency
|
||||
deselectedTabBrush.Color(deselectedTabColor.with_alpha(255));
|
||||
deselectedTabBrush.Opacity(deselectedTabColor.a / 255.f);
|
||||
|
||||
hoverTabBrush.Color(color);
|
||||
hoverTabBrush.Opacity(0.6);
|
||||
|
||||
// Account for the color of the tab row when setting the color of text
|
||||
// on inactive tabs. Consider:
|
||||
// * black active tabs
|
||||
// * on a white tab row
|
||||
// * with a transparent inactive tab color
|
||||
//
|
||||
// We don't want that to result in white text on a white tab row for
|
||||
// inactive tabs.
|
||||
auto deselectedActualColor = deselectedTabColor.blend_with(_tabRowColor);
|
||||
if (TerminalApp::ColorHelper::IsBrightColor(deselectedActualColor))
|
||||
{
|
||||
deselectedFontBrush.Color(winrt::Windows::UI::Colors::Black());
|
||||
}
|
||||
else
|
||||
{
|
||||
deselectedFontBrush.Color(winrt::Windows::UI::Colors::White());
|
||||
}
|
||||
|
||||
// Prior to MUX 2.7, we set TabViewItemHeaderBackground, but now we can
|
||||
// use TabViewItem().Background() for that. HOWEVER,
|
||||
// TabViewItem().Background() only sets the color of the tab background
|
||||
// when the TabViewItem is unselected. So we still need to set the other
|
||||
// properties ourselves.
|
||||
//
|
||||
// In GH#11294 we thought we'd still need to set
|
||||
// TabViewItemHeaderBackground manually, but GH#11382 discovered that
|
||||
// Background() was actually okay after all.
|
||||
TabViewItem().Background(deselectedTabBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundSelected"), selectedTabBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPointerOver"), hoverTabBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPressed"), selectedTabBrush);
|
||||
|
||||
// Similarly, TabViewItem().Foreground() sets the color for the text
|
||||
// when the TabViewItem isn't selected, but not when it is hovered,
|
||||
// pressed, dragged, or selected, so we'll need to just set them all
|
||||
// anyways.
|
||||
TabViewItem().Foreground(deselectedFontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForeground"), deselectedFontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundSelected"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundPointerOver"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundPressed"), fontBrush);
|
||||
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonForeground"), deselectedFontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonForegroundPressed"), secondaryFontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonForegroundPointerOver"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderPressedCloseButtonForeground"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderPointerOverCloseButtonForeground"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderSelectedCloseButtonForeground"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBackgroundPressed"), subtleFillColorTertiaryBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBackgroundPointerOver"), subtleFillColorSecondaryBrush);
|
||||
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewButtonForegroundActiveTab"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewButtonForegroundPressed"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewButtonForegroundPointerOver"), fontBrush);
|
||||
|
||||
_RefreshVisualState();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Clear out any color we've set for the TabViewItem.
|
||||
// - This method should only be called on the UI thread.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TabBase::_ClearTabBackgroundColor()
|
||||
{
|
||||
winrt::hstring keys[] = {
|
||||
L"TabViewItemHeaderBackground",
|
||||
L"TabViewItemHeaderBackgroundSelected",
|
||||
L"TabViewItemHeaderBackgroundPointerOver",
|
||||
L"TabViewItemHeaderBackgroundPressed",
|
||||
L"TabViewItemHeaderForeground",
|
||||
L"TabViewItemHeaderForegroundSelected",
|
||||
L"TabViewItemHeaderForegroundPointerOver",
|
||||
L"TabViewItemHeaderForegroundPressed",
|
||||
L"TabViewItemHeaderCloseButtonForeground",
|
||||
L"TabViewItemHeaderCloseButtonForegroundPressed",
|
||||
L"TabViewItemHeaderCloseButtonForegroundPointerOver",
|
||||
L"TabViewItemHeaderPressedCloseButtonForeground",
|
||||
L"TabViewItemHeaderPointerOverCloseButtonForeground",
|
||||
L"TabViewItemHeaderSelectedCloseButtonForeground",
|
||||
L"TabViewItemHeaderCloseButtonBackgroundPressed",
|
||||
L"TabViewItemHeaderCloseButtonBackgroundPointerOver",
|
||||
L"TabViewButtonForegroundActiveTab",
|
||||
L"TabViewButtonForegroundPressed",
|
||||
L"TabViewButtonForegroundPointerOver"
|
||||
};
|
||||
|
||||
// simply clear any of the colors in the tab's dict
|
||||
for (auto keyString : keys)
|
||||
{
|
||||
auto key = winrt::box_value(keyString);
|
||||
if (TabViewItem().Resources().HasKey(key))
|
||||
{
|
||||
TabViewItem().Resources().Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
// GH#11382 DON'T set the background to null. If you do that, then the
|
||||
// tab won't be hit testable at all. Transparent, however, is a totally
|
||||
// valid hit test target. That makes sense.
|
||||
TabViewItem().Background(WUX::Media::SolidColorBrush{ Windows::UI::Colors::Transparent() });
|
||||
|
||||
_RefreshVisualState();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// Toggles the visual state of the tab view item,
|
||||
// so that changes to the tab color are reflected immediately
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TabBase::_RefreshVisualState()
|
||||
{
|
||||
if (TabViewItem().IsSelected())
|
||||
{
|
||||
VisualStateManager::GoToState(TabViewItem(), L"Normal", true);
|
||||
VisualStateManager::GoToState(TabViewItem(), L"Selected", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
VisualStateManager::GoToState(TabViewItem(), L"Selected", true);
|
||||
VisualStateManager::GoToState(TabViewItem(), L"Normal", true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,11 @@ namespace winrt::TerminalApp::implementation
|
||||
void SetActionMap(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap);
|
||||
virtual std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs> BuildStartupActions() const = 0;
|
||||
|
||||
virtual std::optional<winrt::Windows::UI::Color> GetTabColor();
|
||||
void ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused,
|
||||
const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused,
|
||||
const til::color& tabRowColor);
|
||||
|
||||
WINRT_CALLBACK(RequestFocusActiveControl, winrt::delegate<void()>);
|
||||
|
||||
WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>);
|
||||
@@ -51,6 +56,10 @@ namespace winrt::TerminalApp::implementation
|
||||
Microsoft::Terminal::Settings::Model::IActionMapView _actionMap{ nullptr };
|
||||
winrt::hstring _keyChord{};
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::Model::ThemeColor _themeColor{ nullptr };
|
||||
winrt::Microsoft::Terminal::Settings::Model::ThemeColor _unfocusedThemeColor{ nullptr };
|
||||
til::color _tabRowColor;
|
||||
|
||||
virtual void _CreateContextMenu();
|
||||
virtual winrt::hstring _CreateToolTipTitle();
|
||||
|
||||
@@ -63,6 +72,12 @@ namespace winrt::TerminalApp::implementation
|
||||
winrt::fire_and_forget _UpdateSwitchToTabKeyChord();
|
||||
void _UpdateToolTip();
|
||||
|
||||
void _RecalculateAndApplyTabColor();
|
||||
void _ApplyTabColor(const winrt::Windows::UI::Color& color);
|
||||
void _ClearTabBackgroundColor();
|
||||
void _RefreshVisualState();
|
||||
virtual winrt::Windows::UI::Xaml::Media::Brush _BackgroundBrush() = 0;
|
||||
|
||||
friend class ::TerminalAppLocalTests::TabTests;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "DebugTapConnection.h"
|
||||
#include "SettingsTab.h"
|
||||
#include "TabRowControl.h"
|
||||
#include "Utils.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Microsoft::Terminal::Control;
|
||||
@@ -4102,80 +4103,11 @@ namespace winrt::TerminalApp::implementation
|
||||
const auto theme = _settings.GlobalSettings().CurrentTheme();
|
||||
auto requestedTheme{ theme.RequestedTheme() };
|
||||
|
||||
// First: Update the colors of our individual TabViewItems. This applies tab.background to the tabs via TerminalTab::ThemeColor
|
||||
{
|
||||
auto tabBackground = theme.Tab() ? theme.Tab().Background() : nullptr;
|
||||
auto tabUnfocusedBackground = theme.Tab() ? theme.Tab().UnfocusedBackground() : nullptr;
|
||||
for (const auto& tab : _tabs)
|
||||
{
|
||||
if (const auto& terminalTabImpl{ _GetTerminalTabImpl(tab) })
|
||||
{
|
||||
terminalTabImpl->ThemeColor(tabBackground, tabUnfocusedBackground);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto res = Application::Current().Resources();
|
||||
|
||||
// XAML Hacks:
|
||||
//
|
||||
// the App is always in the OS theme, so the
|
||||
// App::Current().Resources() lookup will always get the value for the
|
||||
// OS theme, not the requested theme.
|
||||
//
|
||||
// This helper allows us to instead lookup the value of a resource
|
||||
// specified by `key` for the given `requestedTheme`, from the
|
||||
// dictionaries in App.xaml. Make sure the value is actually there!
|
||||
// Otherwise this'll throw like any other Lookup for a resource that
|
||||
// isn't there.
|
||||
static const auto lookup = [](auto& res, auto& requestedTheme, auto& key) {
|
||||
// You want the Default version of the resource? Great, the App is
|
||||
// always in the OS theme. Just look it up and be done.
|
||||
if (requestedTheme == ElementTheme::Default)
|
||||
{
|
||||
return res.Lookup(key);
|
||||
}
|
||||
static const auto lightKey = winrt::box_value(L"Light");
|
||||
static const auto darkKey = winrt::box_value(L"Dark");
|
||||
// There isn't an ElementTheme::HighContrast.
|
||||
|
||||
auto requestedThemeKey = requestedTheme == ElementTheme::Dark ? darkKey : lightKey;
|
||||
for (const auto& dictionary : res.MergedDictionaries())
|
||||
{
|
||||
// Don't look in the MUX resources. They come first. A person
|
||||
// with more patience than me may find a way to look through our
|
||||
// dictionaries first, then the MUX ones, but that's not needed
|
||||
// currently
|
||||
if (dictionary.Source())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Look through the theme dictionaries we defined:
|
||||
for (const auto& [dictionaryKey, dict] : dictionary.ThemeDictionaries())
|
||||
{
|
||||
// Does the key for this dict match the theme we're looking for?
|
||||
if (winrt::unbox_value<winrt::hstring>(dictionaryKey) !=
|
||||
winrt::unbox_value<winrt::hstring>(requestedThemeKey))
|
||||
{
|
||||
// No? skip it.
|
||||
continue;
|
||||
}
|
||||
// Look for the requested resource in this dict.
|
||||
const auto themeDictionary = dict.as<winrt::Windows::UI::Xaml::ResourceDictionary>();
|
||||
if (themeDictionary.HasKey(key))
|
||||
{
|
||||
return themeDictionary.Lookup(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We didn't find it in the requested dict, fall back to the default dictionary.
|
||||
return res.Lookup(key);
|
||||
};
|
||||
|
||||
// Use our helper to lookup the theme-aware version of the resource.
|
||||
const auto tabViewBackgroundKey = winrt::box_value(L"TabViewBackground");
|
||||
const auto backgroundSolidBrush = lookup(res, requestedTheme, tabViewBackgroundKey).as<Media::SolidColorBrush>();
|
||||
const auto backgroundSolidBrush = ThemeLookup(res, requestedTheme, tabViewBackgroundKey).as<Media::SolidColorBrush>();
|
||||
|
||||
til::color bgColor = backgroundSolidBrush.Color();
|
||||
|
||||
@@ -4200,6 +4132,8 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
else if (auto settingsTab = _GetFocusedTab().try_as<TerminalApp::SettingsTab>())
|
||||
{
|
||||
// static Media::SolidColorBrush campbellBg{ winrt::Windows::UI::Color{ 0x0c, 0x0c, 0x0c } };
|
||||
// return campbellBg; //
|
||||
return settingsTab.Content().try_as<Settings::Editor::MainPage>().BackgroundBrush();
|
||||
}
|
||||
return nullptr;
|
||||
@@ -4220,6 +4154,21 @@ namespace winrt::TerminalApp::implementation
|
||||
_tabRow.Background(TitlebarBrush());
|
||||
}
|
||||
|
||||
// Second: Update the colors of our individual TabViewItems. This
|
||||
// applies tab.background to the tabs via TerminalTab::ThemeColor.
|
||||
//
|
||||
// Do this second, so that we already know the bgColor of the titlebar.
|
||||
{
|
||||
auto tabBackground = theme.Tab() ? theme.Tab().Background() : nullptr;
|
||||
auto tabUnfocusedBackground = theme.Tab() ? theme.Tab().UnfocusedBackground() : nullptr;
|
||||
for (const auto& tab : _tabs)
|
||||
{
|
||||
winrt::com_ptr<TabBase> tabImpl;
|
||||
tabImpl.copy_from(winrt::get_self<TabBase>(tab));
|
||||
tabImpl->ThemeColor(tabBackground, tabUnfocusedBackground, bgColor);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the new tab button to have better contrast with the new color.
|
||||
// In theory, it would be convenient to also change these for the
|
||||
// inactive tabs as well, but we're leaving that as a follow up.
|
||||
|
||||
@@ -1394,195 +1394,6 @@ namespace winrt::TerminalApp::implementation
|
||||
_RecalculateAndApplyTabColor();
|
||||
}
|
||||
|
||||
void TerminalTab::ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused, const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused)
|
||||
{
|
||||
_themeColor = focused;
|
||||
_unfocusedThemeColor = unfocused;
|
||||
_RecalculateAndApplyTabColor();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This function dispatches a function to the UI thread to recalculate
|
||||
// what this tab's current background color should be. If a color is set,
|
||||
// it will apply the given color to the tab's background. Otherwise, it
|
||||
// will clear the tab's background color.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalTab::_RecalculateAndApplyTabColor()
|
||||
{
|
||||
auto weakThis{ get_weak() };
|
||||
|
||||
TabViewItem().Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [weakThis]() {
|
||||
auto ptrTab = weakThis.get();
|
||||
if (!ptrTab)
|
||||
return;
|
||||
|
||||
auto tab{ ptrTab };
|
||||
|
||||
// GetTabColor will return the color set by the color picker, or the
|
||||
// color specified in the profile. If neither of those were set,
|
||||
// then look to _themeColor to see if there's a value there.
|
||||
// Otherwise, clear our color, falling back to the TabView defaults.
|
||||
auto currentColor = tab->GetTabColor();
|
||||
if (currentColor.has_value())
|
||||
{
|
||||
tab->_ApplyTabColor(currentColor.value());
|
||||
}
|
||||
else if (tab->_themeColor != nullptr)
|
||||
{
|
||||
// Safely get the active control's brush.
|
||||
Media::Brush terminalBrush{ nullptr };
|
||||
if (const auto& c{ tab->GetActiveTerminalControl() })
|
||||
{
|
||||
terminalBrush = c.BackgroundBrush();
|
||||
}
|
||||
|
||||
if (const auto themeBrush{ tab->_themeColor.Evaluate(Application::Current().Resources(), terminalBrush, false) })
|
||||
{
|
||||
// ThemeColor.Evaluate will get us a Brush (because the
|
||||
// TermControl could have an acrylic BG, for example). Take
|
||||
// that brush, and get the color out of it. We don't really
|
||||
// want to have the tab items themselves be acrylic.
|
||||
tab->_ApplyTabColor(til::color{ ThemeColor::ColorFromBrush(themeBrush) });
|
||||
}
|
||||
else
|
||||
{
|
||||
tab->_ClearTabBackgroundColor();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tab->_ClearTabBackgroundColor();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Applies the given color to the background of this tab's TabViewItem.
|
||||
// - Sets the tab foreground color depending on the luminance of
|
||||
// the background color
|
||||
// - This method should only be called on the UI thread.
|
||||
// Arguments:
|
||||
// - color: the color the user picked for their tab
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalTab::_ApplyTabColor(const winrt::Windows::UI::Color& color)
|
||||
{
|
||||
Media::SolidColorBrush selectedTabBrush{};
|
||||
Media::SolidColorBrush deselectedTabBrush{};
|
||||
Media::SolidColorBrush fontBrush{};
|
||||
Media::SolidColorBrush secondaryFontBrush{};
|
||||
Media::SolidColorBrush hoverTabBrush{};
|
||||
Media::SolidColorBrush subtleFillColorSecondaryBrush;
|
||||
Media::SolidColorBrush subtleFillColorTertiaryBrush;
|
||||
// calculate the luminance of the current color and select a font
|
||||
// color based on that
|
||||
// see https://www.w3.org/TR/WCAG20/#relativeluminancedef
|
||||
if (TerminalApp::ColorHelper::IsBrightColor(color))
|
||||
{
|
||||
fontBrush.Color(winrt::Windows::UI::Colors::Black());
|
||||
auto secondaryFontColor = winrt::Windows::UI::Colors::Black();
|
||||
// For alpha value see: https://github.com/microsoft/microsoft-ui-xaml/blob/7a33ad772d77d908aa6b316ec24e6d2eb3ebf571/dev/CommonStyles/Common_themeresources_any.xaml#L269
|
||||
secondaryFontColor.A = 0x9E;
|
||||
secondaryFontBrush.Color(secondaryFontColor);
|
||||
auto subtleFillColorSecondary = winrt::Windows::UI::Colors::Black();
|
||||
subtleFillColorSecondary.A = 0x09;
|
||||
subtleFillColorSecondaryBrush.Color(subtleFillColorSecondary);
|
||||
auto subtleFillColorTertiary = winrt::Windows::UI::Colors::Black();
|
||||
subtleFillColorTertiary.A = 0x06;
|
||||
subtleFillColorTertiaryBrush.Color(subtleFillColorTertiary);
|
||||
}
|
||||
else
|
||||
{
|
||||
fontBrush.Color(winrt::Windows::UI::Colors::White());
|
||||
auto secondaryFontColor = winrt::Windows::UI::Colors::White();
|
||||
// For alpha value see: https://github.com/microsoft/microsoft-ui-xaml/blob/7a33ad772d77d908aa6b316ec24e6d2eb3ebf571/dev/CommonStyles/Common_themeresources_any.xaml#L14
|
||||
secondaryFontColor.A = 0xC5;
|
||||
secondaryFontBrush.Color(secondaryFontColor);
|
||||
auto subtleFillColorSecondary = winrt::Windows::UI::Colors::White();
|
||||
subtleFillColorSecondary.A = 0x0F;
|
||||
subtleFillColorSecondaryBrush.Color(subtleFillColorSecondary);
|
||||
auto subtleFillColorTertiary = winrt::Windows::UI::Colors::White();
|
||||
subtleFillColorTertiary.A = 0x0A;
|
||||
subtleFillColorTertiaryBrush.Color(subtleFillColorTertiary);
|
||||
}
|
||||
|
||||
selectedTabBrush.Color(color);
|
||||
|
||||
// Start with the current tab color, set to Opacity=.3
|
||||
til::color deselectedTabColor{ color };
|
||||
deselectedTabColor = deselectedTabColor.with_alpha(77); // 255 * .3 = 77
|
||||
// If we have a unfocused color in the theme:
|
||||
if (_unfocusedThemeColor != nullptr)
|
||||
{
|
||||
// Safely get the active control's brush.
|
||||
Media::Brush terminalBrush{ nullptr };
|
||||
if (const auto& c{ GetActiveTerminalControl() })
|
||||
{
|
||||
terminalBrush = c.BackgroundBrush();
|
||||
}
|
||||
// Get the color of the brush.
|
||||
if (const auto themeBrush{ _unfocusedThemeColor.Evaluate(Application::Current().Resources(), terminalBrush, false) })
|
||||
{
|
||||
// We did figure out the brush. Get the color out of it. If it
|
||||
// was "accent" or "terminalBackground", then we're gonna set
|
||||
// the alpha to .3 manually here.
|
||||
// (ThemeColor::UnfocusedTabOpacity will do this for us). If the
|
||||
// user sets both unfocused and focused tab.background to
|
||||
// terminalBackground, this will allow for some differentiation
|
||||
// (and is generally just sensible).
|
||||
deselectedTabColor = til::color{ ThemeColor::ColorFromBrush(themeBrush) }.with_alpha(_unfocusedThemeColor.UnfocusedTabOpacity());
|
||||
}
|
||||
}
|
||||
// currently if a tab has a custom color, a deselected state is
|
||||
// signified by using the same color with a bit of transparency
|
||||
deselectedTabBrush.Color(deselectedTabColor.with_alpha(255));
|
||||
deselectedTabBrush.Opacity(deselectedTabColor.a / 255.f);
|
||||
|
||||
hoverTabBrush.Color(color);
|
||||
hoverTabBrush.Opacity(0.6);
|
||||
|
||||
// Prior to MUX 2.7, we set TabViewItemHeaderBackground, but now we can
|
||||
// use TabViewItem().Background() for that. HOWEVER,
|
||||
// TabViewItem().Background() only sets the color of the tab background
|
||||
// when the TabViewItem is unselected. So we still need to set the other
|
||||
// properties ourselves.
|
||||
//
|
||||
// In GH#11294 we thought we'd still need to set
|
||||
// TabViewItemHeaderBackground manually, but GH#11382 discovered that
|
||||
// Background() was actually okay after all.
|
||||
TabViewItem().Background(deselectedTabBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundSelected"), selectedTabBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPointerOver"), hoverTabBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPressed"), selectedTabBrush);
|
||||
|
||||
// TabViewItem().Foreground() unfortunately does not work for us. It
|
||||
// sets the color for the text when the TabViewItem isn't selected, but
|
||||
// not when it is hovered, pressed, dragged, or selected, so we'll need
|
||||
// to just set them all anyways.
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForeground"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundSelected"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundPointerOver"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundPressed"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonForeground"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonForegroundPressed"), secondaryFontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonForegroundPointerOver"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderPressedCloseButtonForeground"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderPointerOverCloseButtonForeground"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderSelectedCloseButtonForeground"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBackgroundPressed"), subtleFillColorTertiaryBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBackgroundPointerOver"), subtleFillColorSecondaryBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewButtonForegroundActiveTab"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewButtonForegroundPressed"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewButtonForegroundPointerOver"), fontBrush);
|
||||
|
||||
_RefreshVisualState();
|
||||
|
||||
_ColorSelectedHandlers(color);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Clear the custom runtime color of the tab, if any color is set. This
|
||||
// will re-apply whatever the tab's base color should be (either the color
|
||||
@@ -1597,54 +1408,14 @@ namespace winrt::TerminalApp::implementation
|
||||
_RecalculateAndApplyTabColor();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Clear out any color we've set for the TabViewItem.
|
||||
// - This method should only be called on the UI thread.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalTab::_ClearTabBackgroundColor()
|
||||
winrt::Windows::UI::Xaml::Media::Brush TerminalTab::_BackgroundBrush()
|
||||
{
|
||||
winrt::hstring keys[] = {
|
||||
L"TabViewItemHeaderBackground",
|
||||
L"TabViewItemHeaderBackgroundSelected",
|
||||
L"TabViewItemHeaderBackgroundPointerOver",
|
||||
L"TabViewItemHeaderBackgroundPressed",
|
||||
L"TabViewItemHeaderForeground",
|
||||
L"TabViewItemHeaderForegroundSelected",
|
||||
L"TabViewItemHeaderForegroundPointerOver",
|
||||
L"TabViewItemHeaderForegroundPressed",
|
||||
L"TabViewItemHeaderCloseButtonForeground",
|
||||
L"TabViewItemHeaderCloseButtonForegroundPressed",
|
||||
L"TabViewItemHeaderCloseButtonForegroundPointerOver",
|
||||
L"TabViewItemHeaderPressedCloseButtonForeground",
|
||||
L"TabViewItemHeaderPointerOverCloseButtonForeground",
|
||||
L"TabViewItemHeaderSelectedCloseButtonForeground",
|
||||
L"TabViewItemHeaderCloseButtonBackgroundPressed",
|
||||
L"TabViewItemHeaderCloseButtonBackgroundPointerOver",
|
||||
L"TabViewButtonForegroundActiveTab",
|
||||
L"TabViewButtonForegroundPressed",
|
||||
L"TabViewButtonForegroundPointerOver"
|
||||
};
|
||||
|
||||
// simply clear any of the colors in the tab's dict
|
||||
for (auto keyString : keys)
|
||||
Media::Brush terminalBrush{ nullptr };
|
||||
if (const auto& c{ GetActiveTerminalControl() })
|
||||
{
|
||||
auto key = winrt::box_value(keyString);
|
||||
if (TabViewItem().Resources().HasKey(key))
|
||||
{
|
||||
TabViewItem().Resources().Remove(key);
|
||||
}
|
||||
terminalBrush = c.BackgroundBrush();
|
||||
}
|
||||
|
||||
// GH#11382 DON'T set the background to null. If you do that, then the
|
||||
// tab won't be hit testable at all. Transparent, however, is a totally
|
||||
// valid hit test target. That makes sense.
|
||||
TabViewItem().Background(WUX::Media::SolidColorBrush{ Windows::UI::Colors::Transparent() });
|
||||
|
||||
_RefreshVisualState();
|
||||
_ColorClearedHandlers();
|
||||
return terminalBrush;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -1659,27 +1430,6 @@ namespace winrt::TerminalApp::implementation
|
||||
_ColorPickerRequestedHandlers();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// Toggles the visual state of the tab view item,
|
||||
// so that changes to the tab color are reflected immediately
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalTab::_RefreshVisualState()
|
||||
{
|
||||
if (TabViewItem().IsSelected())
|
||||
{
|
||||
VisualStateManager::GoToState(TabViewItem(), L"Normal", true);
|
||||
VisualStateManager::GoToState(TabViewItem(), L"Selected", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
VisualStateManager::GoToState(TabViewItem(), L"Selected", true);
|
||||
VisualStateManager::GoToState(TabViewItem(), L"Normal", true);
|
||||
}
|
||||
}
|
||||
|
||||
// - Get the total number of leaf panes in this tab. This will be the number
|
||||
// of actual controls hosted by this tab.
|
||||
// Arguments:
|
||||
|
||||
@@ -71,10 +71,7 @@ namespace winrt::TerminalApp::implementation
|
||||
void ResetTabText();
|
||||
void ActivateTabRenamer();
|
||||
|
||||
std::optional<winrt::Windows::UI::Color> GetTabColor();
|
||||
|
||||
void ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused,
|
||||
const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused);
|
||||
virtual std::optional<winrt::Windows::UI::Color> GetTabColor() override;
|
||||
void SetRuntimeTabColor(const winrt::Windows::UI::Color& color);
|
||||
void ResetRuntimeTabColor();
|
||||
void RequestColorPicker();
|
||||
@@ -101,8 +98,6 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
WINRT_CALLBACK(ActivePaneChanged, winrt::delegate<>);
|
||||
WINRT_CALLBACK(ColorSelected, winrt::delegate<winrt::Windows::UI::Color>);
|
||||
WINRT_CALLBACK(ColorCleared, winrt::delegate<>);
|
||||
WINRT_CALLBACK(TabRaiseVisualBell, winrt::delegate<>);
|
||||
WINRT_CALLBACK(DuplicateRequested, winrt::delegate<>);
|
||||
WINRT_CALLBACK(SplitTabRequested, winrt::delegate<>);
|
||||
@@ -120,8 +115,6 @@ namespace winrt::TerminalApp::implementation
|
||||
std::optional<winrt::Windows::UI::Color> _runtimeTabColor{};
|
||||
winrt::TerminalApp::TabHeaderControl _headerControl{};
|
||||
winrt::TerminalApp::TerminalTabStatus _tabStatus{};
|
||||
winrt::Microsoft::Terminal::Settings::Model::ThemeColor _themeColor{ nullptr };
|
||||
winrt::Microsoft::Terminal::Settings::Model::ThemeColor _unfocusedThemeColor{ nullptr };
|
||||
|
||||
winrt::TerminalApp::ColorPickupFlyout _tabColorPickup{ nullptr };
|
||||
winrt::event_token _colorSelectedToken;
|
||||
@@ -165,8 +158,6 @@ namespace winrt::TerminalApp::implementation
|
||||
void _CreateContextMenu() override;
|
||||
virtual winrt::hstring _CreateToolTipTitle() override;
|
||||
|
||||
void _RefreshVisualState();
|
||||
|
||||
void _DetachEventHandlersFromControl(const uint32_t paneId, const winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
void _AttachEventHandlersToControl(const uint32_t paneId, const winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
void _AttachEventHandlersToPane(std::shared_ptr<Pane> pane);
|
||||
@@ -175,16 +166,14 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
winrt::hstring _GetActiveTitle() const;
|
||||
|
||||
void _RecalculateAndApplyTabColor();
|
||||
void _ApplyTabColor(const winrt::Windows::UI::Color& color);
|
||||
void _ClearTabBackgroundColor();
|
||||
|
||||
void _RecalculateAndApplyReadOnly();
|
||||
|
||||
void _UpdateProgressState();
|
||||
|
||||
void _DuplicateTab();
|
||||
|
||||
virtual winrt::Windows::UI::Xaml::Media::Brush _BackgroundBrush() override;
|
||||
|
||||
friend class ::TerminalAppLocalTests::TabTests;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// Miscellaneous
|
||||
"confirmCloseAllTabs": true,
|
||||
"startOnUserLogin": false,
|
||||
"theme": "system",
|
||||
"theme": "dark",
|
||||
"snapToGridOnResize": true,
|
||||
"disableAnimations": false,
|
||||
"startupActions": "",
|
||||
@@ -283,20 +283,44 @@
|
||||
"themes": [
|
||||
{
|
||||
"name": "light",
|
||||
"window":{
|
||||
"window":
|
||||
{
|
||||
"applicationTheme": "light"
|
||||
},
|
||||
"tab":
|
||||
{
|
||||
"background": "terminalBackground",
|
||||
"unfocusedBackground": "#00000000"
|
||||
},
|
||||
"tabRow":
|
||||
{
|
||||
"unfocusedBackground": "#FFFFFFFF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "dark",
|
||||
"window":{
|
||||
"window":
|
||||
{
|
||||
"applicationTheme": "dark"
|
||||
},
|
||||
"tab":
|
||||
{
|
||||
"background": "terminalBackground",
|
||||
"unfocusedBackground": "#00000000",
|
||||
},
|
||||
"tabRow":
|
||||
{
|
||||
"unfocusedBackground": "#333333FF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "system",
|
||||
"window":{
|
||||
"applicationTheme": "system"
|
||||
},
|
||||
"tab":{
|
||||
"background": "terminalBackground",
|
||||
"unfocusedBackground": "#00000000",
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
@@ -53,3 +53,66 @@ winrt::Windows::Foundation::IAsyncOperation<winrt::hstring> SaveFilePicker(HWND
|
||||
}
|
||||
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::hstring> OpenImagePicker(HWND parentHwnd);
|
||||
|
||||
#ifdef WINRT_Windows_UI_Xaml_H
|
||||
// Only compile me if Windows.UI.Xaml is already included.
|
||||
//
|
||||
// XAML Hacks:
|
||||
//
|
||||
// the App is always in the OS theme, so the
|
||||
// App::Current().Resources() lookup will always get the value for the
|
||||
// OS theme, not the requested theme.
|
||||
//
|
||||
// This helper allows us to instead lookup the value of a resource
|
||||
// specified by `key` for the given `requestedTheme`, from the
|
||||
// dictionaries in App.xaml. Make sure the value is actually there!
|
||||
// Otherwise this'll throw like any other Lookup for a resource that
|
||||
// isn't there.
|
||||
winrt::Windows::Foundation::IInspectable ThemeLookup(const auto& res,
|
||||
const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme,
|
||||
const winrt::Windows::Foundation::IInspectable& key)
|
||||
{
|
||||
// You want the Default version of the resource? Great, the App is
|
||||
// always in the OS theme. Just look it up and be done.
|
||||
if (requestedTheme == winrt::Windows::UI::Xaml::ElementTheme::Default)
|
||||
{
|
||||
return res.Lookup(key);
|
||||
}
|
||||
static const auto lightKey = winrt::box_value(L"Light");
|
||||
static const auto darkKey = winrt::box_value(L"Dark");
|
||||
// There isn't an ElementTheme::HighContrast.
|
||||
|
||||
auto requestedThemeKey = requestedTheme == winrt::Windows::UI::Xaml::ElementTheme::Dark ? darkKey : lightKey;
|
||||
for (const auto& dictionary : res.MergedDictionaries())
|
||||
{
|
||||
// Don't look in the MUX resources. They come first. A person
|
||||
// with more patience than me may find a way to look through our
|
||||
// dictionaries first, then the MUX ones, but that's not needed
|
||||
// currently
|
||||
if (dictionary.Source())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Look through the theme dictionaries we defined:
|
||||
for (const auto& [dictionaryKey, dict] : dictionary.ThemeDictionaries())
|
||||
{
|
||||
// Does the key for this dict match the theme we're looking for?
|
||||
if (winrt::unbox_value<winrt::hstring>(dictionaryKey) !=
|
||||
winrt::unbox_value<winrt::hstring>(requestedThemeKey))
|
||||
{
|
||||
// No? skip it.
|
||||
continue;
|
||||
}
|
||||
// Look for the requested resource in this dict.
|
||||
const auto themeDictionary = dict.as<winrt::Windows::UI::Xaml::ResourceDictionary>();
|
||||
if (themeDictionary.HasKey(key))
|
||||
{
|
||||
return themeDictionary.Lookup(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We didn't find it in the requested dict, fall back to the default dictionary.
|
||||
return res.Lookup(key);
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -134,6 +134,19 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
||||
};
|
||||
}
|
||||
|
||||
// Do a simple linear blend with `other`, taking a% of us and (1-a)% of
|
||||
// other. The result will retain our original alpha channel value
|
||||
constexpr color blend_with(const color& other)
|
||||
{
|
||||
auto result = *this;
|
||||
float a1 = a / 255.0f;
|
||||
float a2 = 1.0f - a1;
|
||||
result.r = static_cast<uint8_t>((a1 * r) + (a2 * other.r));
|
||||
result.g = static_cast<uint8_t>((a1 * g) + (a2 * other.g));
|
||||
result.b = static_cast<uint8_t>((a1 * b) + (a2 * other.b));
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef D3DCOLORVALUE_DEFINED
|
||||
constexpr operator D3DCOLORVALUE() const
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user