From 57e02b885be361129fe9e0ad0a3c9d904b1efc22 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 5 Aug 2022 09:58:28 -0500 Subject: [PATCH 01/11] sometimes I do the code good --- src/cascadia/TerminalApp/TerminalPage.cpp | 3 +- src/cascadia/TerminalApp/TerminalTab.cpp | 40 +++++++++++++++---- src/cascadia/TerminalApp/TerminalTab.h | 4 +- .../TerminalSettingsModel/MTSMSettings.h | 5 ++- src/cascadia/TerminalSettingsModel/Theme.cpp | 13 ++++++ src/cascadia/TerminalSettingsModel/Theme.h | 1 + src/cascadia/TerminalSettingsModel/Theme.idl | 2 + 7 files changed, 57 insertions(+), 11 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index eb8f02f06b8..186869bdcfe 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -4091,11 +4091,12 @@ namespace winrt::TerminalApp::implementation // 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); + terminalTabImpl->ThemeColor(tabBackground, tabUnfocusedBackground); } } } diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index 3b1307c9cab..3ad19e9e076 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -864,7 +864,7 @@ namespace winrt::TerminalApp::implementation } }); - events.taskbarToken = control.SetTaskbarProgress([dispatcher, weakThis](auto&&, auto&&) -> winrt::fire_and_forget { + events.taskbarToken = control.SetTaskbarProgress([dispatcher, weakThis](auto&&, auto &&) -> winrt::fire_and_forget { co_await wil::resume_foreground(dispatcher); // Check if Tab's lifetime has expired if (auto tab{ weakThis.get() }) @@ -1069,7 +1069,7 @@ namespace winrt::TerminalApp::implementation // Add a Closed event handler to the Pane. If the pane closes out from // underneath us, and it's zoomed, we want to be able to make sure to // update our state accordingly to un-zoom that pane. See GH#7252. - auto closedToken = pane->Closed([weakThis, weakPane](auto&& /*s*/, auto&& /*e*/) -> winrt::fire_and_forget { + auto closedToken = pane->Closed([weakThis, weakPane](auto&& /*s*/, auto && /*e*/) -> winrt::fire_and_forget { if (auto tab{ weakThis.get() }) { if (tab->_zoomedPane) @@ -1369,9 +1369,10 @@ namespace winrt::TerminalApp::implementation _RecalculateAndApplyTabColor(); } - void TerminalTab::ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& color) + void TerminalTab::ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused, const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused) { - _themeColor = color; + _themeColor = focused; + _unfocusedThemeColor = unfocused; _RecalculateAndApplyTabColor(); } @@ -1406,7 +1407,7 @@ namespace winrt::TerminalApp::implementation } else if (tab->_themeColor != nullptr) { - // One-liner to safely get the active control's brush. + // Safely get the active control's brush. Media::Brush terminalBrush{ nullptr }; if (const auto& c{ tab->GetActiveTerminalControl() }) { @@ -1485,10 +1486,35 @@ namespace winrt::TerminalApp::implementation 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(color); - deselectedTabBrush.Opacity(0.3); + deselectedTabBrush.Color(deselectedTabColor.with_alpha(255)); + deselectedTabBrush.Opacity(deselectedTabColor.a / 255.f); hoverTabBrush.Color(color); hoverTabBrush.Opacity(0.6); diff --git a/src/cascadia/TerminalApp/TerminalTab.h b/src/cascadia/TerminalApp/TerminalTab.h index d5e45ca0a0b..394fd87fb22 100644 --- a/src/cascadia/TerminalApp/TerminalTab.h +++ b/src/cascadia/TerminalApp/TerminalTab.h @@ -71,7 +71,8 @@ namespace winrt::TerminalApp::implementation std::optional GetTabColor(); - void ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& color); + void ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused, + const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused); void SetRuntimeTabColor(const winrt::Windows::UI::Color& color); void ResetRuntimeTabColor(); void ActivateColorPicker(); @@ -118,6 +119,7 @@ namespace winrt::TerminalApp::implementation winrt::TerminalApp::TabHeaderControl _headerControl{}; winrt::TerminalApp::TerminalTabStatus _tabStatus{}; winrt::Microsoft::Terminal::Settings::Model::ThemeColor _themeColor{ nullptr }; + winrt::Microsoft::Terminal::Settings::Model::ThemeColor _unfocusedThemeColor{ nullptr }; struct ControlEventTokens { diff --git a/src/cascadia/TerminalSettingsModel/MTSMSettings.h b/src/cascadia/TerminalSettingsModel/MTSMSettings.h index d95dbdfe43e..0aa612dcf1e 100644 --- a/src/cascadia/TerminalSettingsModel/MTSMSettings.h +++ b/src/cascadia/TerminalSettingsModel/MTSMSettings.h @@ -130,6 +130,7 @@ 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_TAB_SETTINGS(X) \ - X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, Background, "background", 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) \ X(winrt::Microsoft::Terminal::Settings::Model::TabCloseButtonVisibility, ShowCloseButton, "showCloseButton", winrt::Microsoft::Terminal::Settings::Model::TabCloseButtonVisibility::Always) diff --git a/src/cascadia/TerminalSettingsModel/Theme.cpp b/src/cascadia/TerminalSettingsModel/Theme.cpp index 236cb5ab987..8e5f8bb5789 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.cpp +++ b/src/cascadia/TerminalSettingsModel/Theme.cpp @@ -170,6 +170,19 @@ winrt::WUX::Media::Brush ThemeColor::Evaluate(const winrt::WUX::ResourceDictiona return nullptr; } +uint8_t ThemeColor::UnfocusedTabOpacity() const noexcept +{ + switch (ColorType()) + { + case ThemeColorType::Accent: + case ThemeColorType::TerminalBackground: + return 77; + case ThemeColorType::Color: + return _Color.a; + } + return 0; +} + #define THEME_SETTINGS_FROM_JSON(type, name, jsonKey, ...) \ { \ std::optional _val; \ diff --git a/src/cascadia/TerminalSettingsModel/Theme.h b/src/cascadia/TerminalSettingsModel/Theme.h index b27e42baa46..9ba500ffd78 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.h +++ b/src/cascadia/TerminalSettingsModel/Theme.h @@ -39,6 +39,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation winrt::Windows::UI::Xaml::Media::Brush Evaluate(const winrt::Windows::UI::Xaml::ResourceDictionary& res, const winrt::Windows::UI::Xaml::Media::Brush& terminalBackground, const bool forTitlebar); + uint8_t UnfocusedTabOpacity() const noexcept; WINRT_PROPERTY(til::color, Color); WINRT_PROPERTY(winrt::Microsoft::Terminal::Settings::Model::ThemeColorType, ColorType); diff --git a/src/cascadia/TerminalSettingsModel/Theme.idl b/src/cascadia/TerminalSettingsModel/Theme.idl index 3dd2782c48e..7078030fa9b 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.idl +++ b/src/cascadia/TerminalSettingsModel/Theme.idl @@ -32,6 +32,7 @@ namespace Microsoft.Terminal.Settings.Model Windows.UI.Xaml.Media.Brush Evaluate(Windows.UI.Xaml.ResourceDictionary res, Windows.UI.Xaml.Media.Brush terminalBackground, Boolean forTitlebar); + UInt8 UnfocusedTabOpacity { get; }; } runtimeclass WindowTheme { @@ -46,6 +47,7 @@ namespace Microsoft.Terminal.Settings.Model runtimeclass TabTheme { ThemeColor Background { get; }; + ThemeColor UnfocusedBackground { get; }; TabCloseButtonVisibility ShowCloseButton { get; }; } From bdfb015a3b339dd710fccd861e77b3552ff68bb1 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 11 Aug 2022 12:39:18 -0500 Subject: [PATCH 02/11] Allow the settings tab to also have a color set by the theme --- src/cascadia/TerminalApp/SettingsTab.cpp | 6 + src/cascadia/TerminalApp/SettingsTab.h | 2 + src/cascadia/TerminalApp/TabBase.cpp | 258 +++++++++++++++++++++ src/cascadia/TerminalApp/TabBase.h | 13 ++ src/cascadia/TerminalApp/TerminalPage.cpp | 12 +- src/cascadia/TerminalApp/TerminalTab.cpp | 260 +--------------------- src/cascadia/TerminalApp/TerminalTab.h | 17 +- 7 files changed, 295 insertions(+), 273 deletions(-) diff --git a/src/cascadia/TerminalApp/SettingsTab.cpp b/src/cascadia/TerminalApp/SettingsTab.cpp index 54e48ed1e0d..2b8b6f1b162 100644 --- a/src/cascadia/TerminalApp/SettingsTab.cpp +++ b/src/cascadia/TerminalApp/SettingsTab.cpp @@ -105,4 +105,10 @@ namespace winrt::TerminalApp::implementation TabViewItem().IconSource(IconPathConverter::IconSourceMUX(glyph)); } } + + winrt::Windows::UI::Xaml::Media::Brush SettingsTab::_BackgroundBrush() + { + static Media::SolidColorBrush campbellBg{ winrt::Windows::UI::Color{ 0xff, 0x0c, 0x0c, 0x0c } }; + return campbellBg; + } } diff --git a/src/cascadia/TerminalApp/SettingsTab.h b/src/cascadia/TerminalApp/SettingsTab.h index 803ed8cb03e..8dc7d83114e 100644 --- a/src/cascadia/TerminalApp/SettingsTab.h +++ b/src/cascadia/TerminalApp/SettingsTab.h @@ -34,5 +34,7 @@ namespace winrt::TerminalApp::implementation private: void _MakeTabViewItem() override; winrt::fire_and_forget _CreateIcon(); + + virtual winrt::Windows::UI::Xaml::Media::Brush _BackgroundBrush() override; }; } diff --git a/src/cascadia/TerminalApp/TabBase.cpp b/src/cascadia/TerminalApp/TabBase.cpp index 167b5008066..80502ec8161 100644 --- a/src/cascadia/TerminalApp/TabBase.cpp +++ b/src/cascadia/TerminalApp/TabBase.cpp @@ -5,6 +5,8 @@ #include #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,260 @@ namespace winrt::TerminalApp::implementation }); } + std::optional TabBase::GetTabColor() + { + return std::nullopt; + } + + void TabBase::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: + // - + // Return Value: + // - + 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: + // - + void TabBase::_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{ _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(); + } + + // Method Description: + // - Clear out any color we've set for the TabViewItem. + // - This method should only be called on the UI thread. + // Arguments: + // - + // Return Value: + // - + 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: + // - + // Return Value: + // - + 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); + } + } + } diff --git a/src/cascadia/TerminalApp/TabBase.h b/src/cascadia/TerminalApp/TabBase.h index a04873f8905..bb510945ef2 100644 --- a/src/cascadia/TerminalApp/TabBase.h +++ b/src/cascadia/TerminalApp/TabBase.h @@ -25,6 +25,10 @@ namespace winrt::TerminalApp::implementation void SetActionMap(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap); virtual std::vector BuildStartupActions() const = 0; + virtual std::optional GetTabColor(); + void ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused, + const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused); + WINRT_CALLBACK(RequestFocusActiveControl, winrt::delegate); WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler); @@ -51,6 +55,9 @@ 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 }; + virtual void _CreateContextMenu(); virtual winrt::hstring _CreateToolTipTitle(); @@ -63,6 +70,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; }; } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 747b26fc35a..63d12ec7860 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -4108,10 +4108,12 @@ namespace winrt::TerminalApp::implementation auto tabUnfocusedBackground = theme.Tab() ? theme.Tab().UnfocusedBackground() : nullptr; for (const auto& tab : _tabs) { - if (const auto& terminalTabImpl{ _GetTerminalTabImpl(tab) }) - { - terminalTabImpl->ThemeColor(tabBackground, tabUnfocusedBackground); - } + winrt::com_ptr tabImpl; + tabImpl.copy_from(winrt::get_self(tab)); + // if (const auto& terminalTabImpl{ _GetTerminalTabImpl(tab) }) + // { + tabImpl->ThemeColor(tabBackground, tabUnfocusedBackground); + // } } } @@ -4200,6 +4202,8 @@ namespace winrt::TerminalApp::implementation } else if (auto settingsTab = _GetFocusedTab().try_as()) { + // static Media::SolidColorBrush campbellBg{ winrt::Windows::UI::Color{ 0x0c, 0x0c, 0x0c } }; + // return campbellBg; // return settingsTab.Content().try_as().BackgroundBrush(); } return nullptr; diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index 758cdf7b51a..0e1c6aa1821 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -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: - // - - // Return Value: - // - - 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: - // - - 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: - // - - // Return Value: - // - - 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: - // - - // Return Value: - // - - 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: diff --git a/src/cascadia/TerminalApp/TerminalTab.h b/src/cascadia/TerminalApp/TerminalTab.h index ad70348d090..53492095db1 100644 --- a/src/cascadia/TerminalApp/TerminalTab.h +++ b/src/cascadia/TerminalApp/TerminalTab.h @@ -71,10 +71,7 @@ namespace winrt::TerminalApp::implementation void ResetTabText(); void ActivateTabRenamer(); - std::optional GetTabColor(); - - void ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused, - const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused); + virtual std::optional 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_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 _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); @@ -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; }; } From 4146d71079a2a1c3812ee7b32457b1d4f1081bbf Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 11 Aug 2022 13:34:07 -0500 Subject: [PATCH 03/11] default settings changes --- src/cascadia/TerminalApp/App.xaml | 4 +-- src/cascadia/TerminalApp/SettingsTab.cpp | 1 + .../TerminalSettingsModel/defaults.json | 30 +++++++++++++++++-- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/cascadia/TerminalApp/App.xaml b/src/cascadia/TerminalApp/App.xaml index 2f025073f97..526e9e7de4e 100644 --- a/src/cascadia/TerminalApp/App.xaml +++ b/src/cascadia/TerminalApp/App.xaml @@ -149,7 +149,7 @@ See GH #12356 for more history on the subject. --> + Color="#2e2e2e" /> @@ -162,7 +162,7 @@ GH #12398 has more history on this value, as well as GH #12400 --> + Color="#e8e8e8" /> diff --git a/src/cascadia/TerminalApp/SettingsTab.cpp b/src/cascadia/TerminalApp/SettingsTab.cpp index 2b8b6f1b162..6f28db42b6c 100644 --- a/src/cascadia/TerminalApp/SettingsTab.cpp +++ b/src/cascadia/TerminalApp/SettingsTab.cpp @@ -108,6 +108,7 @@ namespace winrt::TerminalApp::implementation winrt::Windows::UI::Xaml::Media::Brush SettingsTab::_BackgroundBrush() { + // TODO! convert to a resource lookup static Media::SolidColorBrush campbellBg{ winrt::Windows::UI::Color{ 0xff, 0x0c, 0x0c, 0x0c } }; return campbellBg; } diff --git a/src/cascadia/TerminalSettingsModel/defaults.json b/src/cascadia/TerminalSettingsModel/defaults.json index 76d5f4b3bd1..9f1a3ef4f46 100644 --- a/src/cascadia/TerminalSettingsModel/defaults.json +++ b/src/cascadia/TerminalSettingsModel/defaults.json @@ -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", } } ], From f911929e43cb612c30f316240366ee03cdb4361c Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 11 Aug 2022 15:48:27 -0500 Subject: [PATCH 04/11] transparent inactive tabs on light tab row, when the tabs have a dark FG color, works sanely now --- src/cascadia/TerminalApp/TabBase.cpp | 23 ++++++++++++++--- src/cascadia/TerminalApp/TabBase.h | 4 ++- src/cascadia/TerminalApp/TerminalPage.cpp | 30 +++++++++++------------ src/inc/til/color.h | 11 +++++++++ 4 files changed, 49 insertions(+), 19 deletions(-) diff --git a/src/cascadia/TerminalApp/TabBase.cpp b/src/cascadia/TerminalApp/TabBase.cpp index 80502ec8161..c352ae54129 100644 --- a/src/cascadia/TerminalApp/TabBase.cpp +++ b/src/cascadia/TerminalApp/TabBase.cpp @@ -260,10 +260,12 @@ namespace winrt::TerminalApp::implementation } void TabBase::ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused, - const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused) + const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused, + const til::color& tabRowColor) { _themeColor = focused; _unfocusedThemeColor = unfocused; + _tabRowColor = tabRowColor; _RecalculateAndApplyTabColor(); } @@ -335,6 +337,7 @@ namespace winrt::TerminalApp::implementation Media::SolidColorBrush selectedTabBrush{}; Media::SolidColorBrush deselectedTabBrush{}; Media::SolidColorBrush fontBrush{}; + Media::SolidColorBrush deselectedFontBrush{}; Media::SolidColorBrush secondaryFontBrush{}; Media::SolidColorBrush hoverTabBrush{}; Media::SolidColorBrush subtleFillColorSecondaryBrush; @@ -395,6 +398,7 @@ namespace winrt::TerminalApp::implementation 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)); @@ -403,6 +407,16 @@ namespace winrt::TerminalApp::implementation hoverTabBrush.Color(color); hoverTabBrush.Opacity(0.6); + 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 @@ -421,11 +435,13 @@ namespace winrt::TerminalApp::implementation // 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().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"), 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); @@ -433,6 +449,7 @@ namespace winrt::TerminalApp::implementation 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); diff --git a/src/cascadia/TerminalApp/TabBase.h b/src/cascadia/TerminalApp/TabBase.h index bb510945ef2..aea386ee760 100644 --- a/src/cascadia/TerminalApp/TabBase.h +++ b/src/cascadia/TerminalApp/TabBase.h @@ -27,7 +27,8 @@ namespace winrt::TerminalApp::implementation virtual std::optional GetTabColor(); void ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused, - const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused); + const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused, + const til::color& tabRowColor); WINRT_CALLBACK(RequestFocusActiveControl, winrt::delegate); @@ -57,6 +58,7 @@ namespace winrt::TerminalApp::implementation 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(); diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 63d12ec7860..e4c97721272 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -4102,21 +4102,6 @@ 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) - { - winrt::com_ptr tabImpl; - tabImpl.copy_from(winrt::get_self(tab)); - // if (const auto& terminalTabImpl{ _GetTerminalTabImpl(tab) }) - // { - tabImpl->ThemeColor(tabBackground, tabUnfocusedBackground); - // } - } - } - const auto res = Application::Current().Resources(); // XAML Hacks: @@ -4224,6 +4209,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 + { + auto tabBackground = theme.Tab() ? theme.Tab().Background() : nullptr; + auto tabUnfocusedBackground = theme.Tab() ? theme.Tab().UnfocusedBackground() : nullptr; + for (const auto& tab : _tabs) + { + winrt::com_ptr tabImpl; + tabImpl.copy_from(winrt::get_self(tab)); + // if (const auto& terminalTabImpl{ _GetTerminalTabImpl(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. diff --git a/src/inc/til/color.h b/src/inc/til/color.h index 5054be53318..3461057026f 100644 --- a/src/inc/til/color.h +++ b/src/inc/til/color.h @@ -134,6 +134,17 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" }; } + constexpr color blend_with(const color& other) + { + auto result = *this; + float a1 = a / 255.0f; + float a2 = 1.0f - a1; + result.r = static_cast((a1 * r) + (a2 * other.r)); + result.g = static_cast((a1 * g) + (a2 * other.g)); + result.b = static_cast((a1 * b) + (a2 * other.b)); + return result; + } + #ifdef D3DCOLORVALUE_DEFINED constexpr operator D3DCOLORVALUE() const { From 2964ebe70ffe98ae22833d6954e82ce23b803ad1 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 11 Aug 2022 15:52:50 -0500 Subject: [PATCH 05/11] comments --- src/cascadia/TerminalApp/TabBase.cpp | 16 ++++++++++++---- src/inc/til/color.h | 2 ++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/cascadia/TerminalApp/TabBase.cpp b/src/cascadia/TerminalApp/TabBase.cpp index c352ae54129..ad4bb152758 100644 --- a/src/cascadia/TerminalApp/TabBase.cpp +++ b/src/cascadia/TerminalApp/TabBase.cpp @@ -407,6 +407,14 @@ namespace winrt::TerminalApp::implementation 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)) { @@ -431,10 +439,10 @@ namespace winrt::TerminalApp::implementation 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. + // 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); diff --git a/src/inc/til/color.h b/src/inc/til/color.h index 3461057026f..5d4ade26c99 100644 --- a/src/inc/til/color.h +++ b/src/inc/til/color.h @@ -134,6 +134,8 @@ 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; From 37ce10705a6b7d8d35f3ae25c04f9e79d552480d Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 11 Aug 2022 16:52:04 -0500 Subject: [PATCH 06/11] I can't tell you how much I hate this --- src/cascadia/TerminalApp/App.xaml | 9 +++ src/cascadia/TerminalApp/SettingsTab.cpp | 12 ++- src/cascadia/TerminalApp/SettingsTab.h | 2 + src/cascadia/TerminalApp/TerminalPage.cpp | 91 ++++++++++++----------- src/cascadia/WinRTUtils/inc/Utils.h | 51 +++++++++++++ 5 files changed, 117 insertions(+), 48 deletions(-) diff --git a/src/cascadia/TerminalApp/App.xaml b/src/cascadia/TerminalApp/App.xaml index 526e9e7de4e..01b315644cc 100644 --- a/src/cascadia/TerminalApp/App.xaml +++ b/src/cascadia/TerminalApp/App.xaml @@ -153,6 +153,9 @@ + + @@ -166,6 +169,9 @@ + + @@ -183,6 +189,9 @@ --> + + diff --git a/src/cascadia/TerminalApp/SettingsTab.cpp b/src/cascadia/TerminalApp/SettingsTab.cpp index 6f28db42b6c..c56464a3416 100644 --- a/src/cascadia/TerminalApp/SettingsTab.cpp +++ b/src/cascadia/TerminalApp/SettingsTab.cpp @@ -36,6 +36,8 @@ namespace winrt::TerminalApp::implementation { auto settingsUI{ Content().as() }; settingsUI.UpdateSettings(settings); + + _requestedTheme = settings.GlobalSettings().CurrentTheme().RequestedTheme(); } // Method Description: @@ -108,8 +110,12 @@ namespace winrt::TerminalApp::implementation winrt::Windows::UI::Xaml::Media::Brush SettingsTab::_BackgroundBrush() { - // TODO! convert to a resource lookup - static Media::SolidColorBrush campbellBg{ winrt::Windows::UI::Color{ 0xff, 0x0c, 0x0c, 0x0c } }; - return campbellBg; + // // TODO! convert to a resource lookup + // static Media::SolidColorBrush campbellBg{ winrt::Windows::UI::Color{ 0xff, 0x0c, 0x0c, 0x0c } }; + // return campbellBg; + + static const auto key = winrt::box_value(L"SettingsUiTabBrush"); + // return Application::Current().Resources().TryLookup(key).try_as(); + return ThemeLookup(Application::Current().Resources(), _requestedTheme, key).try_as(); } } diff --git a/src/cascadia/TerminalApp/SettingsTab.h b/src/cascadia/TerminalApp/SettingsTab.h index 8dc7d83114e..b324214f5d4 100644 --- a/src/cascadia/TerminalApp/SettingsTab.h +++ b/src/cascadia/TerminalApp/SettingsTab.h @@ -32,6 +32,8 @@ namespace winrt::TerminalApp::implementation std::vector BuildStartupActions() const override; private: + winrt::Windows::UI::Xaml::ElementTheme _requestedTheme; + void _MakeTabViewItem() override; winrt::fire_and_forget _CreateIcon(); diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index e4c97721272..f167cbc40e9 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -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; @@ -4115,54 +4116,54 @@ namespace winrt::TerminalApp::implementation // 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(dictionaryKey) != - winrt::unbox_value(requestedThemeKey)) - { - // No? skip it. - continue; - } - // Look for the requested resource in this dict. - const auto themeDictionary = dict.as(); - 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); - }; + // 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(dictionaryKey) != + // winrt::unbox_value(requestedThemeKey)) + // { + // // No? skip it. + // continue; + // } + // // Look for the requested resource in this dict. + // const auto themeDictionary = dict.as(); + // 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(); + const auto backgroundSolidBrush = ThemeLookup(res, requestedTheme, tabViewBackgroundKey).as(); til::color bgColor = backgroundSolidBrush.Color(); diff --git a/src/cascadia/WinRTUtils/inc/Utils.h b/src/cascadia/WinRTUtils/inc/Utils.h index 82824c5bfaa..79070c2d588 100644 --- a/src/cascadia/WinRTUtils/inc/Utils.h +++ b/src/cascadia/WinRTUtils/inc/Utils.h @@ -53,3 +53,54 @@ winrt::Windows::Foundation::IAsyncOperation SaveFilePicker(HWND } winrt::Windows::Foundation::IAsyncOperation OpenImagePicker(HWND parentHwnd); + +#ifdef WINRT_Windows_UI_Xaml_H + +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(dictionaryKey) != + winrt::unbox_value(requestedThemeKey)) + { + // No? skip it. + continue; + } + // Look for the requested resource in this dict. + const auto themeDictionary = dict.as(); + 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 From 25e09d695afa7d31f28fa61e25d7de126cb7c2df Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 11 Aug 2022 16:57:19 -0500 Subject: [PATCH 07/11] comments galore --- src/cascadia/TerminalApp/SettingsTab.cpp | 13 +++-- src/cascadia/TerminalApp/TerminalPage.cpp | 64 ++--------------------- src/cascadia/WinRTUtils/inc/Utils.h | 14 ++++- 3 files changed, 25 insertions(+), 66 deletions(-) diff --git a/src/cascadia/TerminalApp/SettingsTab.cpp b/src/cascadia/TerminalApp/SettingsTab.cpp index c56464a3416..33050a4eac4 100644 --- a/src/cascadia/TerminalApp/SettingsTab.cpp +++ b/src/cascadia/TerminalApp/SettingsTab.cpp @@ -37,6 +37,8 @@ namespace winrt::TerminalApp::implementation auto settingsUI{ Content().as() }; 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(); } @@ -110,12 +112,13 @@ namespace winrt::TerminalApp::implementation winrt::Windows::UI::Xaml::Media::Brush SettingsTab::_BackgroundBrush() { - // // TODO! convert to a resource lookup - // static Media::SolidColorBrush campbellBg{ winrt::Windows::UI::Color{ 0xff, 0x0c, 0x0c, 0x0c } }; - // return campbellBg; - + // 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"); - // return Application::Current().Resources().TryLookup(key).try_as(); + // 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(); } } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index f167cbc40e9..0e34dd75b31 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -4105,62 +4105,6 @@ namespace winrt::TerminalApp::implementation 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(dictionaryKey) != - // winrt::unbox_value(requestedThemeKey)) - // { - // // No? skip it. - // continue; - // } - // // Look for the requested resource in this dict. - // const auto themeDictionary = dict.as(); - // 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 = ThemeLookup(res, requestedTheme, tabViewBackgroundKey).as(); @@ -4210,7 +4154,10 @@ 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 + // 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; @@ -4218,10 +4165,7 @@ namespace winrt::TerminalApp::implementation { winrt::com_ptr tabImpl; tabImpl.copy_from(winrt::get_self(tab)); - // if (const auto& terminalTabImpl{ _GetTerminalTabImpl(tab) }) - // { tabImpl->ThemeColor(tabBackground, tabUnfocusedBackground, bgColor); - // } } } diff --git a/src/cascadia/WinRTUtils/inc/Utils.h b/src/cascadia/WinRTUtils/inc/Utils.h index 79070c2d588..c6864280204 100644 --- a/src/cascadia/WinRTUtils/inc/Utils.h +++ b/src/cascadia/WinRTUtils/inc/Utils.h @@ -55,7 +55,19 @@ winrt::Windows::Foundation::IAsyncOperation SaveFilePicker(HWND winrt::Windows::Foundation::IAsyncOperation 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) From 48deba0245c801ed0e76a55f377c3e700b6ae718 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 12 Aug 2022 06:56:16 -0500 Subject: [PATCH 08/11] Revert the changes I made to the default themes --- src/cascadia/TerminalApp/App.xaml | 4 +-- .../TerminalSettingsModel/defaults.json | 30 ++----------------- 2 files changed, 5 insertions(+), 29 deletions(-) diff --git a/src/cascadia/TerminalApp/App.xaml b/src/cascadia/TerminalApp/App.xaml index 01b315644cc..7dabb689a3c 100644 --- a/src/cascadia/TerminalApp/App.xaml +++ b/src/cascadia/TerminalApp/App.xaml @@ -149,7 +149,7 @@ See GH #12356 for more history on the subject. --> + Color="#0a0a0a" /> @@ -165,7 +165,7 @@ GH #12398 has more history on this value, as well as GH #12400 --> + Color="#dadada" /> diff --git a/src/cascadia/TerminalSettingsModel/defaults.json b/src/cascadia/TerminalSettingsModel/defaults.json index 9f1a3ef4f46..76d5f4b3bd1 100644 --- a/src/cascadia/TerminalSettingsModel/defaults.json +++ b/src/cascadia/TerminalSettingsModel/defaults.json @@ -26,7 +26,7 @@ // Miscellaneous "confirmCloseAllTabs": true, "startOnUserLogin": false, - "theme": "dark", + "theme": "system", "snapToGridOnResize": true, "disableAnimations": false, "startupActions": "", @@ -283,44 +283,20 @@ "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", } } ], From ff90631463d0337997f396dcb01e337a1db1b14e Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 12 Aug 2022 06:59:46 -0500 Subject: [PATCH 09/11] runformat --- src/cascadia/TerminalApp/TerminalTab.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index 0e1c6aa1821..4bac51928bf 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -904,7 +904,7 @@ namespace winrt::TerminalApp::implementation } }); - events.taskbarToken = control.SetTaskbarProgress([dispatcher, weakThis](auto&&, auto &&) -> winrt::fire_and_forget { + events.taskbarToken = control.SetTaskbarProgress([dispatcher, weakThis](auto&&, auto&&) -> winrt::fire_and_forget { co_await wil::resume_foreground(dispatcher); // Check if Tab's lifetime has expired if (auto tab{ weakThis.get() }) @@ -1109,7 +1109,7 @@ namespace winrt::TerminalApp::implementation // Add a Closed event handler to the Pane. If the pane closes out from // underneath us, and it's zoomed, we want to be able to make sure to // update our state accordingly to un-zoom that pane. See GH#7252. - auto closedToken = pane->Closed([weakThis, weakPane](auto&& /*s*/, auto && /*e*/) -> winrt::fire_and_forget { + auto closedToken = pane->Closed([weakThis, weakPane](auto&& /*s*/, auto&& /*e*/) -> winrt::fire_and_forget { if (auto tab{ weakThis.get() }) { if (tab->_zoomedPane) From b04019258f235f1486b69c2d02bbb4c83f66a0e4 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 15 Aug 2022 12:56:47 -0500 Subject: [PATCH 10/11] Thanks austin mode --- src/inc/til/color.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/inc/til/color.h b/src/inc/til/color.h index 5d4ade26c99..8533cda7a1a 100644 --- a/src/inc/til/color.h +++ b/src/inc/til/color.h @@ -139,8 +139,8 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" constexpr color blend_with(const color& other) { auto result = *this; - float a1 = a / 255.0f; - float a2 = 1.0f - a1; + const float a1 = a / 255.0f; + const float a2 = 1.0f - a1; result.r = static_cast((a1 * r) + (a2 * other.r)); result.g = static_cast((a1 * g) + (a2 * other.g)); result.b = static_cast((a1 * b) + (a2 * other.b)); From dd218d1e60deab8f49cb2ad1402b89e2748c4dc8 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 15 Aug 2022 12:57:38 -0500 Subject: [PATCH 11/11] Revert "Revert the changes I made to the default themes" This reverts commit 48deba0245c801ed0e76a55f377c3e700b6ae718. --- src/cascadia/TerminalApp/App.xaml | 4 +-- .../TerminalSettingsModel/defaults.json | 30 +++++++++++++++++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/cascadia/TerminalApp/App.xaml b/src/cascadia/TerminalApp/App.xaml index 7dabb689a3c..01b315644cc 100644 --- a/src/cascadia/TerminalApp/App.xaml +++ b/src/cascadia/TerminalApp/App.xaml @@ -149,7 +149,7 @@ See GH #12356 for more history on the subject. --> + Color="#2e2e2e" /> @@ -165,7 +165,7 @@ GH #12398 has more history on this value, as well as GH #12400 --> + Color="#e8e8e8" /> diff --git a/src/cascadia/TerminalSettingsModel/defaults.json b/src/cascadia/TerminalSettingsModel/defaults.json index 76d5f4b3bd1..9f1a3ef4f46 100644 --- a/src/cascadia/TerminalSettingsModel/defaults.json +++ b/src/cascadia/TerminalSettingsModel/defaults.json @@ -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", } } ],