From 15e4fd9be96079e9ef1d5114ee3a2d441b7a4aef Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 24 Mar 2022 06:31:38 -0500 Subject: [PATCH 01/61] Settings project builds at least --- .../GlobalAppSettings.cpp | 11 +++ .../TerminalSettingsModel/GlobalAppSettings.h | 4 + .../GlobalAppSettings.idl | 5 +- .../TerminalSettingsModel/MTSMSettings.h | 5 +- ...crosoft.Terminal.Settings.ModelLib.vcxproj | 7 ++ src/cascadia/TerminalSettingsModel/Theme.cpp | 94 +++++++++++++++++++ src/cascadia/TerminalSettingsModel/Theme.h | 58 ++++++++++++ src/cascadia/TerminalSettingsModel/Theme.idl | 21 +++++ 8 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 src/cascadia/TerminalSettingsModel/Theme.cpp create mode 100644 src/cascadia/TerminalSettingsModel/Theme.h create mode 100644 src/cascadia/TerminalSettingsModel/Theme.idl diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp index e417042e44e..0c3b9c0f503 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp @@ -17,6 +17,7 @@ using namespace winrt::Microsoft::UI::Xaml::Controls; static constexpr std::string_view LegacyKeybindingsKey{ "keybindings" }; static constexpr std::string_view ActionsKey{ "actions" }; +static constexpr std::string_view ThemeKey{ "theme" }; static constexpr std::string_view DefaultProfileKey{ "defaultProfile" }; static constexpr std::string_view LegacyUseTabSwitcherModeKey{ "useTabSwitcher" }; @@ -140,6 +141,11 @@ void GlobalAppSettings::LayerJson(const Json::Value& json) _keybindingsWarnings.insert(_keybindingsWarnings.end(), warnings.begin(), warnings.end()); } } + + if (auto themeJson{ json[JsonKey(ThemeKey)] }) + { + _theme->LayerJson(themeJson); + } } // Method Description: @@ -192,3 +198,8 @@ Json::Value GlobalAppSettings::ToJson() const json[JsonKey(ActionsKey)] = _actionMap->ToJson(); return json; } + +winrt::Microsoft::Terminal::Settings::Model::Theme GlobalAppSettings::Theme() noexcept +{ + return *_theme; +} diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h index 14584b26a72..e81c7efe629 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h @@ -22,6 +22,7 @@ Author(s): #include "ActionMap.h" #include "Command.h" #include "ColorScheme.h" +#include "Theme.h" // fwdecl unittest classes namespace SettingsModelLocalTests @@ -62,6 +63,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation DisableAnimations(!invertedDisableAnimationsValue); } + Model::Theme Theme() noexcept; + INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, UnparsedDefaultProfile, L""); #define GLOBAL_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \ @@ -78,6 +81,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation winrt::guid _defaultProfile; winrt::com_ptr _actionMap{ winrt::make_self() }; + winrt::com_ptr _theme{ winrt::make_self() }; std::vector _keybindingsWarnings; Windows::Foundation::Collections::IMap _colorSchemes{ winrt::single_threaded_map() }; }; diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl index 90e11994320..a61f0fc8cb1 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl @@ -3,6 +3,7 @@ #include "IInheritable.idl.h" +import "Theme.idl"; import "ColorScheme.idl"; import "ActionMap.idl"; @@ -54,7 +55,7 @@ namespace Microsoft.Terminal.Settings.Model INHERITABLE_SETTING(Boolean, ShowTitleInTitlebar); INHERITABLE_SETTING(Boolean, ConfirmCloseAllTabs); INHERITABLE_SETTING(String, Language); - INHERITABLE_SETTING(Windows.UI.Xaml.ElementTheme, Theme); + // INHERITABLE_SETTING(Windows.UI.Xaml.ElementTheme, Theme); INHERITABLE_SETTING(Microsoft.UI.Xaml.Controls.TabViewWidthMode, TabWidthMode); INHERITABLE_SETTING(Boolean, UseAcrylicInTabRow); INHERITABLE_SETTING(Boolean, ShowTabsInTitlebar); @@ -93,5 +94,7 @@ namespace Microsoft.Terminal.Settings.Model void RemoveColorScheme(String schemeName); ActionMap ActionMap { get; }; + + Theme Theme { get; }; } } diff --git a/src/cascadia/TerminalSettingsModel/MTSMSettings.h b/src/cascadia/TerminalSettingsModel/MTSMSettings.h index f2f95a562f5..2077a3b60b6 100644 --- a/src/cascadia/TerminalSettingsModel/MTSMSettings.h +++ b/src/cascadia/TerminalSettingsModel/MTSMSettings.h @@ -33,7 +33,6 @@ Author(s): X(bool, ShowTitleInTitlebar, "showTerminalTitleInTitlebar", true) \ X(bool, ConfirmCloseAllTabs, "confirmCloseAllTabs", true) \ X(hstring, Language, "language") \ - X(winrt::Windows::UI::Xaml::ElementTheme, Theme, "theme", winrt::Windows::UI::Xaml::ElementTheme::Default) \ X(winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, TabWidthMode, "tabWidthMode", winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode::Equal) \ X(bool, UseAcrylicInTabRow, "useAcrylicInTabRow", false) \ X(bool, ShowTabsInTitlebar, "showTabsInTitlebar", true) \ @@ -110,3 +109,7 @@ Author(s): // Intentionally omitted Appearance settings: // * ForegroundKey, BackgroundKey, SelectionBackgroundKey, CursorColorKey: all optional colors // * Opacity: needs special parsing + +#define MTSM_THEME_SETTINGS(X) \ + X(winrt::Windows::UI::Xaml::ElementTheme, RequestedTheme, "window.requestedTheme", winrt::Windows::UI::Xaml::ElementTheme::Default) \ + X(bool, UseMica, "window.useMica", false) diff --git a/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj b/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj index bf0e68e2662..43c22aab237 100644 --- a/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj +++ b/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj @@ -42,6 +42,9 @@ ColorScheme.idl + + Theme.idl + Command.idl @@ -122,6 +125,9 @@ ColorScheme.idl + + Theme.idl + Command.idl @@ -167,6 +173,7 @@ + diff --git a/src/cascadia/TerminalSettingsModel/Theme.cpp b/src/cascadia/TerminalSettingsModel/Theme.cpp new file mode 100644 index 00000000000..f4b038bd460 --- /dev/null +++ b/src/cascadia/TerminalSettingsModel/Theme.cpp @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "Theme.h" +#include "../../types/inc/Utils.hpp" +#include "../../types/inc/colorTable.hpp" +#include "Utils.h" +#include "JsonUtils.h" +#include "TerminalSettingsSerializationHelpers.h" + +#include "Theme.g.cpp" + +using namespace ::Microsoft::Console; +using namespace Microsoft::Terminal::Settings::Model; +using namespace winrt::Microsoft::Terminal::Settings::Model::implementation; +using namespace winrt::Windows::UI; + +static constexpr std::string_view NameKey{ "name" }; + +Theme::Theme() noexcept : + Theme{ winrt::Windows::UI::Xaml::ElementTheme::Default } +{ +} + +Theme::Theme(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme) noexcept : + _RequestedTheme{ requestedTheme } +{ +} + +winrt::com_ptr Theme::Copy() const +{ + auto theme{ winrt::make_self() }; + +#define THEME_SETTINGS_COPY(type, name, jsonKey, ...) \ + theme->_##name = _##name; + + MTSM_THEME_SETTINGS(THEME_SETTINGS_COPY) +#undef THEME_SETTINGS_COPY + + return theme; +} + +// Method Description: +// - Create a new instance of this class from a serialized JsonObject. +// Arguments: +// - json: an object which should be a serialization of a ColorScheme object. +// Return Value: +// - Returns nullptr for invalid JSON. +winrt::com_ptr Theme::FromJson(const Json::Value& json) +{ + auto result = winrt::make_self(); + result->LayerJson(json); + return result; +} + +void Theme::LayerJson(const Json::Value& json) +{ + if (json.isString()) + { + JsonUtils::GetValue(json, _Name); + JsonUtils::GetValue(json, _RequestedTheme); + return; + } + + JsonUtils::GetValueForKey(json, NameKey, _Name); + +#define THEME_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \ + JsonUtils::GetValueForKey(json, jsonKey, _##name); + + MTSM_THEME_SETTINGS(THEME_SETTINGS_LAYER_JSON) +#undef THEME_SETTINGS_LAYER_JSON +} + +// Method Description: +// - Create a new serialized JsonObject from an instance of this class +// Arguments: +// - +// Return Value: +// - the JsonObject representing this instance +Json::Value Theme::ToJson() const +{ + Json::Value json{ Json::ValueType::objectValue }; + + JsonUtils::SetValueForKey(json, NameKey, _Name); + +#define THEME_SETTINGS_TO_JSON(type, name, jsonKey, ...) \ + JsonUtils::SetValueForKey(json, jsonKey, _##name); + + MTSM_THEME_SETTINGS(THEME_SETTINGS_TO_JSON) +#undef THEME_SETTINGS_TO_JSON + + return json; +} diff --git a/src/cascadia/TerminalSettingsModel/Theme.h b/src/cascadia/TerminalSettingsModel/Theme.h new file mode 100644 index 00000000000..b383147eadb --- /dev/null +++ b/src/cascadia/TerminalSettingsModel/Theme.h @@ -0,0 +1,58 @@ +/*++ +Copyright (c) Microsoft Corporation +Licensed under the MIT license. + +Module Name: +- Theme.hpp + +Abstract: +- TODO! + +Author(s): +- Mike Griese - March 2022 + +--*/ +#pragma once + +#include "../../inc/conattrs.hpp" +#include "DefaultSettings.h" +#include "IInheritable.h" +#include "MTSMSettings.h" + +#include "Theme.g.h" + +namespace winrt::Microsoft::Terminal::Settings::Model::implementation +{ + struct Theme : ThemeT + { + public: + Theme() noexcept; + Theme(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme) noexcept; + + com_ptr Copy() const; + + hstring ToString() + { + return Name(); + } + + static com_ptr FromJson(const Json::Value& json); + void LayerJson(const Json::Value& json); + Json::Value ToJson() const; + + WINRT_PROPERTY(winrt::hstring, Name); + +#define THEME_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \ + WINRT_PROPERTY(type, name, ##__VA_ARGS__) + + MTSM_THEME_SETTINGS(THEME_SETTINGS_INITIALIZE) +#undef THEME_SETTINGS_INITIALIZE + + private: + }; +} + +namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation +{ + BASIC_FACTORY(Theme); +} diff --git a/src/cascadia/TerminalSettingsModel/Theme.idl b/src/cascadia/TerminalSettingsModel/Theme.idl new file mode 100644 index 00000000000..f4a9c1a66af --- /dev/null +++ b/src/cascadia/TerminalSettingsModel/Theme.idl @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.Settings.Model +{ + [default_interface] runtimeclass Theme : Windows.Foundation.IStringable { + Theme(); + Theme(Windows.UI.Xaml.ElementTheme requestedTheme); + // Theme(String name); + + String Name; + + // Microsoft.Terminal.Core.Color TabRowColor { get; }; + Windows.UI.Xaml.ElementTheme RequestedTheme { get; }; + Boolean UseMica { get;}; + // Microsoft.Terminal.Core.Color Foreground; + // Microsoft.Terminal.Core.Color Background; + // Microsoft.Terminal.Core.Color SelectionBackground; + // Microsoft.Terminal.Core.Color CursorColor; + } +} From 7e0ae358fba206c10663a829fcbbee97a2477732 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 24 Mar 2022 06:45:52 -0500 Subject: [PATCH 02/61] this fixes the App bits as well --- src/cascadia/TerminalApp/AppLogic.cpp | 7 ++++--- src/cascadia/TerminalApp/TerminalPage.cpp | 3 ++- src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp | 2 +- src/cascadia/TerminalSettingsEditor/GlobalAppearance.h | 2 +- src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl | 4 ++-- src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml | 4 ++-- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index fe6636a4f93..ebdf63a7ef8 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -372,10 +372,11 @@ namespace winrt::TerminalApp::implementation // It's not enough to set the theme on the dialog alone. auto themingLambda{ [this](const Windows::Foundation::IInspectable& sender, const RoutedEventArgs&) { auto theme{ _settings.GlobalSettings().Theme() }; + auto requestedTheme{ theme.RequestedTheme() }; auto element{ sender.try_as() }; while (element) { - element.RequestedTheme(theme); + element.RequestedTheme(requestedTheme); element = element.Parent().try_as(); } } }; @@ -755,7 +756,7 @@ namespace winrt::TerminalApp::implementation LoadSettings(); } - return _settings.GlobalSettings().Theme(); + return _settings.GlobalSettings().Theme().RequestedTheme(); } bool AppLogic::GetShowTabsInTitlebar() @@ -976,7 +977,7 @@ namespace winrt::TerminalApp::implementation void AppLogic::_RefreshThemeRoutine() { - _ApplyTheme(_settings.GlobalSettings().Theme()); + _ApplyTheme(_settings.GlobalSettings().Theme().RequestedTheme()); } // Function Description: diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 8f79e9b8090..4203498e7d0 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -3394,9 +3394,10 @@ namespace winrt::TerminalApp::implementation void TerminalPage::_UpdateTeachingTipTheme(winrt::Windows::UI::Xaml::FrameworkElement element) { auto theme{ _settings.GlobalSettings().Theme() }; + auto requestedTheme{ theme.RequestedTheme() }; while (element) { - element.RequestedTheme(theme); + element.RequestedTheme(requestedTheme); element = element.Parent().try_as(); } } diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp index fd9aa78d4f4..b75d1286422 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp @@ -45,7 +45,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation { InitializeComponent(); - INITIALIZE_BINDABLE_ENUM_SETTING(Theme, ElementTheme, winrt::Windows::UI::Xaml::ElementTheme, L"Globals_Theme", L"Content"); + // INITIALIZE_BINDABLE_ENUM_SETTING(Theme, ElementTheme, winrt::Windows::UI::Xaml::ElementTheme, L"Globals_Theme", L"Content"); INITIALIZE_BINDABLE_ENUM_SETTING(TabWidthMode, TabViewWidthMode, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, L"Globals_TabWidthMode", L"Content"); } diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.h b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.h index 7e48178baf4..dd08096dcc0 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.h +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.h @@ -26,7 +26,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation void OnNavigatedTo(const winrt::Windows::UI::Xaml::Navigation::NavigationEventArgs& e); WINRT_PROPERTY(Editor::GlobalAppearancePageNavigationState, State, nullptr); - GETSET_BINDABLE_ENUM_SETTING(Theme, winrt::Windows::UI::Xaml::ElementTheme, State().Globals().Theme); + // GETSET_BINDABLE_ENUM_SETTING(Theme, winrt::Windows::UI::Xaml::ElementTheme, State().Globals().Theme().RequestedTheme); GETSET_BINDABLE_ENUM_SETTING(TabWidthMode, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, State().Globals().TabWidthMode); public: diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl index 7e3483140ab..5c3c1e584c4 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl @@ -20,8 +20,8 @@ namespace Microsoft.Terminal.Settings.Editor Windows.Foundation.Collections.IObservableVector LanguageList { get; }; IInspectable CurrentLanguage; - IInspectable CurrentTheme; - Windows.Foundation.Collections.IObservableVector ThemeList { get; }; + // IInspectable CurrentTheme; + // Windows.Foundation.Collections.IObservableVector ThemeList { get; }; IInspectable CurrentTabWidthMode; Windows.Foundation.Collections.IObservableVector TabWidthModeList { get; }; diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml index 2a0bdbcb98a..de57f956ee0 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml @@ -40,13 +40,13 @@ - - + --> From 00c135b4d44cdf5684fa5ce895e9ecf257dc1b8d Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 24 Mar 2022 10:15:12 -0500 Subject: [PATCH 03/61] on reload, this changes the BG of the titlebar, but not the tab view --- src/cascadia/TerminalApp/App.xaml | 1 + src/cascadia/TerminalApp/AppLogic.cpp | 11 +++++++ src/cascadia/TerminalApp/AppLogic.h | 2 ++ src/cascadia/TerminalApp/AppLogic.idl | 2 ++ src/cascadia/TerminalApp/TerminalPage.cpp | 11 +++++++ .../GlobalAppearance.idl | 1 + .../GlobalAppearance.xaml | 2 +- .../TerminalSettingsModel/MTSMSettings.h | 3 +- .../TerminalSettingsSerializationHelpers.h | 30 +++++++++++++++++++ src/cascadia/TerminalSettingsModel/Theme.cpp | 10 +++++++ src/cascadia/TerminalSettingsModel/Theme.h | 13 ++++++++ src/cascadia/TerminalSettingsModel/Theme.idl | 16 ++++++++-- src/cascadia/WindowsTerminal/AppHost.cpp | 15 ++++++++++ .../WindowsTerminal/NonClientIslandWindow.cpp | 5 ++++ .../WindowsTerminal/NonClientIslandWindow.h | 2 ++ 15 files changed, 120 insertions(+), 4 deletions(-) diff --git a/src/cascadia/TerminalApp/App.xaml b/src/cascadia/TerminalApp/App.xaml index 1aa09e74d21..4a8e72cbe26 100644 --- a/src/cascadia/TerminalApp/App.xaml +++ b/src/cascadia/TerminalApp/App.xaml @@ -95,6 +95,7 @@ + diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index ebdf63a7ef8..05428d645bf 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -1642,4 +1642,15 @@ namespace winrt::TerminalApp::implementation { return _settings.GlobalSettings().ShowTitleInTitlebar(); } + + Microsoft::Terminal::Settings::Model::Theme AppLogic::Theme() + { + if (!_loadedInitialSettings) + { + // Load settings if we haven't already + LoadSettings(); + } + return _settings.GlobalSettings().Theme(); + } + } diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index 582866704b4..3f23fe701c8 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -127,6 +127,8 @@ namespace winrt::TerminalApp::implementation Windows::Foundation::Collections::IMapView GlobalHotkeys(); + Microsoft::Terminal::Settings::Model::Theme Theme(); + // -------------------------------- WinRT Events --------------------------------- TYPED_EVENT(RequestedThemeChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::ElementTheme); TYPED_EVENT(SettingsChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl index df0f7b3cd47..67953ee9ce0 100644 --- a/src/cascadia/TerminalApp/AppLogic.idl +++ b/src/cascadia/TerminalApp/AppLogic.idl @@ -104,6 +104,8 @@ namespace TerminalApp Boolean GetAlwaysShowNotificationIcon(); Boolean GetShowTitleInTitlebar(); + Microsoft.Terminal.Settings.Model.Theme Theme { get; }; + FindTargetWindowResult FindTargetWindow(String[] args); Windows.Foundation.Collections.IMapView GlobalHotkeys(); diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 4203498e7d0..44e452252e3 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2610,6 +2610,17 @@ namespace winrt::TerminalApp::implementation WUX::Media::Animation::Timeline::AllowDependentAnimations(!_settings.GlobalSettings().DisableAnimations()); _tabRow.ShowElevationShield(IsElevated() && _settings.GlobalSettings().ShowAdminShield()); + + // const auto theme = _settings.GlobalSettings().Theme(); + // if (const auto tabRowBg = theme.TabRowBackground()) + // { + // const auto res = Application::Current().Resources(); + // const auto tabRowBackgroundKey = winrt::box_value(L"TabRowBackground"); + // const til::color backgroundColor = tabRowBg.Color(); + // const auto brush = Media::SolidColorBrush(); + // brush.Color(backgroundColor); + // res.Insert(tabRowBackgroundKey, brush); + // } } // This is a helper to aid in sorting commands by their `Name`s, alphabetically. diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl index 5c3c1e584c4..0361f0451fd 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl @@ -20,6 +20,7 @@ namespace Microsoft.Terminal.Settings.Editor Windows.Foundation.Collections.IObservableVector LanguageList { get; }; IInspectable CurrentLanguage; + // TODO! // IInspectable CurrentTheme; // Windows.Foundation.Collections.IObservableVector ThemeList { get; }; diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml index de57f956ee0..0457fab0fbe 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml @@ -39,7 +39,7 @@ - + + + + + + - + @@ -236,6 +239,9 @@ + + TerminalBackground.idl + @@ -297,6 +303,7 @@ + diff --git a/src/cascadia/TerminalApp/TerminalBackground.cpp b/src/cascadia/TerminalApp/TerminalBackground.cpp new file mode 100644 index 00000000000..c2831c075a1 --- /dev/null +++ b/src/cascadia/TerminalApp/TerminalBackground.cpp @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "TerminalBackground.h" +#include "TerminalBackground.g.cpp" + +using namespace winrt; +using namespace winrt::TerminalApp; +using namespace winrt::Windows::UI::Core; +using namespace winrt::Windows::UI::Xaml; +using namespace winrt::Windows::System; +using namespace winrt::Windows::UI::Text; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Foundation::Collections; +using namespace winrt::Microsoft::Terminal::Settings::Model; + +namespace winrt::TerminalApp::implementation +{ + // TerminalBackground::TerminalBackground() {} +} diff --git a/src/cascadia/TerminalApp/TerminalBackground.h b/src/cascadia/TerminalApp/TerminalBackground.h new file mode 100644 index 00000000000..c08c68676f9 --- /dev/null +++ b/src/cascadia/TerminalApp/TerminalBackground.h @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "TerminalBackground.g.h" + +namespace winrt::TerminalApp::implementation +{ + struct TerminalBackground : TerminalBackgroundT + { + TerminalBackground() = default; + + WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler); + // WINRT_OBSERVABLE_PROPERTY(Windows::UI::Xaml::Media::Brush, Brush, _PropertyChangedHandlers, winrt::Windows::UI::Xaml::Media::SolidColorBrush{ til::color{ 128, 128, 0 } }); + WINRT_OBSERVABLE_PROPERTY(Windows::UI::Xaml::Media::SolidColorBrush, Brush, _PropertyChangedHandlers, winrt::Windows::UI::Xaml::Media::SolidColorBrush{ til::color{ 128, 128, 0 } }); + }; +} + +namespace winrt::TerminalApp::factory_implementation +{ + BASIC_FACTORY(TerminalBackground); +} diff --git a/src/cascadia/TerminalApp/TerminalBackground.idl b/src/cascadia/TerminalApp/TerminalBackground.idl new file mode 100644 index 00000000000..3b300a55646 --- /dev/null +++ b/src/cascadia/TerminalApp/TerminalBackground.idl @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace TerminalApp +{ + [default_interface] runtimeclass TerminalBackground : Windows.UI.Xaml.Data.INotifyPropertyChanged + { + TerminalBackground(); + Windows.UI.Xaml.Media.SolidColorBrush Brush; + } +} diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 23ea5eeb8c1..88005dbeb21 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2629,14 +2629,25 @@ namespace winrt::TerminalApp::implementation // brush.Color(backgroundColor); // res.Insert(tabRowBackgroundKey, brush); - const auto terminalBackgroundBrushKey = winrt::box_value(L"TerminalBackgroundBrush"); - // const auto brush = Media::AcrylicBrush(); - const auto acrylicBrush = Media::AcrylicBrush(); - acrylicBrush.BackgroundSource(Media::AcrylicBackgroundSource::HostBackdrop); - acrylicBrush.FallbackColor(backgroundColor); - acrylicBrush.TintColor(backgroundColor); - acrylicBrush.TintOpacity(0.5); - res.Insert(terminalBackgroundBrushKey, acrylicBrush); + // const auto terminalBackgroundBrushKey = winrt::box_value(L"TerminalBackgroundBrush"); + // // const auto brush = Media::AcrylicBrush(); + // const auto acrylicBrush = Media::AcrylicBrush(); + // acrylicBrush.BackgroundSource(Media::AcrylicBackgroundSource::HostBackdrop); + // acrylicBrush.FallbackColor(backgroundColor); + // acrylicBrush.TintColor(backgroundColor); + // acrylicBrush.TintOpacity(0.5); + // res.Insert(terminalBackgroundBrushKey, acrylicBrush); + + // const auto foo{ res.Lookup(winrt::box_value(L"TerminalBackground")).as() }; + // // const auto terminalBackgroundBrushKey = winrt::box_value(L"TerminalBackgroundBrush"); + // // const auto brush = Media::AcrylicBrush(); + // const auto acrylicBrush = Media::AcrylicBrush(); + // acrylicBrush.BackgroundSource(Media::AcrylicBackgroundSource::HostBackdrop); + // acrylicBrush.FallbackColor(backgroundColor); + // acrylicBrush.TintColor(backgroundColor); + // acrylicBrush.TintOpacity(0.5); + // // res.Insert(terminalBackgroundBrushKey, acrylicBrush); + // foo.Brush(acrylicBrush); } } diff --git a/src/cascadia/TerminalApp/TerminalPage.xaml b/src/cascadia/TerminalApp/TerminalPage.xaml index 5ca8ed25858..f385d31b187 100644 --- a/src/cascadia/TerminalApp/TerminalPage.xaml +++ b/src/cascadia/TerminalApp/TerminalPage.xaml @@ -9,9 +9,19 @@ xmlns:local="using:TerminalApp" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mux="using:Microsoft.UI.Xaml.Controls" - Background="Transparent" + Background="{Binding Source={StaticResource TerminalBackground}}" mc:Ignorable="d"> + + + + + + + + + + diff --git a/src/cascadia/TerminalApp/TitlebarControl.xaml b/src/cascadia/TerminalApp/TitlebarControl.xaml index a55be7585a0..ec3580d14a2 100644 --- a/src/cascadia/TerminalApp/TitlebarControl.xaml +++ b/src/cascadia/TerminalApp/TitlebarControl.xaml @@ -13,9 +13,12 @@ VerticalAlignment="Top" d:DesignHeight="36" d:DesignWidth="400" + Background="#ffff00" SizeChanged="Root_SizeChanged" mc:Ignorable="d"> + + + Color="#00ff00" /> + + - - - - - - - - diff --git a/src/cascadia/TerminalApp/TitlebarControl.xaml b/src/cascadia/TerminalApp/TitlebarControl.xaml index 8a60866fccb..e5eda4f5041 100644 --- a/src/cascadia/TerminalApp/TitlebarControl.xaml +++ b/src/cascadia/TerminalApp/TitlebarControl.xaml @@ -14,11 +14,8 @@ d:DesignHeight="36" d:DesignWidth="400" SizeChanged="Root_SizeChanged" - Style="{ThemeResource TerminalBackgroundStyle}" mc:Ignorable="d"> - - - + Style="{StaticResource ComboBoxSettingStyle}"> + + + + + + + diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h index adebc4156e3..c04a0fec09f 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h @@ -585,20 +585,20 @@ struct ::Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait(); \ - macro(THEME_SETTINGS_FROM_JSON) return *result; \ + macro(THEME_SETTINGS_FROM_JSON); \ + return *result; \ } \ \ bool CanConvert(const Json::Value& json) \ @@ -66,8 +67,11 @@ winrt::Microsoft::Terminal::Settings::Model::ThemeColor ThemeColor::FromTerminal \ Json::Value ToJson(const nameSpace::name& val) \ { \ + if (val == nullptr) \ + return Json::Value::null; \ Json::Value json{ Json::ValueType::objectValue }; \ - macro(THEME_SETTINGS_TO_JSON) return json; \ + macro(THEME_SETTINGS_TO_JSON); \ + return json; \ } \ \ std::string TypeDescription() const \ @@ -99,11 +103,16 @@ winrt::com_ptr Theme::Copy() const { auto theme{ winrt::make_self() }; -#define THEME_SETTINGS_COPY(type, name, jsonKey, ...) \ - theme->_##name = _##name; + theme->_Name = _Name; - MTSM_THEME_SETTINGS(THEME_SETTINGS_COPY) -#undef THEME_SETTINGS_COPY + if (_Window) + { + theme->_Window = *winrt::get_self(_Window)->Copy(); + } + if (_TabRow) + { + theme->_TabRow = *winrt::get_self(_TabRow)->Copy(); + } return theme; } @@ -161,8 +170,10 @@ Json::Value Theme::ToJson() const JsonUtils::SetValueForKey(json, NameKey, _Name); + // Don't serialize anything if the object is null. #define THEME_SETTINGS_TO_JSON(type, name, jsonKey, ...) \ - JsonUtils::SetValueForKey(json, jsonKey, _##name); + if (_##name) \ + JsonUtils::SetValueForKey(json, jsonKey, _##name); MTSM_THEME_SETTINGS(THEME_SETTINGS_TO_JSON) #undef THEME_SETTINGS_TO_JSON From cfb99d9720ba9da65afc3c80f598e9eab1e52de4 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 27 Apr 2022 12:17:50 -0500 Subject: [PATCH 30/61] Change theme with the SUI and actually have it persist --- .../GlobalAppearance.cpp | 29 ++++--------------- 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp index 602307443ae..709f1163fa5 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp @@ -221,34 +221,15 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation winrt::Windows::Foundation::IInspectable GlobalAppearance::CurrentTheme() { - // if (_currentTheme) - // { - // return _currentTheme; - // } - - // // NOTE: PrimaryLanguageOverride throws if this instance is unpackaged. - // auto currentLanguage = _State.Settings().GlobalSettings().CurrentTheme(); - - // _currentLanguage = winrt::box_value(currentLanguage); - // return _currentLanguage; - return _State.Globals().CurrentTheme(); } - void GlobalAppearance::CurrentTheme(const winrt::Windows::Foundation::IInspectable& /*tag*/) + void GlobalAppearance::CurrentTheme(const winrt::Windows::Foundation::IInspectable& tag) { - // _currentLanguage = tag; - - // const auto currentLanguage = winrt::unbox_value(_currentLanguage); - // const auto globals = _State.Globals(); - // if (currentLanguage == systemLanguageTag) - // { - // globals.ClearLanguage(); - // } - // else - // { - // globals.Language(currentLanguage); - // } + if (const auto& theme{ tag.try_as() }) + { + _State.Globals().Theme(theme.Name()); + } } } From a57187b93cb657763e5d2c980a0f0985761da1e8 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 27 Apr 2022 12:33:41 -0500 Subject: [PATCH 31/61] include the themes --- src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp index ccbc0d78477..4002c07a55c 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp @@ -40,6 +40,14 @@ void GlobalAppSettings::_FinalizeInheritance() _colorSchemes.Insert(k, v); } } + + for (const auto& [k, v] : parent->_themes) + { + if (!_themes.HasKey(k)) + { + _themes.Insert(k, v); + } + } } } From b6b9aeaaaa034305def7300a3831bfc7d4ec4e3c Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 27 Apr 2022 13:01:26 -0500 Subject: [PATCH 32/61] Use better display names --- .../TerminalSettingsEditor/GlobalAppearance.cpp | 16 ++++++++++++++++ .../TerminalSettingsEditor/GlobalAppearance.h | 1 + .../TerminalSettingsEditor/GlobalAppearance.idl | 2 +- .../TerminalSettingsEditor/GlobalAppearance.xaml | 2 +- src/cascadia/TerminalSettingsModel/Theme.cpp | 5 +++++ src/cascadia/TerminalSettingsModel/Theme.h | 5 +---- 6 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp index 709f1163fa5..0317250b54b 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp @@ -232,4 +232,20 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation } } + winrt::hstring GlobalAppearance::WellKnownThemeNameConverter(const Model::Theme& theme) + { + if (theme.Name() == L"dark") + { + return RS_(L"Globals_ThemeDark/Content"); + } + if (theme.Name() == L"light") + { + return RS_(L"Globals_ThemeLight/Content"); + } + if (theme.Name() == L"system") + { + return RS_(L"Globals_ThemeSystem/Content"); + } + return theme.Name(); + } } diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.h b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.h index 80299f67cbd..12e3cb63051 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.h +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.h @@ -43,6 +43,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation winrt::Windows::Foundation::IInspectable CurrentTheme(); void CurrentTheme(const winrt::Windows::Foundation::IInspectable& tag); + static winrt::hstring WellKnownThemeNameConverter(const Model::Theme& theme); private: winrt::Windows::Foundation::Collections::IObservableVector _languageList; diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl index 11f57814368..2b5381cfdcb 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl @@ -22,7 +22,7 @@ namespace Microsoft.Terminal.Settings.Editor // TODO! IInspectable CurrentTheme; - // Windows.Foundation.Collections.IObservableVector ThemeList { get; }; + static String WellKnownThemeNameConverter(Microsoft.Terminal.Settings.Model.Theme theme); Windows.Foundation.Collections.IObservableVector ThemeList { get; }; IInspectable CurrentTabWidthMode; diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml index b0aaec7650f..dcde5a35cd1 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml @@ -48,7 +48,7 @@ Style="{StaticResource ComboBoxSettingStyle}"> - + diff --git a/src/cascadia/TerminalSettingsModel/Theme.cpp b/src/cascadia/TerminalSettingsModel/Theme.cpp index 704aad41adc..fd774e8f352 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.cpp +++ b/src/cascadia/TerminalSettingsModel/Theme.cpp @@ -180,3 +180,8 @@ Json::Value Theme::ToJson() const return json; } + +winrt::hstring Theme::ToString() +{ + return Name(); +} diff --git a/src/cascadia/TerminalSettingsModel/Theme.h b/src/cascadia/TerminalSettingsModel/Theme.h index b7ba9160778..a21947e64c0 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.h +++ b/src/cascadia/TerminalSettingsModel/Theme.h @@ -78,10 +78,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation com_ptr Copy() const; - hstring ToString() - { - return Name(); - } + hstring ToString(); static com_ptr FromJson(const Json::Value& json); void LayerJson(const Json::Value& json); From e2318b4dad5025b9f9762175a71808b25a0978da Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 27 Apr 2022 14:40:03 -0500 Subject: [PATCH 33/61] This is horrifying --- src/cascadia/TerminalApp/TerminalPage.cpp | 52 ++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 5123397d979..263cc0d5386 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -3843,10 +3843,60 @@ namespace winrt::TerminalApp::implementation return; } const auto theme = _settings.GlobalSettings().CurrentTheme(); + auto requestedTheme{ theme.Window().RequestedTheme() }; const auto res = Application::Current().Resources(); + + 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 + 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); + }; + const auto tabViewBackgroundKey = winrt::box_value(L"TabViewBackground"); - const auto backgroundSolidBrush = res.Lookup(tabViewBackgroundKey).as(); + + // Horrifying: 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. + // + // Use our helper to lookup the theme-aware version of the resource. + const auto backgroundSolidBrush = lookup(res, requestedTheme, tabViewBackgroundKey).as(); til::color bgColor = backgroundSolidBrush.Color(); From bc8bb8eb156945517046a2c487219b928cc4c175 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 27 Apr 2022 16:05:06 -0500 Subject: [PATCH 34/61] more comments --- src/cascadia/TerminalApp/TerminalPage.cpp | 29 ++++++++++++------- .../GlobalAppearance.cpp | 21 ++++++++++---- .../GlobalAppearance.idl | 1 - .../GlobalAppearance.xaml | 2 +- 4 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 263cc0d5386..959c37ed4ea 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -3842,12 +3842,24 @@ namespace winrt::TerminalApp::implementation { return; } + const auto theme = _settings.GlobalSettings().CurrentTheme(); auto requestedTheme{ theme.Window().RequestedTheme() }; const auto res = Application::Current().Resources(); - auto lookup = [](auto& res, auto& requestedTheme, auto& key) { + // 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) @@ -3861,7 +3873,10 @@ namespace winrt::TerminalApp::implementation auto requestedThemeKey = requestedTheme == ElementTheme::Dark ? darkKey : lightKey; for (const auto& dictionary : res.MergedDictionaries()) { - // Don't look in the MUX resources + // 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; @@ -3889,13 +3904,8 @@ namespace winrt::TerminalApp::implementation return res.Lookup(key); }; - const auto tabViewBackgroundKey = winrt::box_value(L"TabViewBackground"); - - // Horrifying: 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. - // // 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(); til::color bgColor = backgroundSolidBrush.Color(); @@ -3959,9 +3969,6 @@ namespace winrt::TerminalApp::implementation } break; } - default: - { - } } } else diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp index 0317250b54b..cc6c5065cc4 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp @@ -198,11 +198,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation } // Function Description: - // - Updates the list of all color schemes available to choose from. - // Arguments: - // - - // Return Value: - // - + // - Updates the list of all themes available to choose from. void GlobalAppearance::_UpdateThemeList() { // Surprisingly, though this is called every time we navigate to the page, @@ -224,6 +220,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation return _State.Globals().CurrentTheme(); } + // Get the name out of the newly selected item, stash that as the Theme name + // set for the globals. That controls which theme is actually the current + // theme. void GlobalAppearance::CurrentTheme(const winrt::Windows::Foundation::IInspectable& tag) { if (const auto& theme{ tag.try_as() }) @@ -232,6 +231,18 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation } } + // Method Description: + // - Convert the names of the inbox themes to some more descriptive, + // well-known values. If the passed in theme isn't an inbox one, then just + // return its set Name. + // - "light" becomes "Light" + // - "dark" becomes "Dark" + // - "system" becomes "Use Windows theme" + // - These values are all localized based on the app language. + // Arguments: + // - theme: the theme to get the display name for. + // Return Value: + // - the potentially localized name to use for this Theme. winrt::hstring GlobalAppearance::WellKnownThemeNameConverter(const Model::Theme& theme) { if (theme.Name() == L"dark") diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl index 2b5381cfdcb..f8949317320 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.idl @@ -20,7 +20,6 @@ namespace Microsoft.Terminal.Settings.Editor Windows.Foundation.Collections.IObservableVector LanguageList { get; }; IInspectable CurrentLanguage; - // TODO! IInspectable CurrentTheme; static String WellKnownThemeNameConverter(Microsoft.Terminal.Settings.Model.Theme theme); Windows.Foundation.Collections.IObservableVector ThemeList { get; }; diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml index dcde5a35cd1..537676fe32c 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml @@ -40,7 +40,7 @@ - + Date: Wed, 27 Apr 2022 16:38:49 -0500 Subject: [PATCH 35/61] cleanup for the review --- .../TerminalApp/TerminalAppLib.vcxproj | 7 --- .../TerminalApp/TerminalBackground.cpp | 21 -------- src/cascadia/TerminalApp/TerminalBackground.h | 23 -------- .../TerminalApp/TerminalBackground.idl | 11 ---- src/cascadia/TerminalControl/TermControl.cpp | 1 - .../CascadiaSettingsSerialization.cpp | 3 +- .../GlobalAppSettings.cpp | 6 --- .../TerminalSettingsModel/GlobalAppSettings.h | 2 +- src/cascadia/WindowsTerminal/AppHost.cpp | 1 - src/cascadia/WindowsTerminal/IslandWindow.cpp | 10 +--- .../WindowsTerminal/NonClientIslandWindow.cpp | 52 +++++++++---------- 11 files changed, 30 insertions(+), 107 deletions(-) delete mode 100644 src/cascadia/TerminalApp/TerminalBackground.cpp delete mode 100644 src/cascadia/TerminalApp/TerminalBackground.h delete mode 100644 src/cascadia/TerminalApp/TerminalBackground.idl diff --git a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj index 10544ca5fac..fbf1e051fd5 100644 --- a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj +++ b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj @@ -146,9 +146,6 @@ AppLogic.idl - - TerminalBackground.idl - @@ -243,9 +240,6 @@ - - TerminalBackground.idl - @@ -307,7 +301,6 @@ - diff --git a/src/cascadia/TerminalApp/TerminalBackground.cpp b/src/cascadia/TerminalApp/TerminalBackground.cpp deleted file mode 100644 index c2831c075a1..00000000000 --- a/src/cascadia/TerminalApp/TerminalBackground.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#include "pch.h" -#include "TerminalBackground.h" -#include "TerminalBackground.g.cpp" - -using namespace winrt; -using namespace winrt::TerminalApp; -using namespace winrt::Windows::UI::Core; -using namespace winrt::Windows::UI::Xaml; -using namespace winrt::Windows::System; -using namespace winrt::Windows::UI::Text; -using namespace winrt::Windows::Foundation; -using namespace winrt::Windows::Foundation::Collections; -using namespace winrt::Microsoft::Terminal::Settings::Model; - -namespace winrt::TerminalApp::implementation -{ - // TerminalBackground::TerminalBackground() {} -} diff --git a/src/cascadia/TerminalApp/TerminalBackground.h b/src/cascadia/TerminalApp/TerminalBackground.h deleted file mode 100644 index c08c68676f9..00000000000 --- a/src/cascadia/TerminalApp/TerminalBackground.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#pragma once - -#include "TerminalBackground.g.h" - -namespace winrt::TerminalApp::implementation -{ - struct TerminalBackground : TerminalBackgroundT - { - TerminalBackground() = default; - - WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler); - // WINRT_OBSERVABLE_PROPERTY(Windows::UI::Xaml::Media::Brush, Brush, _PropertyChangedHandlers, winrt::Windows::UI::Xaml::Media::SolidColorBrush{ til::color{ 128, 128, 0 } }); - WINRT_OBSERVABLE_PROPERTY(Windows::UI::Xaml::Media::SolidColorBrush, Brush, _PropertyChangedHandlers, winrt::Windows::UI::Xaml::Media::SolidColorBrush{ til::color{ 128, 128, 0 } }); - }; -} - -namespace winrt::TerminalApp::factory_implementation -{ - BASIC_FACTORY(TerminalBackground); -} diff --git a/src/cascadia/TerminalApp/TerminalBackground.idl b/src/cascadia/TerminalApp/TerminalBackground.idl deleted file mode 100644 index 3b300a55646..00000000000 --- a/src/cascadia/TerminalApp/TerminalBackground.idl +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -namespace TerminalApp -{ - [default_interface] runtimeclass TerminalBackground : Windows.UI.Xaml.Data.INotifyPropertyChanged - { - TerminalBackground(); - Windows.UI.Xaml.Media.SolidColorBrush Brush; - } -} diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index f6e81c0902e..adf645e9fa2 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -548,7 +548,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation } else if (auto solidColor = RootGrid().Background().try_as()) { - const auto originalOpacity = solidColor.Opacity(); solidColor.Color(bg); } } diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp index 10e22efdc28..c8b7c952cf8 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp @@ -1074,10 +1074,11 @@ Json::Value CascadiaSettings::ToJson() const } json[JsonKey(SchemesKey)] = schemes; - // Json::Value themes{ Json::ValueType::arrayValue }; for (const auto& entry : _globals->Themes()) { + // Ignore the built in themes, when serializing the themes back out. We + // don't want to re-include them in the user settings file. const auto theme{ winrt::get_self(entry.Value()) }; if (theme->Name() == L"system" || theme->Name() == L"light" || theme->Name() == L"dark") { diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp index 4002c07a55c..a038932225d 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp @@ -157,11 +157,6 @@ void GlobalAppSettings::LayerJson(const Json::Value& json) _keybindingsWarnings.insert(_keybindingsWarnings.end(), warnings.begin(), warnings.end()); } } - - // if (auto themeJson{ json[JsonKey(ThemeKey)] }) - // { - // _theme->LayerJson(themeJson); - // } } // Method Description: @@ -218,7 +213,6 @@ Json::Value GlobalAppSettings::ToJson() const winrt::Microsoft::Terminal::Settings::Model::Theme GlobalAppSettings::CurrentTheme() noexcept { return _themes.HasKey(Theme()) ? _themes.Lookup(Theme()) : nullptr; - // return *_theme; } void GlobalAppSettings::AddTheme(const Model::Theme& theme) { diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h index ea1dcf71656..3c876c75d3f 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h @@ -83,7 +83,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation winrt::guid _defaultProfile; winrt::com_ptr _actionMap{ winrt::make_self() }; - // winrt::com_ptr _theme{ winrt::make_self() }; + std::vector _keybindingsWarnings; Windows::Foundation::Collections::IMap _colorSchemes{ winrt::single_threaded_map() }; Windows::Foundation::Collections::IMap _themes{ winrt::single_threaded_map() }; diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index b4d69f119d5..e4e49b7f999 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -707,7 +707,6 @@ void AppHost::_UpdateTitleBarContent(const winrt::Windows::Foundation::IInspecta void AppHost::_UpdateTheme(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::UI::Xaml::ElementTheme& /*arg*/) { _updateTheme(); - // _window->OnApplicationThemeChanged(arg); } void AppHost::_FocusModeChanged(const winrt::Windows::Foundation::IInspectable&, diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index db6d0481639..6d832e39710 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -77,7 +77,7 @@ void IslandWindow::MakeWindow() noexcept WINRT_VERIFY(CreateWindowEx(WS_EX_NOREDIRECTIONBITMAP | (_alwaysOnTop ? WS_EX_TOPMOST : 0), wc.lpszClassName, L"Windows Terminal", - WS_OVERLAPPEDWINDOW, // WS_OVERLAPPEDWINDOW, + WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, @@ -87,14 +87,6 @@ void IslandWindow::MakeWindow() noexcept wc.hInstance, this)); - // WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) - - // WS_OVERLAPPED | WS_SYSMENU | WS_THICKFRAME didn't work: still had titlebar - // WS_SYSMENU | WS_THICKFRAME: still a border - // WS_BORDER: No close button, but still a titlebar - // WS_POPUP: No titlebar! but also no window border at all. Fooey. - // WS_POPUP | WS_BORDER: did not add titlebar back. - WINRT_ASSERT(_window); } diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp index a5bf8817b2f..d1a9ac0b85b 100644 --- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp @@ -858,32 +858,32 @@ void NonClientIslandWindow::_UpdateFrameMargins() const noexcept // vintage opacity set. // // We can't set it to all 0's unfortunately. - // if (_borderless) - // { - margins.cyTopHeight = 1; - // } - // else if (_GetTopBorderHeight() != 0) - // { - // RECT frame = {}; - // winrt::check_bool(::AdjustWindowRectExForDpi(&frame, GetWindowStyle(_window.get()), FALSE, 0, _currentDpi)); - - // // We removed the whole top part of the frame (see handling of - // // WM_NCCALCSIZE) so the top border is missing now. We add it back here. - // // Note #1: You might wonder why we don't remove just the title bar instead - // // of removing the whole top part of the frame and then adding the little - // // top border back. I tried to do this but it didn't work: DWM drew the - // // whole title bar anyways on top of the window. It seems that DWM only - // // wants to draw either nothing or the whole top part of the frame. - // // Note #2: For some reason if you try to set the top margin to just the - // // top border height (what we want to do), then there is a transparency - // // bug when the window is inactive, so I've decided to add the whole top - // // part of the frame instead and then we will hide everything that we - // // don't need (that is, the whole thing but the little 1 pixel wide border - // // at the top) in the WM_PAINT handler. This eliminates the transparency - // // bug and it's what a lot of Win32 apps that customize the title bar do - // // so it should work fine. - // margins.cyTopHeight = -frame.top; - // } + if (_borderless) + { + margins.cyTopHeight = 1; + } + else if (_GetTopBorderHeight() != 0) + { + RECT frame = {}; + winrt::check_bool(::AdjustWindowRectExForDpi(&frame, GetWindowStyle(_window.get()), FALSE, 0, _currentDpi)); + + // We removed the whole top part of the frame (see handling of + // WM_NCCALCSIZE) so the top border is missing now. We add it back here. + // Note #1: You might wonder why we don't remove just the title bar instead + // of removing the whole top part of the frame and then adding the little + // top border back. I tried to do this but it didn't work: DWM drew the + // whole title bar anyways on top of the window. It seems that DWM only + // wants to draw either nothing or the whole top part of the frame. + // Note #2: For some reason if you try to set the top margin to just the + // top border height (what we want to do), then there is a transparency + // bug when the window is inactive, so I've decided to add the whole top + // part of the frame instead and then we will hide everything that we + // don't need (that is, the whole thing but the little 1 pixel wide border + // at the top) in the WM_PAINT handler. This eliminates the transparency + // bug and it's what a lot of Win32 apps that customize the title bar do + // so it should work fine. + margins.cyTopHeight = -frame.top; + } // Extend the frame into the client area. microsoft/terminal#2735 - Just log // the failure here, don't crash. If DWM crashes for any reason, calling From a1ea0fdc4f200aceb695696fcbdc71cce681a3ed Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 28 Apr 2022 05:27:00 -0500 Subject: [PATCH 36/61] forgot you --- src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp index cc6c5065cc4..07a9e5fb216 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp @@ -46,7 +46,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation { InitializeComponent(); - // INITIALIZE_BINDABLE_ENUM_SETTING(Theme, ElementTheme, winrt::Windows::UI::Xaml::ElementTheme, L"Globals_Theme", L"Content"); INITIALIZE_BINDABLE_ENUM_SETTING(TabWidthMode, TabViewWidthMode, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, L"Globals_TabWidthMode", L"Content"); } From 9b9a6440b52e8c18fdbd5ebba395218742becf42 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 28 Apr 2022 05:29:27 -0500 Subject: [PATCH 37/61] spell --- .github/actions/spelling/allow/apis.txt | 4 ++++ src/cascadia/WindowsTerminal/AppHost.cpp | 10 +++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/actions/spelling/allow/apis.txt b/.github/actions/spelling/allow/apis.txt index 682023fd96c..32efee53f55 100644 --- a/.github/actions/spelling/allow/apis.txt +++ b/.github/actions/spelling/allow/apis.txt @@ -30,6 +30,7 @@ DERR dlldata DONTADDTORECENT DWORDLONG +DWMSBT endfor enumset environstrings @@ -95,6 +96,7 @@ lround Lsa lsass LSHIFT +MAINWINDOW memchr memicmp MENUCOMMAND @@ -175,6 +177,8 @@ Stubless Subheader Subpage syscall +SYSTEMBACKDROP +TABROW TASKBARCREATED TBPF THEMECHANGED diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index e4e49b7f999..23f8ffafd50 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -688,9 +688,9 @@ void AppHost::_UpdateTitleBarContent(const winrt::Windows::Foundation::IInspecta { if (_useNonClientArea) { - auto nciw{ static_cast(_window.get()) }; - nciw->SetTitlebarContent(arg); - nciw->SetTitlebarBackground(_logic.TitlebarBrush()); + auto nonClientWindow{ static_cast(_window.get()) }; + nonClientWindow->SetTitlebarContent(arg); + nonClientWindow->SetTitlebarBackground(_logic.TitlebarBrush()); } _updateTheme(); @@ -1589,7 +1589,7 @@ void AppHost::_PropertyChangedHandler(const winrt::Windows::Foundation::IInspect { if (e.PropertyName() == L"TitlebarBrush") { - auto nciw{ static_cast(_window.get()) }; - nciw->SetTitlebarBackground(_logic.TitlebarBrush()); + auto nonClientWindow{ static_cast(_window.get()) }; + nonClientWindow->SetTitlebarBackground(_logic.TitlebarBrush()); } } From 03da3b7cc8ecc8c8be2aff6d322b309aadc6a958 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 28 Apr 2022 05:47:27 -0500 Subject: [PATCH 38/61] runformat --- .../TerminalSettingsSerializationHelpers.h | 4 ++-- src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h index c04a0fec09f..be0b3e0e64e 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h @@ -577,8 +577,8 @@ struct ::Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait Date: Tue, 3 May 2022 12:04:14 -0500 Subject: [PATCH 39/61] this is REALLY janky but seems to work --- src/cascadia/TerminalApp/TerminalPage.cpp | 74 +++++++++++++++++++++-- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index e394a89dbc2..a3e6efa7404 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -3943,6 +3943,54 @@ namespace winrt::TerminalApp::implementation applicationState.DismissedMessages(std::move(messages)); } + static constexpr wchar_t RegKeyDwm[] = L"Software\\Microsoft\\Windows\\DWM"; + static constexpr wchar_t RegKeyColorizationColor[] = L"ColorizationColor"; + static constexpr wchar_t RegKeyColorizationColorBalance[] = L"ColorizationColorBalance"; + + static til::color alphaBlend(const til::color& one, const til::color& two, const float& weight) + { + const float firstWeight = weight; + const float secondWeight = 1 - weight; + return til::color{ + static_cast(one.r * firstWeight + two.r * secondWeight), + static_cast(one.g * firstWeight + two.g * secondWeight), + static_cast(one.b * firstWeight + two.b * secondWeight) + }; + } + + static wil::unique_hkey openDwmRegKey() + { + HKEY hKey{ nullptr }; + if (RegOpenKeyEx(HKEY_CURRENT_USER, RegKeyDwm, 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + return wil::unique_hkey{ hKey }; + } + return nullptr; + } + static DWORD readDwmSubValue(const wil::unique_hkey& dwmRootKey, const wchar_t* key) + { + DWORD val{ 0 }; + DWORD size{ sizeof(val) }; + LOG_IF_FAILED(RegQueryValueExW(dwmRootKey.get(), key, nullptr, nullptr, reinterpret_cast(&val), &size)); + return val; + } + + static std::optional _getAccentColorForTitlebar() + { + auto dwmKey{ openDwmRegKey() }; + if (!dwmKey) + { + return std::nullopt; + } + const til::color regValue = static_cast(readDwmSubValue(dwmKey, RegKeyColorizationColor)); + const til::color colorizationColor{ regValue.b, regValue.g, regValue.r }; + const auto colorBalance{ readDwmSubValue(dwmKey, RegKeyColorizationColorBalance) }; + static const til::color blendWith{ 0xd9, 0xd9, 0xd9 }; + auto blended = alphaBlend(colorizationColor, blendWith, (colorBalance / 100.0f)); + blended; + return colorizationColor; + } + void TerminalPage::_updateTabRowColors() { if (_settings == nullptr) @@ -4036,12 +4084,26 @@ namespace winrt::TerminalApp::implementation { case ThemeColorType::Accent: { - // TODO! These colors are NOT right at all. But none of - // `SystemAccentColor` is, so we gotta figure this out. - auto accentColor = winrt::unbox_value_or(res.Lookup(winrt::box_value(_activated ? - L"SystemAccentColorDark3" : - L"SystemAccentColorDark2")), - backgroundSolidBrush.Color()); + til::color accentColor; + if (const auto accentFromReg{ _getAccentColorForTitlebar() }) + { + accentColor = accentFromReg.value(); + } + else + { + // winrt::unbox_value_or(res.Lookup(winrt::box_value(_activated ? + // L"SystemAccentColorDark3" : + // L"SystemAccentColorDark2")), + accentColor = winrt::unbox_value_or(res.Lookup(winrt::box_value(L"SystemAccentColor")), + backgroundSolidBrush.Color()); + } + + // // TODO! These colors are NOT right at all. But none of + // // `SystemAccentColor` is, so we gotta figure this out. + // auto accentColor = winrt::unbox_value_or(res.Lookup(winrt::box_value(_activated ? + // L"SystemAccentColorDark3" : + // L"SystemAccentColorDark2")), + // backgroundSolidBrush.Color()); const auto accentBrush = Media::SolidColorBrush(); accentBrush.Color(accentColor); bgColor = accentColor; From 99bc963222440545d534f8cface8cf9db34264e2 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 3 May 2022 12:09:44 -0500 Subject: [PATCH 40/61] this is simpler --- src/cascadia/TerminalApp/TerminalPage.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index a3e6efa7404..c638520a636 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -3946,6 +3946,7 @@ namespace winrt::TerminalApp::implementation static constexpr wchar_t RegKeyDwm[] = L"Software\\Microsoft\\Windows\\DWM"; static constexpr wchar_t RegKeyColorizationColor[] = L"ColorizationColor"; static constexpr wchar_t RegKeyColorizationColorBalance[] = L"ColorizationColorBalance"; + static constexpr wchar_t RegKeyAccentColor[] = L"AccentColor"; static til::color alphaBlend(const til::color& one, const til::color& two, const float& weight) { @@ -3982,13 +3983,14 @@ namespace winrt::TerminalApp::implementation { return std::nullopt; } - const til::color regValue = static_cast(readDwmSubValue(dwmKey, RegKeyColorizationColor)); - const til::color colorizationColor{ regValue.b, regValue.g, regValue.r }; - const auto colorBalance{ readDwmSubValue(dwmKey, RegKeyColorizationColorBalance) }; - static const til::color blendWith{ 0xd9, 0xd9, 0xd9 }; - auto blended = alphaBlend(colorizationColor, blendWith, (colorBalance / 100.0f)); - blended; - return colorizationColor; + // const til::color regValue = static_cast(readDwmSubValue(dwmKey, RegKeyColorizationColor)); + // const til::color colorizationColor{ regValue.b, regValue.g, regValue.r }; + // const auto colorBalance{ readDwmSubValue(dwmKey, RegKeyColorizationColorBalance) }; + // static const til::color blendWith{ 0xd9, 0xd9, 0xd9 }; + // auto blended = alphaBlend(colorizationColor, blendWith, (colorBalance / 100.0f)); + // blended; + const til::color accentColor{ static_cast(readDwmSubValue(dwmKey, RegKeyAccentColor)) }; + return accentColor; } void TerminalPage::_updateTabRowColors() From 6c28ba6bf39835c3a84dac46bca459816e2c5b53 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 3 May 2022 15:24:03 -0500 Subject: [PATCH 41/61] make the code a lot cleaner --- src/cascadia/TerminalApp/TerminalPage.cpp | 172 +++++++------------ src/cascadia/TerminalSettingsModel/Theme.cpp | 76 ++++++++ src/cascadia/TerminalSettingsModel/Theme.h | 6 + src/cascadia/TerminalSettingsModel/Theme.idl | 5 + 4 files changed, 150 insertions(+), 109 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index c638520a636..45eaa7b53da 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -3943,56 +3943,6 @@ namespace winrt::TerminalApp::implementation applicationState.DismissedMessages(std::move(messages)); } - static constexpr wchar_t RegKeyDwm[] = L"Software\\Microsoft\\Windows\\DWM"; - static constexpr wchar_t RegKeyColorizationColor[] = L"ColorizationColor"; - static constexpr wchar_t RegKeyColorizationColorBalance[] = L"ColorizationColorBalance"; - static constexpr wchar_t RegKeyAccentColor[] = L"AccentColor"; - - static til::color alphaBlend(const til::color& one, const til::color& two, const float& weight) - { - const float firstWeight = weight; - const float secondWeight = 1 - weight; - return til::color{ - static_cast(one.r * firstWeight + two.r * secondWeight), - static_cast(one.g * firstWeight + two.g * secondWeight), - static_cast(one.b * firstWeight + two.b * secondWeight) - }; - } - - static wil::unique_hkey openDwmRegKey() - { - HKEY hKey{ nullptr }; - if (RegOpenKeyEx(HKEY_CURRENT_USER, RegKeyDwm, 0, KEY_READ, &hKey) == ERROR_SUCCESS) - { - return wil::unique_hkey{ hKey }; - } - return nullptr; - } - static DWORD readDwmSubValue(const wil::unique_hkey& dwmRootKey, const wchar_t* key) - { - DWORD val{ 0 }; - DWORD size{ sizeof(val) }; - LOG_IF_FAILED(RegQueryValueExW(dwmRootKey.get(), key, nullptr, nullptr, reinterpret_cast(&val), &size)); - return val; - } - - static std::optional _getAccentColorForTitlebar() - { - auto dwmKey{ openDwmRegKey() }; - if (!dwmKey) - { - return std::nullopt; - } - // const til::color regValue = static_cast(readDwmSubValue(dwmKey, RegKeyColorizationColor)); - // const til::color colorizationColor{ regValue.b, regValue.g, regValue.r }; - // const auto colorBalance{ readDwmSubValue(dwmKey, RegKeyColorizationColorBalance) }; - // static const til::color blendWith{ 0xd9, 0xd9, 0xd9 }; - // auto blended = alphaBlend(colorizationColor, blendWith, (colorBalance / 100.0f)); - // blended; - const til::color accentColor{ static_cast(readDwmSubValue(dwmKey, RegKeyAccentColor)) }; - return accentColor; - } - void TerminalPage::_updateTabRowColors() { if (_settings == nullptr) @@ -4082,65 +4032,69 @@ namespace winrt::TerminalApp::implementation else if (theme.TabRow() && theme.TabRow().Background()) { const auto tabRowBg = theme.TabRow().Background(); - switch (tabRowBg.ColorType()) - { - case ThemeColorType::Accent: - { - til::color accentColor; - if (const auto accentFromReg{ _getAccentColorForTitlebar() }) - { - accentColor = accentFromReg.value(); - } - else - { - // winrt::unbox_value_or(res.Lookup(winrt::box_value(_activated ? - // L"SystemAccentColorDark3" : - // L"SystemAccentColorDark2")), - accentColor = winrt::unbox_value_or(res.Lookup(winrt::box_value(L"SystemAccentColor")), - backgroundSolidBrush.Color()); - } - - // // TODO! These colors are NOT right at all. But none of - // // `SystemAccentColor` is, so we gotta figure this out. - // auto accentColor = winrt::unbox_value_or(res.Lookup(winrt::box_value(_activated ? - // L"SystemAccentColorDark3" : - // L"SystemAccentColorDark2")), - // backgroundSolidBrush.Color()); - const auto accentBrush = Media::SolidColorBrush(); - accentBrush.Color(accentColor); - bgColor = accentColor; - - TitlebarBrush(accentBrush); - break; - } - case ThemeColorType::Color: - { - const til::color backgroundColor = tabRowBg.Color(); - const auto solidBrush = Media::SolidColorBrush(); - solidBrush.Color(backgroundColor); - bgColor = backgroundColor; - TitlebarBrush(solidBrush); - break; - } - case ThemeColorType::TerminalBackground: - { - if (const auto termControl{ _GetActiveControl() }) - { - const auto& brush{ termControl.BackgroundBrush() }; - if (auto acrylic = brush.try_as()) - { - bgColor = acrylic.TintColor(); - } - else if (auto solidColor = brush.try_as()) - { - bgColor = solidColor.Color(); - } - - TitlebarBrush(brush); - } - break; - } - } + const auto terminalBrush = [this]() -> Media::Brush { if(const auto& control{_GetActiveControl()}){ return control.BackgroundBrush(); } return nullptr; }(); + const auto themeBrush{ tabRowBg.Evaluate(res, terminalBrush, true) }; + bgColor = ThemeColor::ColorFromBrush(themeBrush); + TitlebarBrush(themeBrush); + // switch (tabRowBg.ColorType()) + // { + // case ThemeColorType::Accent: + // { + // til::color accentColor; + // if (const auto accentFromReg{ _getAccentColorForTitlebar() }) + // { + // accentColor = accentFromReg.value(); + // } + // else + // { + // // winrt::unbox_value_or(res.Lookup(winrt::box_value(_activated ? + // // L"SystemAccentColorDark3" : + // // L"SystemAccentColorDark2")), + // accentColor = winrt::unbox_value_or(res.Lookup(winrt::box_value(L"SystemAccentColor")), + // backgroundSolidBrush.Color()); + // } + + // // // TODO! These colors are NOT right at all. But none of + // // // `SystemAccentColor` is, so we gotta figure this out. + // // auto accentColor = winrt::unbox_value_or(res.Lookup(winrt::box_value(_activated ? + // // L"SystemAccentColorDark3" : + // // L"SystemAccentColorDark2")), + // // backgroundSolidBrush.Color()); + // const auto accentBrush = Media::SolidColorBrush(); + // accentBrush.Color(accentColor); + // bgColor = accentColor; + + // TitlebarBrush(accentBrush); + // break; + // } + // case ThemeColorType::Color: + // { + // const til::color backgroundColor = tabRowBg.Color(); + // const auto solidBrush = Media::SolidColorBrush(); + // solidBrush.Color(backgroundColor); + // bgColor = backgroundColor; + // TitlebarBrush(solidBrush); + // break; + // } + // case ThemeColorType::TerminalBackground: + // { + // if (const auto termControl{ _GetActiveControl() }) + // { + // const auto& brush{ termControl.BackgroundBrush() }; + // if (auto acrylic = brush.try_as()) + // { + // bgColor = acrylic.TintColor(); + // } + // else if (auto solidColor = brush.try_as()) + // { + // bgColor = solidColor.Color(); + // } + + // TitlebarBrush(brush); + // } + // break; + // } + // } } else { diff --git a/src/cascadia/TerminalSettingsModel/Theme.cpp b/src/cascadia/TerminalSettingsModel/Theme.cpp index fd774e8f352..48fb2c56ec8 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.cpp +++ b/src/cascadia/TerminalSettingsModel/Theme.cpp @@ -21,6 +21,9 @@ using namespace winrt::Windows::UI; static constexpr std::string_view NameKey{ "name" }; +static constexpr wchar_t RegKeyDwm[] = L"Software\\Microsoft\\Windows\\DWM"; +static constexpr wchar_t RegKeyAccentColor[] = L"AccentColor"; + winrt::Microsoft::Terminal::Settings::Model::ThemeColor ThemeColor::FromColor(const winrt::Microsoft::Terminal::Core::Color& coreColor) noexcept { auto result = winrt::make_self(); @@ -43,6 +46,79 @@ winrt::Microsoft::Terminal::Settings::Model::ThemeColor ThemeColor::FromTerminal return *result; } +static wil::unique_hkey openDwmRegKey() +{ + HKEY hKey{ nullptr }; + if (RegOpenKeyEx(HKEY_CURRENT_USER, RegKeyDwm, 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + return wil::unique_hkey{ hKey }; + } + return nullptr; +} +static DWORD readDwmSubValue(const wil::unique_hkey& dwmRootKey, const wchar_t* key) +{ + DWORD val{ 0 }; + DWORD size{ sizeof(val) }; + LOG_IF_FAILED(RegQueryValueExW(dwmRootKey.get(), key, nullptr, nullptr, reinterpret_cast(&val), &size)); + return val; +} + +static til::color _getAccentColorForTitlebar() +{ + return til::color{ static_cast(readDwmSubValue(openDwmRegKey(), RegKeyAccentColor)) }; +} + +til::color ThemeColor::ColorFromBrush(const winrt::Windows::UI::Xaml::Media::Brush& brush) +{ + if (auto acrylic = brush.try_as()) + { + return acrylic.TintColor(); + } + else if (auto solidColor = brush.try_as()) + { + return solidColor.Color(); + } + return {}; +} + +winrt::Windows::UI::Xaml::Media::Brush ThemeColor::Evaluate(const winrt::Windows::UI::Xaml::ResourceDictionary& res, + const winrt::Windows::UI::Xaml::Media::Brush& terminalBackground, + const bool forTitlebar) +{ + static const auto accentColorKey{ winrt::box_value(L"SystemAccentColor") }; + + switch (ColorType()) + { + case ThemeColorType::Accent: + { + til::color accentColor; + if (forTitlebar) + { + accentColor = _getAccentColorForTitlebar(); + } + else + { + accentColor = winrt::unbox_value(res.Lookup(accentColorKey)); + } + + const auto accentBrush = winrt::Windows::UI::Xaml::Media::SolidColorBrush(); + accentBrush.Color(accentColor); + return accentBrush; + } + case ThemeColorType::Color: + { + const auto solidBrush = winrt::Windows::UI::Xaml::Media::SolidColorBrush(); + solidBrush.Color(Color()); + return solidBrush; + } + case ThemeColorType::TerminalBackground: + { + return terminalBackground; + } + } + return nullptr; +} + #define THEME_SETTINGS_FROM_JSON(type, name, jsonKey, ...) \ result->name(JsonUtils::GetValueForKey(json, jsonKey)); diff --git a/src/cascadia/TerminalSettingsModel/Theme.h b/src/cascadia/TerminalSettingsModel/Theme.h index a21947e64c0..624329acb6f 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.h +++ b/src/cascadia/TerminalSettingsModel/Theme.h @@ -36,6 +36,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation static winrt::Microsoft::Terminal::Settings::Model::ThemeColor FromAccent() noexcept; static winrt::Microsoft::Terminal::Settings::Model::ThemeColor FromTerminalBackground() noexcept; + static til::color ColorFromBrush(const winrt::Windows::UI::Xaml::Media::Brush& brush); + + 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); + 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 5bf8d228e36..00406deea34 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.idl +++ b/src/cascadia/TerminalSettingsModel/Theme.idl @@ -20,6 +20,11 @@ namespace Microsoft.Terminal.Settings.Model Microsoft.Terminal.Core.Color Color { get; }; ThemeColorType ColorType; + + static Microsoft.Terminal.Core.Color ColorFromBrush(Windows.UI.Xaml.Media.Brush brush); + Windows.UI.Xaml.Media.Brush Evaluate(Windows.UI.Xaml.ResourceDictionary res, + Windows.UI.Xaml.Media.Brush terminalBackground, + Boolean forTitlebar); } runtimeclass WindowTheme { From 342eb2b64d3324db0ed8f69a640438f6790d14c0 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 4 May 2022 14:59:08 -0500 Subject: [PATCH 42/61] Removes the ability to add Mica in the titlebar, but good enough for v0 --- src/cascadia/TerminalSettingsModel/Theme.cpp | 39 +++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/cascadia/TerminalSettingsModel/Theme.cpp b/src/cascadia/TerminalSettingsModel/Theme.cpp index 48fb2c56ec8..1a9b0566594 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.cpp +++ b/src/cascadia/TerminalSettingsModel/Theme.cpp @@ -87,6 +87,10 @@ winrt::Windows::UI::Xaml::Media::Brush ThemeColor::Evaluate(const winrt::Windows { static const auto accentColorKey{ winrt::box_value(L"SystemAccentColor") }; + // NOTE: Currently, the DWM titlebar is always drawn, underneath our XAML + // content. If the opacity is <1.0, the you'll be able to see it, including + // the original caption buttons, which we don't want. + switch (ColorType()) { case ThemeColorType::Accent: @@ -103,16 +107,49 @@ winrt::Windows::UI::Xaml::Media::Brush ThemeColor::Evaluate(const winrt::Windows const auto accentBrush = winrt::Windows::UI::Xaml::Media::SolidColorBrush(); accentBrush.Color(accentColor); + if (forTitlebar) + { + accentBrush.Opacity(1.0); + } + return accentBrush; } case ThemeColorType::Color: { const auto solidBrush = winrt::Windows::UI::Xaml::Media::SolidColorBrush(); - solidBrush.Color(Color()); + solidBrush.Color(forTitlebar? Color().with_alpha(255) : Color()); + return solidBrush; } case ThemeColorType::TerminalBackground: { + // If we're evaluating this color for the tab row, there are some rulse + // we have to follow, unfortunately. We can't allow a transparent + // background, so we have to make sure to fill that in with Opacity(1.0) + // manually. + // + // So for that case, just make a new brush with the relevant properties + // set. + if (forTitlebar) + { + if (auto acrylic = terminalBackground.try_as()) + { + winrt::Windows::UI::Xaml::Media::AcrylicBrush newBrush{}; + newBrush.TintColor(acrylic.TintColor()); + // Allow acrylic opacity, but it's gotta be HostBackdrop acrylic. + newBrush.TintOpacity(acrylic.TintOpacity()); + acrylic.BackgroundSource(winrt::Windows::UI::Xaml::Media::AcrylicBackgroundSource::HostBackdrop); + return newBrush; + } + else if (auto solidColor = terminalBackground.try_as()) + { + winrt::Windows::UI::Xaml::Media::SolidColorBrush newBrush{}; + newBrush.Color(til::color{ solidColor.Color() }.with_alpha(255)); + newBrush.Opacity(1.0); + return newBrush; + } + } + return terminalBackground; } } From 44319a169038c124f03032cdbc91bb5eb77528f4 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 5 May 2022 13:19:21 -0500 Subject: [PATCH 43/61] Fixes the Settings UI terminalBackground settings --- src/cascadia/TerminalApp/TerminalPage.cpp | 72 ++++------------------- 1 file changed, 12 insertions(+), 60 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index b14ac67a325..6ada07affc5 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -4038,69 +4038,21 @@ namespace winrt::TerminalApp::implementation else if (theme.TabRow() && theme.TabRow().Background()) { const auto tabRowBg = theme.TabRow().Background(); - const auto terminalBrush = [this]() -> Media::Brush { if(const auto& control{_GetActiveControl()}){ return control.BackgroundBrush(); } return nullptr; }(); + const auto terminalBrush = [this]() -> Media::Brush { + if (const auto& control{ _GetActiveControl() }) + { + return control.BackgroundBrush(); + } + else if (auto settingsTab = _GetFocusedTab().try_as()) + { + return settingsTab.Content().try_as().Background(); + } + return nullptr; + }(); + const auto themeBrush{ tabRowBg.Evaluate(res, terminalBrush, true) }; bgColor = ThemeColor::ColorFromBrush(themeBrush); TitlebarBrush(themeBrush); - // switch (tabRowBg.ColorType()) - // { - // case ThemeColorType::Accent: - // { - // til::color accentColor; - // if (const auto accentFromReg{ _getAccentColorForTitlebar() }) - // { - // accentColor = accentFromReg.value(); - // } - // else - // { - // // winrt::unbox_value_or(res.Lookup(winrt::box_value(_activated ? - // // L"SystemAccentColorDark3" : - // // L"SystemAccentColorDark2")), - // accentColor = winrt::unbox_value_or(res.Lookup(winrt::box_value(L"SystemAccentColor")), - // backgroundSolidBrush.Color()); - // } - - // // // TODO! These colors are NOT right at all. But none of - // // // `SystemAccentColor` is, so we gotta figure this out. - // // auto accentColor = winrt::unbox_value_or(res.Lookup(winrt::box_value(_activated ? - // // L"SystemAccentColorDark3" : - // // L"SystemAccentColorDark2")), - // // backgroundSolidBrush.Color()); - // const auto accentBrush = Media::SolidColorBrush(); - // accentBrush.Color(accentColor); - // bgColor = accentColor; - - // TitlebarBrush(accentBrush); - // break; - // } - // case ThemeColorType::Color: - // { - // const til::color backgroundColor = tabRowBg.Color(); - // const auto solidBrush = Media::SolidColorBrush(); - // solidBrush.Color(backgroundColor); - // bgColor = backgroundColor; - // TitlebarBrush(solidBrush); - // break; - // } - // case ThemeColorType::TerminalBackground: - // { - // if (const auto termControl{ _GetActiveControl() }) - // { - // const auto& brush{ termControl.BackgroundBrush() }; - // if (auto acrylic = brush.try_as()) - // { - // bgColor = acrylic.TintColor(); - // } - // else if (auto solidColor = brush.try_as()) - // { - // bgColor = solidColor.Color(); - // } - - // TitlebarBrush(brush); - // } - // break; - // } - // } } else { From d73e450f141ab25a51baed6a6f3077acd53cae72 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 5 May 2022 13:30:42 -0500 Subject: [PATCH 44/61] this fixes the terminalBG + runtime change --- src/cascadia/TerminalControl/TermControl.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index adf645e9fa2..d4c4370d8a9 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -550,6 +550,19 @@ namespace winrt::Microsoft::Terminal::Control::implementation { solidColor.Color(bg); } + + BackgroundBrush(RootGrid().Background()); + + // Don't use the normal BackgroundBrush() Observable Property setter + // here. The one from the macro will automatically ignore changes where + // the value doesn't _actually_ change. In our case, most of the time + // when changing the colors of the background, the _Brush_ itself + // doesn't change, we simply change the Color() of the brush. This + // results in the event not getting bubbled up. + // + // Firing it manually makes sure it does. + _BackgroundBrush = RootGrid().Background(); + _PropertyChangedHandlers(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"BackgroundBrush" }); } // Method Description: From e52b7a9c2be1c95a871e15435a1dcb3d9daa6c31 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 5 May 2022 14:14:02 -0500 Subject: [PATCH 45/61] well, this was part of it... --- src/cascadia/TerminalApp/TerminalPage.cpp | 5 ++++- src/cascadia/TerminalSettingsModel/Theme.cpp | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 6ada07affc5..164693b0dda 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -4060,7 +4060,10 @@ namespace winrt::TerminalApp::implementation TitlebarBrush(backgroundSolidBrush); } - _tabRow.Background(TitlebarBrush()); + if (!_settings.GlobalSettings().ShowTabsInTitlebar()) + { + _tabRow.Background(TitlebarBrush()); + } // 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 diff --git a/src/cascadia/TerminalSettingsModel/Theme.cpp b/src/cascadia/TerminalSettingsModel/Theme.cpp index 1a9b0566594..f0cdf10cca1 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.cpp +++ b/src/cascadia/TerminalSettingsModel/Theme.cpp @@ -136,6 +136,9 @@ winrt::Windows::UI::Xaml::Media::Brush ThemeColor::Evaluate(const winrt::Windows { winrt::Windows::UI::Xaml::Media::AcrylicBrush newBrush{}; newBrush.TintColor(acrylic.TintColor()); + newBrush.FallbackColor(acrylic.FallbackColor()); + newBrush.TintLuminosityOpacity(acrylic.TintLuminosityOpacity()); + newBrush.Opacity(acrylic.Opacity()); // Allow acrylic opacity, but it's gotta be HostBackdrop acrylic. newBrush.TintOpacity(acrylic.TintOpacity()); acrylic.BackgroundSource(winrt::Windows::UI::Xaml::Media::AcrylicBackgroundSource::HostBackdrop); From 3af471a93a51f9b46352f912fedd9265ef6e3daa Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 5 May 2022 18:06:00 -0500 Subject: [PATCH 46/61] derp --- src/cascadia/TerminalSettingsModel/Theme.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalSettingsModel/Theme.cpp b/src/cascadia/TerminalSettingsModel/Theme.cpp index f0cdf10cca1..26da3b84ceb 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.cpp +++ b/src/cascadia/TerminalSettingsModel/Theme.cpp @@ -141,7 +141,7 @@ winrt::Windows::UI::Xaml::Media::Brush ThemeColor::Evaluate(const winrt::Windows newBrush.Opacity(acrylic.Opacity()); // Allow acrylic opacity, but it's gotta be HostBackdrop acrylic. newBrush.TintOpacity(acrylic.TintOpacity()); - acrylic.BackgroundSource(winrt::Windows::UI::Xaml::Media::AcrylicBackgroundSource::HostBackdrop); + newBrush.BackgroundSource(winrt::Windows::UI::Xaml::Media::AcrylicBackgroundSource::HostBackdrop); return newBrush; } else if (auto solidColor = terminalBackground.try_as()) From b2abca6027eab51816d683c1acc1e113d999e08b Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 6 May 2022 06:44:45 -0500 Subject: [PATCH 47/61] Add comments --- src/cascadia/TerminalSettingsModel/Theme.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/cascadia/TerminalSettingsModel/Theme.cpp b/src/cascadia/TerminalSettingsModel/Theme.cpp index 26da3b84ceb..b2b90bab30c 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.cpp +++ b/src/cascadia/TerminalSettingsModel/Theme.cpp @@ -65,6 +65,8 @@ static DWORD readDwmSubValue(const wil::unique_hkey& dwmRootKey, const wchar_t* static til::color _getAccentColorForTitlebar() { + // The color used for the "Use Accent color in the title bar" in DWM is + // stored in HKCU\Software\Microsoft\Windows\DWM\AccentColor. return til::color{ static_cast(readDwmSubValue(openDwmRegKey(), RegKeyAccentColor)) }; } @@ -117,7 +119,7 @@ winrt::Windows::UI::Xaml::Media::Brush ThemeColor::Evaluate(const winrt::Windows case ThemeColorType::Color: { const auto solidBrush = winrt::Windows::UI::Xaml::Media::SolidColorBrush(); - solidBrush.Color(forTitlebar? Color().with_alpha(255) : Color()); + solidBrush.Color(forTitlebar ? Color().with_alpha(255) : Color()); return solidBrush; } @@ -138,9 +140,19 @@ winrt::Windows::UI::Xaml::Media::Brush ThemeColor::Evaluate(const winrt::Windows newBrush.TintColor(acrylic.TintColor()); newBrush.FallbackColor(acrylic.FallbackColor()); newBrush.TintLuminosityOpacity(acrylic.TintLuminosityOpacity()); - newBrush.Opacity(acrylic.Opacity()); + // Allow acrylic opacity, but it's gotta be HostBackdrop acrylic. - newBrush.TintOpacity(acrylic.TintOpacity()); + // + // For now, just always use 50% opacity for this. If we do ever + // figure out how to get rid of our titlebar under the XAML tab + // row (GH#10509), we can always get rid of the HostBackdrop + // thing, and all this copying, and just return the + // terminalBackground brush directly. + // + // Because we're wholesale copying the brush, we won't be able + // to adjust it's opacity with the mouse wheel. This seems like + // an acceptable tradeoff for now. + newBrush.TintOpacity(.5); newBrush.BackgroundSource(winrt::Windows::UI::Xaml::Media::AcrylicBackgroundSource::HostBackdrop); return newBrush; } @@ -148,7 +160,6 @@ winrt::Windows::UI::Xaml::Media::Brush ThemeColor::Evaluate(const winrt::Windows { winrt::Windows::UI::Xaml::Media::SolidColorBrush newBrush{}; newBrush.Color(til::color{ solidColor.Color() }.with_alpha(255)); - newBrush.Opacity(1.0); return newBrush; } } From ebe80cda36ea842e233e20d6f42587343148bec0 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 6 May 2022 09:49:22 -0500 Subject: [PATCH 48/61] Try to implement unfocusedBackground, find all sorts of serialization bugs --- src/cascadia/TerminalApp/TerminalPage.cpp | 43 +++++++++++-------- .../TerminalSettingsModel/MTSMSettings.h | 5 ++- src/cascadia/TerminalSettingsModel/Theme.idl | 1 + 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 164693b0dda..33d16231328 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -4023,6 +4023,7 @@ namespace winrt::TerminalApp::implementation til::color bgColor = backgroundSolidBrush.Color(); + bool setBG = false; if (_settings.GlobalSettings().UseAcrylicInTabRow()) { const til::color backgroundColor = backgroundSolidBrush.Color(); @@ -4034,27 +4035,35 @@ namespace winrt::TerminalApp::implementation TitlebarBrush(acrylicBrush); bgColor = backgroundColor; + + setBG = true; } - else if (theme.TabRow() && theme.TabRow().Background()) + else if (theme.TabRow()) { - const auto tabRowBg = theme.TabRow().Background(); - const auto terminalBrush = [this]() -> Media::Brush { - if (const auto& control{ _GetActiveControl() }) - { - return control.BackgroundBrush(); - } - else if (auto settingsTab = _GetFocusedTab().try_as()) - { - return settingsTab.Content().try_as().Background(); - } - return nullptr; - }(); + if (const auto tabRowBg{ _activated ? theme.TabRow().Background() : + theme.TabRow().UnfocusedBackground() }) + { + const auto terminalBrush = [this]() -> Media::Brush { + if (const auto& control{ _GetActiveControl() }) + { + return control.BackgroundBrush(); + } + else if (auto settingsTab = _GetFocusedTab().try_as()) + { + return settingsTab.Content().try_as().Background(); + } + return nullptr; + }(); + + const auto themeBrush{ tabRowBg.Evaluate(res, terminalBrush, true) }; + bgColor = ThemeColor::ColorFromBrush(themeBrush); + TitlebarBrush(themeBrush); - const auto themeBrush{ tabRowBg.Evaluate(res, terminalBrush, true) }; - bgColor = ThemeColor::ColorFromBrush(themeBrush); - TitlebarBrush(themeBrush); + setBG = true; + } } - else + + if (!setBG) { // Nothing was set in the theme - fall back to our original `TabViewBackground` color. TitlebarBrush(backgroundSolidBrush); diff --git a/src/cascadia/TerminalSettingsModel/MTSMSettings.h b/src/cascadia/TerminalSettingsModel/MTSMSettings.h index 91dda758e3d..37b21b750a4 100644 --- a/src/cascadia/TerminalSettingsModel/MTSMSettings.h +++ b/src/cascadia/TerminalSettingsModel/MTSMSettings.h @@ -121,5 +121,6 @@ Author(s): X(winrt::Windows::UI::Xaml::ElementTheme, RequestedTheme, "applicationTheme", winrt::Windows::UI::Xaml::ElementTheme::Default) \ X(bool, UseMica, "useMica", false) -#define MTSM_THEME_TABROW_SETTINGS(X) \ - X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, Background, "background", nullptr) +#define MTSM_THEME_TABROW_SETTINGS(X) \ + X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, Background, "background", nullptr) \ + X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, UnfocusedBackground, "unfocusedBackground", nullptr) diff --git a/src/cascadia/TerminalSettingsModel/Theme.idl b/src/cascadia/TerminalSettingsModel/Theme.idl index 00406deea34..6e05cde3010 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.idl +++ b/src/cascadia/TerminalSettingsModel/Theme.idl @@ -34,6 +34,7 @@ namespace Microsoft.Terminal.Settings.Model runtimeclass TabRowTheme { ThemeColor Background { get; }; + ThemeColor UnfocusedBackground { get; }; } [default_interface] runtimeclass Theme : Windows.Foundation.IStringable { From 233f6ddfc243892b166551835d36417524e91f55 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 6 May 2022 09:49:40 -0500 Subject: [PATCH 49/61] Start by just adding a test file --- .../SettingsModel.LocalTests.vcxproj | 1 + .../LocalTests_SettingsModel/ThemeTests.cpp | 259 ++++++++++++++++++ .../GlobalAppearance.cpp | 4 - .../TerminalSettingsSerializationHelpers.h | 13 + 4 files changed, 273 insertions(+), 4 deletions(-) create mode 100644 src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp diff --git a/src/cascadia/LocalTests_SettingsModel/SettingsModel.LocalTests.vcxproj b/src/cascadia/LocalTests_SettingsModel/SettingsModel.LocalTests.vcxproj index 47214270725..76e0f07e293 100644 --- a/src/cascadia/LocalTests_SettingsModel/SettingsModel.LocalTests.vcxproj +++ b/src/cascadia/LocalTests_SettingsModel/SettingsModel.LocalTests.vcxproj @@ -41,6 +41,7 @@ + Create diff --git a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp new file mode 100644 index 00000000000..b425856a660 --- /dev/null +++ b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp @@ -0,0 +1,259 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" + +#include "../TerminalSettingsModel/Theme.h" +#include "../TerminalSettingsModel/CascadiaSettings.h" +#include "../types/inc/colorTable.hpp" +#include "JsonTestClass.h" + +#include + +using namespace Microsoft::Console; +using namespace winrt::Microsoft::Terminal; +using namespace winrt::Microsoft::Terminal::Settings::Model::implementation; +using namespace WEX::Logging; +using namespace WEX::TestExecution; +using namespace WEX::Common; + +namespace SettingsModelLocalTests +{ + // TODO:microsoft/terminal#3838: + // Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for + // an updated TAEF that will let us install framework packages when the test + // package is deployed. Until then, these tests won't deploy in CI. + + class ThemeTests : public JsonTestClass + { + // Use a custom AppxManifest to ensure that we can activate winrt types + // from our test. This property will tell taef to manually use this as + // the AppxManifest for this test class. + // This does not yet work for anything XAML-y. See TabTests.cpp for more + // details on that. + BEGIN_TEST_CLASS(ThemeTests) + TEST_CLASS_PROPERTY(L"RunAs", L"UAP") + TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml") + END_TEST_CLASS() + + TEST_METHOD(ParseSimpleTheme); + TEST_METHOD(ParseThemeWithNullThemeColor); + + // static Core::Color rgb(uint8_t r, uint8_t g, uint8_t b) noexcept + // { + // return Core::Color{ r, g, b, 255 }; + // } + }; + + void ThemeTests::ParseSimpleTheme() + { + static constexpr std::string_view orangeTheme{ R"({ + "name": "orange", + "tabRow": + { + "background": "#FFFF8800", + "unfocusedBackground": "#FF884400" + }, + "window": + { + "applicationTheme": "light", + "useMica": true + } + })" }; + + const auto schemeObject = VerifyParseSucceeded(orangeTheme); + auto theme = Theme::FromJson(schemeObject); + VERIFY_ARE_EQUAL(L"orange", theme->Name()); + // VERIFY_ARE_EQUAL(til::color(0xf2, 0xf2, 0xf2, 255), til::color{ scheme->Foreground() }); + // VERIFY_ARE_EQUAL(til::color(0x0c, 0x0c, 0x0c, 255), til::color{ scheme->Background() }); + // VERIFY_ARE_EQUAL(til::color(0x13, 0x13, 0x13, 255), til::color{ scheme->SelectionBackground() }); + // VERIFY_ARE_EQUAL(til::color(0xFF, 0xFF, 0xFF, 255), til::color{ scheme->CursorColor() }); + + // std::array expectedCampbellTable; + // const auto campbellSpan = gsl::make_span(expectedCampbellTable); + // Utils::InitializeColorTable(campbellSpan); + + // for (size_t i = 0; i < expectedCampbellTable.size(); i++) + // { + // const til::color expected{ expectedCampbellTable.at(i) }; + // const til::color actual{ scheme->Table().at(static_cast(i)) }; + // VERIFY_ARE_EQUAL(expected, actual); + // } + + // Log::Comment(L"Roundtrip Test for Color Scheme"); + // auto outJson{ scheme->ToJson() }; + // VERIFY_ARE_EQUAL(schemeObject, outJson); + } + + // void ColorSchemeTests::LayerColorSchemesOnArray() + // { + // static constexpr std::string_view inboxSettings{ R"({ + // "schemes": [ + // { + // "background": "#0C0C0C", + // "black": "#0C0C0C", + // "blue": "#0037DA", + // "brightBlack": "#767676", + // "brightBlue": "#3B78FF", + // "brightCyan": "#61D6D6", + // "brightGreen": "#16C60C", + // "brightPurple": "#B4009E", + // "brightRed": "#E74856", + // "brightWhite": "#F2F2F2", + // "brightYellow": "#F9F1A5", + // "cursorColor": "#FFFFFF", + // "cyan": "#3A96DD", + // "foreground": "#CCCCCC", + // "green": "#13A10E", + // "name": "Campbell", + // "purple": "#881798", + // "red": "#C50F1F", + // "selectionBackground": "#FFFFFF", + // "white": "#CCCCCC", + // "yellow": "#C19C00" + // } + // ] + // })" }; + // static constexpr std::string_view userSettings{ R"({ + // "profiles": [ + // { + // "name" : "profile0" + // } + // ], + // "schemes": [ + // { + // "background": "#121314", + // "black": "#121314", + // "blue": "#121314", + // "brightBlack": "#121314", + // "brightBlue": "#121314", + // "brightCyan": "#121314", + // "brightGreen": "#121314", + // "brightPurple": "#121314", + // "brightRed": "#121314", + // "brightWhite": "#121314", + // "brightYellow": "#121314", + // "cursorColor": "#121314", + // "cyan": "#121314", + // "foreground": "#121314", + // "green": "#121314", + // "name": "Campbell", + // "purple": "#121314", + // "red": "#121314", + // "selectionBackground": "#121314", + // "white": "#121314", + // "yellow": "#121314" + // }, + // { + // "background": "#012456", + // "black": "#0C0C0C", + // "blue": "#0037DA", + // "brightBlack": "#767676", + // "brightBlue": "#3B78FF", + // "brightCyan": "#61D6D6", + // "brightGreen": "#16C60C", + // "brightPurple": "#B4009E", + // "brightRed": "#E74856", + // "brightWhite": "#F2F2F2", + // "brightYellow": "#F9F1A5", + // "cursorColor": "#FFFFFF", + // "cyan": "#3A96DD", + // "foreground": "#CCCCCC", + // "green": "#13A10E", + // "name": "Campbell Powershell", + // "purple": "#881798", + // "red": "#C50F1F", + // "selectionBackground": "#FFFFFF", + // "white": "#CCCCCC", + // "yellow": "#C19C00" + // } + // ] + // })" }; + + // const auto settings = winrt::make_self(userSettings, inboxSettings); + + // const auto colorSchemes = settings->GlobalSettings().ColorSchemes(); + // VERIFY_ARE_EQUAL(2u, colorSchemes.Size()); + + // const auto scheme0 = winrt::get_self(colorSchemes.Lookup(L"Campbell")); + // VERIFY_ARE_EQUAL(rgb(0x12, 0x13, 0x14), scheme0->Foreground()); + // VERIFY_ARE_EQUAL(rgb(0x12, 0x13, 0x14), scheme0->Background()); + + // const auto scheme1 = winrt::get_self(colorSchemes.Lookup(L"Campbell Powershell")); + // VERIFY_ARE_EQUAL(rgb(0xCC, 0xCC, 0xCC), scheme1->Foreground()); + // VERIFY_ARE_EQUAL(rgb(0x01, 0x24, 0x56), scheme1->Background()); + // } + + void ThemeTests::ParseThemeWithNullThemeColor() + { + static constexpr std::string_view settingsString{ R"json({ + "themes": [ + { + "name": "backgroundEmpty", + "tabRow": + { + }, + "window": + { + "applicationTheme": "light", + "useMica": true + } + }, + ] + })json" }; + + // { + // "name": "backgroundNull", + // "tabRow": + // { + // "background": null + // }, + // "window": + // { + // "applicationTheme": "light", + // "useMica": true + // } + // }, + // { + // "name": "backgroundOmittedEntirely", + // "window": + // { + // "applicationTheme": "light", + // "useMica": true + // } + // } + + try + { + const auto settings{ winrt::make_self(settingsString, DefaultJson) }; + + const auto& themes{ settings->GlobalSettings().Themes() }; + { + const auto& backgroundEmpty{ themes.Lookup(L"backgroundEmpty") }; + VERIFY_ARE_EQUAL(L"backgroundEmpty", backgroundEmpty.Name()); + } + { + const auto& backgroundNull{ themes.Lookup(L"backgroundNull") }; + VERIFY_ARE_EQUAL(L"backgroundNull", backgroundNull.Name()); + } + { + const auto& backgroundOmittedEntirely{ themes.Lookup(L"backgroundOmittedEntirely") }; + VERIFY_ARE_EQUAL(L"backgroundOmittedEntirely", backgroundOmittedEntirely.Name()); + } + } + catch (const SettingsException& ex) + { + auto loadError = ex.Error(); + loadError; + DebugBreak(); + throw ex; + } + catch (const SettingsTypedDeserializationException& e) + { + auto deserializationErrorMessage = til::u8u16(e.what()); + Log::Comment(NoThrowString().Format(deserializationErrorMessage.c_str())); + DebugBreak(); + throw e; + } + } +} diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp index 07a9e5fb216..69686b51e1d 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp @@ -206,10 +206,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation for (const auto& pair : ThemeMap) { const auto& theme{ pair.Value() }; - const auto& name{ theme.Name() }; - theme; - name; - _ThemeList.Append(theme); } } diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h index be0b3e0e64e..daff9111663 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h @@ -552,6 +552,10 @@ struct ::Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait Date: Fri, 6 May 2022 09:58:17 -0500 Subject: [PATCH 50/61] Fill in more tests --- .../LocalTests_SettingsModel/ThemeTests.cpp | 76 ++++++++----------- 1 file changed, 33 insertions(+), 43 deletions(-) diff --git a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp index b425856a660..fc9e0333f9d 100644 --- a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp +++ b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp @@ -39,10 +39,10 @@ namespace SettingsModelLocalTests TEST_METHOD(ParseSimpleTheme); TEST_METHOD(ParseThemeWithNullThemeColor); - // static Core::Color rgb(uint8_t r, uint8_t g, uint8_t b) noexcept - // { - // return Core::Color{ r, g, b, 255 }; - // } + static Core::Color rgb(uint8_t r, uint8_t g, uint8_t b) noexcept + { + return Core::Color{ r, g, b, 255 }; + } }; void ThemeTests::ParseSimpleTheme() @@ -64,25 +64,11 @@ namespace SettingsModelLocalTests const auto schemeObject = VerifyParseSucceeded(orangeTheme); auto theme = Theme::FromJson(schemeObject); VERIFY_ARE_EQUAL(L"orange", theme->Name()); - // VERIFY_ARE_EQUAL(til::color(0xf2, 0xf2, 0xf2, 255), til::color{ scheme->Foreground() }); - // VERIFY_ARE_EQUAL(til::color(0x0c, 0x0c, 0x0c, 255), til::color{ scheme->Background() }); - // VERIFY_ARE_EQUAL(til::color(0x13, 0x13, 0x13, 255), til::color{ scheme->SelectionBackground() }); - // VERIFY_ARE_EQUAL(til::color(0xFF, 0xFF, 0xFF, 255), til::color{ scheme->CursorColor() }); - - // std::array expectedCampbellTable; - // const auto campbellSpan = gsl::make_span(expectedCampbellTable); - // Utils::InitializeColorTable(campbellSpan); - // for (size_t i = 0; i < expectedCampbellTable.size(); i++) - // { - // const til::color expected{ expectedCampbellTable.at(i) }; - // const til::color actual{ scheme->Table().at(static_cast(i)) }; - // VERIFY_ARE_EQUAL(expected, actual); - // } - - // Log::Comment(L"Roundtrip Test for Color Scheme"); - // auto outJson{ scheme->ToJson() }; - // VERIFY_ARE_EQUAL(schemeObject, outJson); + VERIFY_IS_NOT_NULL(theme->TabRow()); + VERIFY_IS_NOT_NULL(theme->TabRow().Background()); + VERIFY_ARE_EQUAL(Settings::Model::ThemeColorType::Color, theme->TabRow().Background().ColorType()); + VERIFY_ARE_EQUAL(rgb(0xff, 0x88, 0x00), theme->TabRow().Background().Color()); } // void ColorSchemeTests::LayerColorSchemesOnArray() @@ -199,30 +185,29 @@ namespace SettingsModelLocalTests "useMica": true } }, + { + "name": "backgroundNull", + "tabRow": + { + "background": null + }, + "window": + { + "applicationTheme": "light", + "useMica": true + } + }, + { + "name": "backgroundOmittedEntirely", + "window": + { + "applicationTheme": "light", + "useMica": true + } + } ] })json" }; - // { - // "name": "backgroundNull", - // "tabRow": - // { - // "background": null - // }, - // "window": - // { - // "applicationTheme": "light", - // "useMica": true - // } - // }, - // { - // "name": "backgroundOmittedEntirely", - // "window": - // { - // "applicationTheme": "light", - // "useMica": true - // } - // } - try { const auto settings{ winrt::make_self(settingsString, DefaultJson) }; @@ -231,14 +216,19 @@ namespace SettingsModelLocalTests { const auto& backgroundEmpty{ themes.Lookup(L"backgroundEmpty") }; VERIFY_ARE_EQUAL(L"backgroundEmpty", backgroundEmpty.Name()); + VERIFY_IS_NOT_NULL(backgroundEmpty.TabRow()); + VERIFY_IS_NULL(backgroundEmpty.TabRow().Background()); } { const auto& backgroundNull{ themes.Lookup(L"backgroundNull") }; VERIFY_ARE_EQUAL(L"backgroundNull", backgroundNull.Name()); + VERIFY_IS_NOT_NULL(backgroundNull.TabRow()); + VERIFY_IS_NULL(backgroundNull.TabRow().Background()); } { const auto& backgroundOmittedEntirely{ themes.Lookup(L"backgroundOmittedEntirely") }; VERIFY_ARE_EQUAL(L"backgroundOmittedEntirely", backgroundOmittedEntirely.Name()); + VERIFY_IS_NULL(backgroundOmittedEntirely.TabRow()); } } catch (const SettingsException& ex) From b61b0b6b32b5818bdd9b151e68a649c483dfbac3 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 6 May 2022 11:00:29 -0500 Subject: [PATCH 51/61] This is what I was looking for --- .../LocalTests_SettingsModel/ThemeTests.cpp | 99 ------------------- src/cascadia/TerminalSettingsModel/Theme.cpp | 7 +- 2 files changed, 6 insertions(+), 100 deletions(-) diff --git a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp index fc9e0333f9d..5d085922cf5 100644 --- a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp +++ b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp @@ -71,105 +71,6 @@ namespace SettingsModelLocalTests VERIFY_ARE_EQUAL(rgb(0xff, 0x88, 0x00), theme->TabRow().Background().Color()); } - // void ColorSchemeTests::LayerColorSchemesOnArray() - // { - // static constexpr std::string_view inboxSettings{ R"({ - // "schemes": [ - // { - // "background": "#0C0C0C", - // "black": "#0C0C0C", - // "blue": "#0037DA", - // "brightBlack": "#767676", - // "brightBlue": "#3B78FF", - // "brightCyan": "#61D6D6", - // "brightGreen": "#16C60C", - // "brightPurple": "#B4009E", - // "brightRed": "#E74856", - // "brightWhite": "#F2F2F2", - // "brightYellow": "#F9F1A5", - // "cursorColor": "#FFFFFF", - // "cyan": "#3A96DD", - // "foreground": "#CCCCCC", - // "green": "#13A10E", - // "name": "Campbell", - // "purple": "#881798", - // "red": "#C50F1F", - // "selectionBackground": "#FFFFFF", - // "white": "#CCCCCC", - // "yellow": "#C19C00" - // } - // ] - // })" }; - // static constexpr std::string_view userSettings{ R"({ - // "profiles": [ - // { - // "name" : "profile0" - // } - // ], - // "schemes": [ - // { - // "background": "#121314", - // "black": "#121314", - // "blue": "#121314", - // "brightBlack": "#121314", - // "brightBlue": "#121314", - // "brightCyan": "#121314", - // "brightGreen": "#121314", - // "brightPurple": "#121314", - // "brightRed": "#121314", - // "brightWhite": "#121314", - // "brightYellow": "#121314", - // "cursorColor": "#121314", - // "cyan": "#121314", - // "foreground": "#121314", - // "green": "#121314", - // "name": "Campbell", - // "purple": "#121314", - // "red": "#121314", - // "selectionBackground": "#121314", - // "white": "#121314", - // "yellow": "#121314" - // }, - // { - // "background": "#012456", - // "black": "#0C0C0C", - // "blue": "#0037DA", - // "brightBlack": "#767676", - // "brightBlue": "#3B78FF", - // "brightCyan": "#61D6D6", - // "brightGreen": "#16C60C", - // "brightPurple": "#B4009E", - // "brightRed": "#E74856", - // "brightWhite": "#F2F2F2", - // "brightYellow": "#F9F1A5", - // "cursorColor": "#FFFFFF", - // "cyan": "#3A96DD", - // "foreground": "#CCCCCC", - // "green": "#13A10E", - // "name": "Campbell Powershell", - // "purple": "#881798", - // "red": "#C50F1F", - // "selectionBackground": "#FFFFFF", - // "white": "#CCCCCC", - // "yellow": "#C19C00" - // } - // ] - // })" }; - - // const auto settings = winrt::make_self(userSettings, inboxSettings); - - // const auto colorSchemes = settings->GlobalSettings().ColorSchemes(); - // VERIFY_ARE_EQUAL(2u, colorSchemes.Size()); - - // const auto scheme0 = winrt::get_self(colorSchemes.Lookup(L"Campbell")); - // VERIFY_ARE_EQUAL(rgb(0x12, 0x13, 0x14), scheme0->Foreground()); - // VERIFY_ARE_EQUAL(rgb(0x12, 0x13, 0x14), scheme0->Background()); - - // const auto scheme1 = winrt::get_self(colorSchemes.Lookup(L"Campbell Powershell")); - // VERIFY_ARE_EQUAL(rgb(0xCC, 0xCC, 0xCC), scheme1->Foreground()); - // VERIFY_ARE_EQUAL(rgb(0x01, 0x24, 0x56), scheme1->Background()); - // } - void ThemeTests::ParseThemeWithNullThemeColor() { static constexpr std::string_view settingsString{ R"json({ diff --git a/src/cascadia/TerminalSettingsModel/Theme.cpp b/src/cascadia/TerminalSettingsModel/Theme.cpp index b2b90bab30c..b9450db8025 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.cpp +++ b/src/cascadia/TerminalSettingsModel/Theme.cpp @@ -171,7 +171,12 @@ winrt::Windows::UI::Xaml::Media::Brush ThemeColor::Evaluate(const winrt::Windows } #define THEME_SETTINGS_FROM_JSON(type, name, jsonKey, ...) \ - result->name(JsonUtils::GetValueForKey(json, jsonKey)); + { \ + std::optional _val; \ + _val = JsonUtils::GetValueForKey>(json, jsonKey); \ + if (_val) \ + result->name(*_val); \ + } #define THEME_SETTINGS_TO_JSON(type, name, jsonKey, ...) \ JsonUtils::SetValueForKey(json, jsonKey, val.name()); From 8a02e9784ba8bfe99510a70bf8c77e29681fb3d0 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 6 May 2022 12:02:33 -0500 Subject: [PATCH 52/61] Fix having a null window, cause that was actually very possible --- .../LocalTests_SettingsModel/ThemeTests.cpp | 75 +++++++++++++++++++ src/cascadia/TerminalApp/AppLogic.cpp | 6 +- src/cascadia/TerminalApp/TerminalPage.cpp | 4 +- src/cascadia/TerminalSettingsModel/Theme.cpp | 33 ++++++-- src/cascadia/TerminalSettingsModel/Theme.h | 2 + src/cascadia/TerminalSettingsModel/Theme.idl | 3 + src/cascadia/WindowsTerminal/AppHost.cpp | 2 +- 7 files changed, 112 insertions(+), 13 deletions(-) diff --git a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp index 5d085922cf5..2475f2e8d09 100644 --- a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp +++ b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp @@ -37,6 +37,9 @@ namespace SettingsModelLocalTests END_TEST_CLASS() TEST_METHOD(ParseSimpleTheme); + TEST_METHOD(ParseEmptyTheme); + TEST_METHOD(ParseNoWindowTheme); + TEST_METHOD(ParseNullWindowTheme); TEST_METHOD(ParseThemeWithNullThemeColor); static Core::Color rgb(uint8_t r, uint8_t g, uint8_t b) noexcept @@ -69,10 +72,82 @@ namespace SettingsModelLocalTests VERIFY_IS_NOT_NULL(theme->TabRow().Background()); VERIFY_ARE_EQUAL(Settings::Model::ThemeColorType::Color, theme->TabRow().Background().ColorType()); VERIFY_ARE_EQUAL(rgb(0xff, 0x88, 0x00), theme->TabRow().Background().Color()); + + VERIFY_IS_NOT_NULL(theme->Window()); + VERIFY_ARE_EQUAL(winrt::Windows::UI::Xaml::ElementTheme::Light, theme->Window().RequestedTheme()); + VERIFY_ARE_EQUAL(true, theme->Window().UseMica()); + } + + void ThemeTests::ParseEmptyTheme() + { + Log::Comment(L"This theme doesn't have any elements defined."); + static constexpr std::string_view emptyTheme{ R"({ + "name": "empty" + })" }; + + const auto schemeObject = VerifyParseSucceeded(emptyTheme); + auto theme = Theme::FromJson(schemeObject); + VERIFY_ARE_EQUAL(L"empty", theme->Name()); + VERIFY_IS_NULL(theme->TabRow()); + VERIFY_IS_NULL(theme->Window()); + VERIFY_ARE_EQUAL(winrt::Windows::UI::Xaml::ElementTheme::Default, theme->RequestedTheme()); + } + + void ThemeTests::ParseNoWindowTheme() + { + Log::Comment(L"This theme doesn't have a window defined."); + static constexpr std::string_view emptyTheme{ R"({ + "name": "noWindow", + "tabRow": + { + "background": "#FF112233", + "unfocusedBackground": "#FF884400" + }, + })" }; + + const auto schemeObject = VerifyParseSucceeded(emptyTheme); + auto theme = Theme::FromJson(schemeObject); + VERIFY_ARE_EQUAL(L"noWindow", theme->Name()); + + VERIFY_IS_NOT_NULL(theme->TabRow()); + VERIFY_IS_NOT_NULL(theme->TabRow().Background()); + VERIFY_ARE_EQUAL(Settings::Model::ThemeColorType::Color, theme->TabRow().Background().ColorType()); + VERIFY_ARE_EQUAL(rgb(0x11, 0x22, 0x33), theme->TabRow().Background().Color()); + + VERIFY_IS_NULL(theme->Window()); + VERIFY_ARE_EQUAL(winrt::Windows::UI::Xaml::ElementTheme::Default, theme->RequestedTheme()); + } + + void ThemeTests::ParseNullWindowTheme() + { + Log::Comment(L"This theme doesn't have a window defined."); + static constexpr std::string_view emptyTheme{ R"({ + "name": "nullWindow", + "tabRow": + { + "background": "#FF112233", + "unfocusedBackground": "#FF884400" + }, + "window": null + })" }; + + const auto schemeObject = VerifyParseSucceeded(emptyTheme); + auto theme = Theme::FromJson(schemeObject); + VERIFY_ARE_EQUAL(L"nullWindow", theme->Name()); + + VERIFY_IS_NOT_NULL(theme->TabRow()); + VERIFY_IS_NOT_NULL(theme->TabRow().Background()); + VERIFY_ARE_EQUAL(Settings::Model::ThemeColorType::Color, theme->TabRow().Background().ColorType()); + VERIFY_ARE_EQUAL(rgb(0x11, 0x22, 0x33), theme->TabRow().Background().Color()); + + VERIFY_IS_NULL(theme->Window()); + VERIFY_ARE_EQUAL(winrt::Windows::UI::Xaml::ElementTheme::Default, theme->RequestedTheme()); } void ThemeTests::ParseThemeWithNullThemeColor() { + Log::Comment(L"These themes are all missing a tabRow background. Make sure we don't somehow default-construct one for them"); + static constexpr std::string_view settingsString{ R"json({ "themes": [ { diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 90edd97f0fb..a15b7c5372e 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -368,7 +368,7 @@ namespace winrt::TerminalApp::implementation // It's not enough to set the theme on the dialog alone. auto themingLambda{ [this](const Windows::Foundation::IInspectable& sender, const RoutedEventArgs&) { auto theme{ _settings.GlobalSettings().CurrentTheme() }; - auto requestedTheme{ theme.Window().RequestedTheme() }; + auto requestedTheme{ theme.RequestedTheme() }; auto element{ sender.try_as() }; while (element) { @@ -744,7 +744,7 @@ namespace winrt::TerminalApp::implementation LoadSettings(); } - return _settings.GlobalSettings().CurrentTheme().Window().RequestedTheme(); + return _settings.GlobalSettings().CurrentTheme().RequestedTheme(); } bool AppLogic::GetShowTabsInTitlebar() @@ -965,7 +965,7 @@ namespace winrt::TerminalApp::implementation void AppLogic::_RefreshThemeRoutine() { - _ApplyTheme(_settings.GlobalSettings().CurrentTheme().Window().RequestedTheme()); + _ApplyTheme(_settings.GlobalSettings().CurrentTheme().RequestedTheme()); } // Function Description: diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 33d16231328..e7fb8aa690b 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -3442,7 +3442,7 @@ namespace winrt::TerminalApp::implementation void TerminalPage::_UpdateTeachingTipTheme(winrt::Windows::UI::Xaml::FrameworkElement element) { auto theme{ _settings.GlobalSettings().CurrentTheme() }; - auto requestedTheme{ theme.Window().RequestedTheme() }; + auto requestedTheme{ theme.RequestedTheme() }; while (element) { element.RequestedTheme(requestedTheme); @@ -3957,7 +3957,7 @@ namespace winrt::TerminalApp::implementation } const auto theme = _settings.GlobalSettings().CurrentTheme(); - auto requestedTheme{ theme.Window().RequestedTheme() }; + auto requestedTheme{ theme.RequestedTheme() }; const auto res = Application::Current().Resources(); diff --git a/src/cascadia/TerminalSettingsModel/Theme.cpp b/src/cascadia/TerminalSettingsModel/Theme.cpp index b9450db8025..8fe7d3fb23e 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.cpp +++ b/src/cascadia/TerminalSettingsModel/Theme.cpp @@ -170,12 +170,12 @@ winrt::Windows::UI::Xaml::Media::Brush ThemeColor::Evaluate(const winrt::Windows return nullptr; } -#define THEME_SETTINGS_FROM_JSON(type, name, jsonKey, ...) \ - { \ - std::optional _val; \ - _val = JsonUtils::GetValueForKey>(json, jsonKey); \ - if (_val) \ - result->name(*_val); \ +#define THEME_SETTINGS_FROM_JSON(type, name, jsonKey, ...) \ + { \ + std::optional _val; \ + _val = JsonUtils::GetValueForKey>(json, jsonKey); \ + if (_val) \ + result->name(*_val); \ } #define THEME_SETTINGS_TO_JSON(type, name, jsonKey, ...) \ @@ -187,6 +187,8 @@ winrt::Windows::UI::Xaml::Media::Brush ThemeColor::Evaluate(const winrt::Windows { \ nameSpace::name FromJson(const Json::Value& json) \ { \ + if (json == Json::Value::null) \ + return nullptr; \ auto result = winrt::make_self(); \ macro(THEME_SETTINGS_FROM_JSON); \ return *result; \ @@ -284,7 +286,13 @@ void Theme::LayerJson(const Json::Value& json) // This will use each of the ConversionTrait's from above to quickly parse the sub-objects #define THEME_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \ - JsonUtils::GetValueForKey(json, jsonKey, _##name); + { \ + std::optional _val; \ + _val = JsonUtils::GetValueForKey>(json, jsonKey); \ + if (_val) \ + _##name = *_val; \ + else _##name=nullptr; \ + } MTSM_THEME_SETTINGS(THEME_SETTINGS_LAYER_JSON) #undef THEME_SETTINGS_LAYER_JSON @@ -317,3 +325,14 @@ winrt::hstring Theme::ToString() { return Name(); } +// Method Description: +// - A helper for retreiving the RequestedTheme out of the window property. +// There's a bunch of places throughout the app that all ask for the +// RequestedTheme, this saves some hassle. If there wasn't a `window` defined +// for this theme, this'll quickly just return `system`, to use the OS theme. +// Return Value: +// - the set applicationTheme for this Theme, otherwise the system theme. +winrt::Windows::UI::Xaml::ElementTheme Theme::RequestedTheme() const noexcept +{ + return _Window ? _Window.RequestedTheme() : winrt::Windows::UI::Xaml::ElementTheme::Default; +} diff --git a/src/cascadia/TerminalSettingsModel/Theme.h b/src/cascadia/TerminalSettingsModel/Theme.h index 624329acb6f..02e94a55ce1 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.h +++ b/src/cascadia/TerminalSettingsModel/Theme.h @@ -90,6 +90,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation void LayerJson(const Json::Value& json); Json::Value ToJson() const; + winrt::Windows::UI::Xaml::ElementTheme RequestedTheme() const noexcept; + WINRT_PROPERTY(winrt::hstring, Name); MTSM_THEME_SETTINGS(THEME_SETTINGS_INITIALIZE) diff --git a/src/cascadia/TerminalSettingsModel/Theme.idl b/src/cascadia/TerminalSettingsModel/Theme.idl index 6e05cde3010..1f4f241b66a 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.idl +++ b/src/cascadia/TerminalSettingsModel/Theme.idl @@ -49,5 +49,8 @@ namespace Microsoft.Terminal.Settings.Model // tabRow.* Namespace TabRowTheme TabRow { get; }; + // A helper for retreiving the RequestedTheme out of the window property + Windows.UI.Xaml.ElementTheme RequestedTheme { get; }; + } } diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 23f8ffafd50..9861ad7031e 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -1331,7 +1331,7 @@ void AppHost::_updateTheme() { auto theme = _logic.Theme(); - _window->OnApplicationThemeChanged(theme.Window().RequestedTheme()); + _window->OnApplicationThemeChanged(theme.RequestedTheme()); int attribute = theme.Window().UseMica() ? /* DWMSBT_MAINWINDOW */ 2 : /*DWMSBT_NONE*/ 1; DwmSetWindowAttribute(_window->GetHandle(), /* DWMWA_SYSTEMBACKDROP_TYPE */ 38, &attribute, sizeof(attribute)); From cae5218a7b8da39622a34d51ab11a864f2cc6295 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 6 May 2022 09:49:40 -0500 Subject: [PATCH 53/61] Start by just adding a test file --- .../SettingsModel.LocalTests.vcxproj | 1 + .../LocalTests_SettingsModel/ThemeTests.cpp | 259 ++++++++++++++++++ .../GlobalAppearance.cpp | 4 - .../TerminalSettingsSerializationHelpers.h | 13 + 4 files changed, 273 insertions(+), 4 deletions(-) create mode 100644 src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp diff --git a/src/cascadia/LocalTests_SettingsModel/SettingsModel.LocalTests.vcxproj b/src/cascadia/LocalTests_SettingsModel/SettingsModel.LocalTests.vcxproj index 47214270725..76e0f07e293 100644 --- a/src/cascadia/LocalTests_SettingsModel/SettingsModel.LocalTests.vcxproj +++ b/src/cascadia/LocalTests_SettingsModel/SettingsModel.LocalTests.vcxproj @@ -41,6 +41,7 @@ + Create diff --git a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp new file mode 100644 index 00000000000..b425856a660 --- /dev/null +++ b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp @@ -0,0 +1,259 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" + +#include "../TerminalSettingsModel/Theme.h" +#include "../TerminalSettingsModel/CascadiaSettings.h" +#include "../types/inc/colorTable.hpp" +#include "JsonTestClass.h" + +#include + +using namespace Microsoft::Console; +using namespace winrt::Microsoft::Terminal; +using namespace winrt::Microsoft::Terminal::Settings::Model::implementation; +using namespace WEX::Logging; +using namespace WEX::TestExecution; +using namespace WEX::Common; + +namespace SettingsModelLocalTests +{ + // TODO:microsoft/terminal#3838: + // Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for + // an updated TAEF that will let us install framework packages when the test + // package is deployed. Until then, these tests won't deploy in CI. + + class ThemeTests : public JsonTestClass + { + // Use a custom AppxManifest to ensure that we can activate winrt types + // from our test. This property will tell taef to manually use this as + // the AppxManifest for this test class. + // This does not yet work for anything XAML-y. See TabTests.cpp for more + // details on that. + BEGIN_TEST_CLASS(ThemeTests) + TEST_CLASS_PROPERTY(L"RunAs", L"UAP") + TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml") + END_TEST_CLASS() + + TEST_METHOD(ParseSimpleTheme); + TEST_METHOD(ParseThemeWithNullThemeColor); + + // static Core::Color rgb(uint8_t r, uint8_t g, uint8_t b) noexcept + // { + // return Core::Color{ r, g, b, 255 }; + // } + }; + + void ThemeTests::ParseSimpleTheme() + { + static constexpr std::string_view orangeTheme{ R"({ + "name": "orange", + "tabRow": + { + "background": "#FFFF8800", + "unfocusedBackground": "#FF884400" + }, + "window": + { + "applicationTheme": "light", + "useMica": true + } + })" }; + + const auto schemeObject = VerifyParseSucceeded(orangeTheme); + auto theme = Theme::FromJson(schemeObject); + VERIFY_ARE_EQUAL(L"orange", theme->Name()); + // VERIFY_ARE_EQUAL(til::color(0xf2, 0xf2, 0xf2, 255), til::color{ scheme->Foreground() }); + // VERIFY_ARE_EQUAL(til::color(0x0c, 0x0c, 0x0c, 255), til::color{ scheme->Background() }); + // VERIFY_ARE_EQUAL(til::color(0x13, 0x13, 0x13, 255), til::color{ scheme->SelectionBackground() }); + // VERIFY_ARE_EQUAL(til::color(0xFF, 0xFF, 0xFF, 255), til::color{ scheme->CursorColor() }); + + // std::array expectedCampbellTable; + // const auto campbellSpan = gsl::make_span(expectedCampbellTable); + // Utils::InitializeColorTable(campbellSpan); + + // for (size_t i = 0; i < expectedCampbellTable.size(); i++) + // { + // const til::color expected{ expectedCampbellTable.at(i) }; + // const til::color actual{ scheme->Table().at(static_cast(i)) }; + // VERIFY_ARE_EQUAL(expected, actual); + // } + + // Log::Comment(L"Roundtrip Test for Color Scheme"); + // auto outJson{ scheme->ToJson() }; + // VERIFY_ARE_EQUAL(schemeObject, outJson); + } + + // void ColorSchemeTests::LayerColorSchemesOnArray() + // { + // static constexpr std::string_view inboxSettings{ R"({ + // "schemes": [ + // { + // "background": "#0C0C0C", + // "black": "#0C0C0C", + // "blue": "#0037DA", + // "brightBlack": "#767676", + // "brightBlue": "#3B78FF", + // "brightCyan": "#61D6D6", + // "brightGreen": "#16C60C", + // "brightPurple": "#B4009E", + // "brightRed": "#E74856", + // "brightWhite": "#F2F2F2", + // "brightYellow": "#F9F1A5", + // "cursorColor": "#FFFFFF", + // "cyan": "#3A96DD", + // "foreground": "#CCCCCC", + // "green": "#13A10E", + // "name": "Campbell", + // "purple": "#881798", + // "red": "#C50F1F", + // "selectionBackground": "#FFFFFF", + // "white": "#CCCCCC", + // "yellow": "#C19C00" + // } + // ] + // })" }; + // static constexpr std::string_view userSettings{ R"({ + // "profiles": [ + // { + // "name" : "profile0" + // } + // ], + // "schemes": [ + // { + // "background": "#121314", + // "black": "#121314", + // "blue": "#121314", + // "brightBlack": "#121314", + // "brightBlue": "#121314", + // "brightCyan": "#121314", + // "brightGreen": "#121314", + // "brightPurple": "#121314", + // "brightRed": "#121314", + // "brightWhite": "#121314", + // "brightYellow": "#121314", + // "cursorColor": "#121314", + // "cyan": "#121314", + // "foreground": "#121314", + // "green": "#121314", + // "name": "Campbell", + // "purple": "#121314", + // "red": "#121314", + // "selectionBackground": "#121314", + // "white": "#121314", + // "yellow": "#121314" + // }, + // { + // "background": "#012456", + // "black": "#0C0C0C", + // "blue": "#0037DA", + // "brightBlack": "#767676", + // "brightBlue": "#3B78FF", + // "brightCyan": "#61D6D6", + // "brightGreen": "#16C60C", + // "brightPurple": "#B4009E", + // "brightRed": "#E74856", + // "brightWhite": "#F2F2F2", + // "brightYellow": "#F9F1A5", + // "cursorColor": "#FFFFFF", + // "cyan": "#3A96DD", + // "foreground": "#CCCCCC", + // "green": "#13A10E", + // "name": "Campbell Powershell", + // "purple": "#881798", + // "red": "#C50F1F", + // "selectionBackground": "#FFFFFF", + // "white": "#CCCCCC", + // "yellow": "#C19C00" + // } + // ] + // })" }; + + // const auto settings = winrt::make_self(userSettings, inboxSettings); + + // const auto colorSchemes = settings->GlobalSettings().ColorSchemes(); + // VERIFY_ARE_EQUAL(2u, colorSchemes.Size()); + + // const auto scheme0 = winrt::get_self(colorSchemes.Lookup(L"Campbell")); + // VERIFY_ARE_EQUAL(rgb(0x12, 0x13, 0x14), scheme0->Foreground()); + // VERIFY_ARE_EQUAL(rgb(0x12, 0x13, 0x14), scheme0->Background()); + + // const auto scheme1 = winrt::get_self(colorSchemes.Lookup(L"Campbell Powershell")); + // VERIFY_ARE_EQUAL(rgb(0xCC, 0xCC, 0xCC), scheme1->Foreground()); + // VERIFY_ARE_EQUAL(rgb(0x01, 0x24, 0x56), scheme1->Background()); + // } + + void ThemeTests::ParseThemeWithNullThemeColor() + { + static constexpr std::string_view settingsString{ R"json({ + "themes": [ + { + "name": "backgroundEmpty", + "tabRow": + { + }, + "window": + { + "applicationTheme": "light", + "useMica": true + } + }, + ] + })json" }; + + // { + // "name": "backgroundNull", + // "tabRow": + // { + // "background": null + // }, + // "window": + // { + // "applicationTheme": "light", + // "useMica": true + // } + // }, + // { + // "name": "backgroundOmittedEntirely", + // "window": + // { + // "applicationTheme": "light", + // "useMica": true + // } + // } + + try + { + const auto settings{ winrt::make_self(settingsString, DefaultJson) }; + + const auto& themes{ settings->GlobalSettings().Themes() }; + { + const auto& backgroundEmpty{ themes.Lookup(L"backgroundEmpty") }; + VERIFY_ARE_EQUAL(L"backgroundEmpty", backgroundEmpty.Name()); + } + { + const auto& backgroundNull{ themes.Lookup(L"backgroundNull") }; + VERIFY_ARE_EQUAL(L"backgroundNull", backgroundNull.Name()); + } + { + const auto& backgroundOmittedEntirely{ themes.Lookup(L"backgroundOmittedEntirely") }; + VERIFY_ARE_EQUAL(L"backgroundOmittedEntirely", backgroundOmittedEntirely.Name()); + } + } + catch (const SettingsException& ex) + { + auto loadError = ex.Error(); + loadError; + DebugBreak(); + throw ex; + } + catch (const SettingsTypedDeserializationException& e) + { + auto deserializationErrorMessage = til::u8u16(e.what()); + Log::Comment(NoThrowString().Format(deserializationErrorMessage.c_str())); + DebugBreak(); + throw e; + } + } +} diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp index 07a9e5fb216..69686b51e1d 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.cpp @@ -206,10 +206,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation for (const auto& pair : ThemeMap) { const auto& theme{ pair.Value() }; - const auto& name{ theme.Name() }; - theme; - name; - _ThemeList.Append(theme); } } diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h index be0b3e0e64e..daff9111663 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h @@ -552,6 +552,10 @@ struct ::Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait Date: Fri, 6 May 2022 09:58:17 -0500 Subject: [PATCH 54/61] Fill in more tests --- .../LocalTests_SettingsModel/ThemeTests.cpp | 76 ++++++++----------- 1 file changed, 33 insertions(+), 43 deletions(-) diff --git a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp index b425856a660..fc9e0333f9d 100644 --- a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp +++ b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp @@ -39,10 +39,10 @@ namespace SettingsModelLocalTests TEST_METHOD(ParseSimpleTheme); TEST_METHOD(ParseThemeWithNullThemeColor); - // static Core::Color rgb(uint8_t r, uint8_t g, uint8_t b) noexcept - // { - // return Core::Color{ r, g, b, 255 }; - // } + static Core::Color rgb(uint8_t r, uint8_t g, uint8_t b) noexcept + { + return Core::Color{ r, g, b, 255 }; + } }; void ThemeTests::ParseSimpleTheme() @@ -64,25 +64,11 @@ namespace SettingsModelLocalTests const auto schemeObject = VerifyParseSucceeded(orangeTheme); auto theme = Theme::FromJson(schemeObject); VERIFY_ARE_EQUAL(L"orange", theme->Name()); - // VERIFY_ARE_EQUAL(til::color(0xf2, 0xf2, 0xf2, 255), til::color{ scheme->Foreground() }); - // VERIFY_ARE_EQUAL(til::color(0x0c, 0x0c, 0x0c, 255), til::color{ scheme->Background() }); - // VERIFY_ARE_EQUAL(til::color(0x13, 0x13, 0x13, 255), til::color{ scheme->SelectionBackground() }); - // VERIFY_ARE_EQUAL(til::color(0xFF, 0xFF, 0xFF, 255), til::color{ scheme->CursorColor() }); - - // std::array expectedCampbellTable; - // const auto campbellSpan = gsl::make_span(expectedCampbellTable); - // Utils::InitializeColorTable(campbellSpan); - // for (size_t i = 0; i < expectedCampbellTable.size(); i++) - // { - // const til::color expected{ expectedCampbellTable.at(i) }; - // const til::color actual{ scheme->Table().at(static_cast(i)) }; - // VERIFY_ARE_EQUAL(expected, actual); - // } - - // Log::Comment(L"Roundtrip Test for Color Scheme"); - // auto outJson{ scheme->ToJson() }; - // VERIFY_ARE_EQUAL(schemeObject, outJson); + VERIFY_IS_NOT_NULL(theme->TabRow()); + VERIFY_IS_NOT_NULL(theme->TabRow().Background()); + VERIFY_ARE_EQUAL(Settings::Model::ThemeColorType::Color, theme->TabRow().Background().ColorType()); + VERIFY_ARE_EQUAL(rgb(0xff, 0x88, 0x00), theme->TabRow().Background().Color()); } // void ColorSchemeTests::LayerColorSchemesOnArray() @@ -199,30 +185,29 @@ namespace SettingsModelLocalTests "useMica": true } }, + { + "name": "backgroundNull", + "tabRow": + { + "background": null + }, + "window": + { + "applicationTheme": "light", + "useMica": true + } + }, + { + "name": "backgroundOmittedEntirely", + "window": + { + "applicationTheme": "light", + "useMica": true + } + } ] })json" }; - // { - // "name": "backgroundNull", - // "tabRow": - // { - // "background": null - // }, - // "window": - // { - // "applicationTheme": "light", - // "useMica": true - // } - // }, - // { - // "name": "backgroundOmittedEntirely", - // "window": - // { - // "applicationTheme": "light", - // "useMica": true - // } - // } - try { const auto settings{ winrt::make_self(settingsString, DefaultJson) }; @@ -231,14 +216,19 @@ namespace SettingsModelLocalTests { const auto& backgroundEmpty{ themes.Lookup(L"backgroundEmpty") }; VERIFY_ARE_EQUAL(L"backgroundEmpty", backgroundEmpty.Name()); + VERIFY_IS_NOT_NULL(backgroundEmpty.TabRow()); + VERIFY_IS_NULL(backgroundEmpty.TabRow().Background()); } { const auto& backgroundNull{ themes.Lookup(L"backgroundNull") }; VERIFY_ARE_EQUAL(L"backgroundNull", backgroundNull.Name()); + VERIFY_IS_NOT_NULL(backgroundNull.TabRow()); + VERIFY_IS_NULL(backgroundNull.TabRow().Background()); } { const auto& backgroundOmittedEntirely{ themes.Lookup(L"backgroundOmittedEntirely") }; VERIFY_ARE_EQUAL(L"backgroundOmittedEntirely", backgroundOmittedEntirely.Name()); + VERIFY_IS_NULL(backgroundOmittedEntirely.TabRow()); } } catch (const SettingsException& ex) From 28119c7614e231577940a1b5d4fbb69d9fa93507 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 6 May 2022 11:00:29 -0500 Subject: [PATCH 55/61] This is what I was looking for --- .../LocalTests_SettingsModel/ThemeTests.cpp | 99 ------------------- src/cascadia/TerminalSettingsModel/Theme.cpp | 7 +- 2 files changed, 6 insertions(+), 100 deletions(-) diff --git a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp index fc9e0333f9d..5d085922cf5 100644 --- a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp +++ b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp @@ -71,105 +71,6 @@ namespace SettingsModelLocalTests VERIFY_ARE_EQUAL(rgb(0xff, 0x88, 0x00), theme->TabRow().Background().Color()); } - // void ColorSchemeTests::LayerColorSchemesOnArray() - // { - // static constexpr std::string_view inboxSettings{ R"({ - // "schemes": [ - // { - // "background": "#0C0C0C", - // "black": "#0C0C0C", - // "blue": "#0037DA", - // "brightBlack": "#767676", - // "brightBlue": "#3B78FF", - // "brightCyan": "#61D6D6", - // "brightGreen": "#16C60C", - // "brightPurple": "#B4009E", - // "brightRed": "#E74856", - // "brightWhite": "#F2F2F2", - // "brightYellow": "#F9F1A5", - // "cursorColor": "#FFFFFF", - // "cyan": "#3A96DD", - // "foreground": "#CCCCCC", - // "green": "#13A10E", - // "name": "Campbell", - // "purple": "#881798", - // "red": "#C50F1F", - // "selectionBackground": "#FFFFFF", - // "white": "#CCCCCC", - // "yellow": "#C19C00" - // } - // ] - // })" }; - // static constexpr std::string_view userSettings{ R"({ - // "profiles": [ - // { - // "name" : "profile0" - // } - // ], - // "schemes": [ - // { - // "background": "#121314", - // "black": "#121314", - // "blue": "#121314", - // "brightBlack": "#121314", - // "brightBlue": "#121314", - // "brightCyan": "#121314", - // "brightGreen": "#121314", - // "brightPurple": "#121314", - // "brightRed": "#121314", - // "brightWhite": "#121314", - // "brightYellow": "#121314", - // "cursorColor": "#121314", - // "cyan": "#121314", - // "foreground": "#121314", - // "green": "#121314", - // "name": "Campbell", - // "purple": "#121314", - // "red": "#121314", - // "selectionBackground": "#121314", - // "white": "#121314", - // "yellow": "#121314" - // }, - // { - // "background": "#012456", - // "black": "#0C0C0C", - // "blue": "#0037DA", - // "brightBlack": "#767676", - // "brightBlue": "#3B78FF", - // "brightCyan": "#61D6D6", - // "brightGreen": "#16C60C", - // "brightPurple": "#B4009E", - // "brightRed": "#E74856", - // "brightWhite": "#F2F2F2", - // "brightYellow": "#F9F1A5", - // "cursorColor": "#FFFFFF", - // "cyan": "#3A96DD", - // "foreground": "#CCCCCC", - // "green": "#13A10E", - // "name": "Campbell Powershell", - // "purple": "#881798", - // "red": "#C50F1F", - // "selectionBackground": "#FFFFFF", - // "white": "#CCCCCC", - // "yellow": "#C19C00" - // } - // ] - // })" }; - - // const auto settings = winrt::make_self(userSettings, inboxSettings); - - // const auto colorSchemes = settings->GlobalSettings().ColorSchemes(); - // VERIFY_ARE_EQUAL(2u, colorSchemes.Size()); - - // const auto scheme0 = winrt::get_self(colorSchemes.Lookup(L"Campbell")); - // VERIFY_ARE_EQUAL(rgb(0x12, 0x13, 0x14), scheme0->Foreground()); - // VERIFY_ARE_EQUAL(rgb(0x12, 0x13, 0x14), scheme0->Background()); - - // const auto scheme1 = winrt::get_self(colorSchemes.Lookup(L"Campbell Powershell")); - // VERIFY_ARE_EQUAL(rgb(0xCC, 0xCC, 0xCC), scheme1->Foreground()); - // VERIFY_ARE_EQUAL(rgb(0x01, 0x24, 0x56), scheme1->Background()); - // } - void ThemeTests::ParseThemeWithNullThemeColor() { static constexpr std::string_view settingsString{ R"json({ diff --git a/src/cascadia/TerminalSettingsModel/Theme.cpp b/src/cascadia/TerminalSettingsModel/Theme.cpp index b2b90bab30c..b9450db8025 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.cpp +++ b/src/cascadia/TerminalSettingsModel/Theme.cpp @@ -171,7 +171,12 @@ winrt::Windows::UI::Xaml::Media::Brush ThemeColor::Evaluate(const winrt::Windows } #define THEME_SETTINGS_FROM_JSON(type, name, jsonKey, ...) \ - result->name(JsonUtils::GetValueForKey(json, jsonKey)); + { \ + std::optional _val; \ + _val = JsonUtils::GetValueForKey>(json, jsonKey); \ + if (_val) \ + result->name(*_val); \ + } #define THEME_SETTINGS_TO_JSON(type, name, jsonKey, ...) \ JsonUtils::SetValueForKey(json, jsonKey, val.name()); From 2712e462a1156e57f914fcf340edee555581f08f Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 6 May 2022 12:02:33 -0500 Subject: [PATCH 56/61] Fix having a null window, cause that was actually very possible --- .../LocalTests_SettingsModel/ThemeTests.cpp | 75 +++++++++++++++++++ src/cascadia/TerminalApp/AppLogic.cpp | 6 +- src/cascadia/TerminalApp/TerminalPage.cpp | 4 +- src/cascadia/TerminalSettingsModel/Theme.cpp | 33 ++++++-- src/cascadia/TerminalSettingsModel/Theme.h | 2 + src/cascadia/TerminalSettingsModel/Theme.idl | 3 + src/cascadia/WindowsTerminal/AppHost.cpp | 2 +- 7 files changed, 112 insertions(+), 13 deletions(-) diff --git a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp index 5d085922cf5..2475f2e8d09 100644 --- a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp +++ b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp @@ -37,6 +37,9 @@ namespace SettingsModelLocalTests END_TEST_CLASS() TEST_METHOD(ParseSimpleTheme); + TEST_METHOD(ParseEmptyTheme); + TEST_METHOD(ParseNoWindowTheme); + TEST_METHOD(ParseNullWindowTheme); TEST_METHOD(ParseThemeWithNullThemeColor); static Core::Color rgb(uint8_t r, uint8_t g, uint8_t b) noexcept @@ -69,10 +72,82 @@ namespace SettingsModelLocalTests VERIFY_IS_NOT_NULL(theme->TabRow().Background()); VERIFY_ARE_EQUAL(Settings::Model::ThemeColorType::Color, theme->TabRow().Background().ColorType()); VERIFY_ARE_EQUAL(rgb(0xff, 0x88, 0x00), theme->TabRow().Background().Color()); + + VERIFY_IS_NOT_NULL(theme->Window()); + VERIFY_ARE_EQUAL(winrt::Windows::UI::Xaml::ElementTheme::Light, theme->Window().RequestedTheme()); + VERIFY_ARE_EQUAL(true, theme->Window().UseMica()); + } + + void ThemeTests::ParseEmptyTheme() + { + Log::Comment(L"This theme doesn't have any elements defined."); + static constexpr std::string_view emptyTheme{ R"({ + "name": "empty" + })" }; + + const auto schemeObject = VerifyParseSucceeded(emptyTheme); + auto theme = Theme::FromJson(schemeObject); + VERIFY_ARE_EQUAL(L"empty", theme->Name()); + VERIFY_IS_NULL(theme->TabRow()); + VERIFY_IS_NULL(theme->Window()); + VERIFY_ARE_EQUAL(winrt::Windows::UI::Xaml::ElementTheme::Default, theme->RequestedTheme()); + } + + void ThemeTests::ParseNoWindowTheme() + { + Log::Comment(L"This theme doesn't have a window defined."); + static constexpr std::string_view emptyTheme{ R"({ + "name": "noWindow", + "tabRow": + { + "background": "#FF112233", + "unfocusedBackground": "#FF884400" + }, + })" }; + + const auto schemeObject = VerifyParseSucceeded(emptyTheme); + auto theme = Theme::FromJson(schemeObject); + VERIFY_ARE_EQUAL(L"noWindow", theme->Name()); + + VERIFY_IS_NOT_NULL(theme->TabRow()); + VERIFY_IS_NOT_NULL(theme->TabRow().Background()); + VERIFY_ARE_EQUAL(Settings::Model::ThemeColorType::Color, theme->TabRow().Background().ColorType()); + VERIFY_ARE_EQUAL(rgb(0x11, 0x22, 0x33), theme->TabRow().Background().Color()); + + VERIFY_IS_NULL(theme->Window()); + VERIFY_ARE_EQUAL(winrt::Windows::UI::Xaml::ElementTheme::Default, theme->RequestedTheme()); + } + + void ThemeTests::ParseNullWindowTheme() + { + Log::Comment(L"This theme doesn't have a window defined."); + static constexpr std::string_view emptyTheme{ R"({ + "name": "nullWindow", + "tabRow": + { + "background": "#FF112233", + "unfocusedBackground": "#FF884400" + }, + "window": null + })" }; + + const auto schemeObject = VerifyParseSucceeded(emptyTheme); + auto theme = Theme::FromJson(schemeObject); + VERIFY_ARE_EQUAL(L"nullWindow", theme->Name()); + + VERIFY_IS_NOT_NULL(theme->TabRow()); + VERIFY_IS_NOT_NULL(theme->TabRow().Background()); + VERIFY_ARE_EQUAL(Settings::Model::ThemeColorType::Color, theme->TabRow().Background().ColorType()); + VERIFY_ARE_EQUAL(rgb(0x11, 0x22, 0x33), theme->TabRow().Background().Color()); + + VERIFY_IS_NULL(theme->Window()); + VERIFY_ARE_EQUAL(winrt::Windows::UI::Xaml::ElementTheme::Default, theme->RequestedTheme()); } void ThemeTests::ParseThemeWithNullThemeColor() { + Log::Comment(L"These themes are all missing a tabRow background. Make sure we don't somehow default-construct one for them"); + static constexpr std::string_view settingsString{ R"json({ "themes": [ { diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 90edd97f0fb..a15b7c5372e 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -368,7 +368,7 @@ namespace winrt::TerminalApp::implementation // It's not enough to set the theme on the dialog alone. auto themingLambda{ [this](const Windows::Foundation::IInspectable& sender, const RoutedEventArgs&) { auto theme{ _settings.GlobalSettings().CurrentTheme() }; - auto requestedTheme{ theme.Window().RequestedTheme() }; + auto requestedTheme{ theme.RequestedTheme() }; auto element{ sender.try_as() }; while (element) { @@ -744,7 +744,7 @@ namespace winrt::TerminalApp::implementation LoadSettings(); } - return _settings.GlobalSettings().CurrentTheme().Window().RequestedTheme(); + return _settings.GlobalSettings().CurrentTheme().RequestedTheme(); } bool AppLogic::GetShowTabsInTitlebar() @@ -965,7 +965,7 @@ namespace winrt::TerminalApp::implementation void AppLogic::_RefreshThemeRoutine() { - _ApplyTheme(_settings.GlobalSettings().CurrentTheme().Window().RequestedTheme()); + _ApplyTheme(_settings.GlobalSettings().CurrentTheme().RequestedTheme()); } // Function Description: diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 164693b0dda..141b5bce370 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -3442,7 +3442,7 @@ namespace winrt::TerminalApp::implementation void TerminalPage::_UpdateTeachingTipTheme(winrt::Windows::UI::Xaml::FrameworkElement element) { auto theme{ _settings.GlobalSettings().CurrentTheme() }; - auto requestedTheme{ theme.Window().RequestedTheme() }; + auto requestedTheme{ theme.RequestedTheme() }; while (element) { element.RequestedTheme(requestedTheme); @@ -3957,7 +3957,7 @@ namespace winrt::TerminalApp::implementation } const auto theme = _settings.GlobalSettings().CurrentTheme(); - auto requestedTheme{ theme.Window().RequestedTheme() }; + auto requestedTheme{ theme.RequestedTheme() }; const auto res = Application::Current().Resources(); diff --git a/src/cascadia/TerminalSettingsModel/Theme.cpp b/src/cascadia/TerminalSettingsModel/Theme.cpp index b9450db8025..8fe7d3fb23e 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.cpp +++ b/src/cascadia/TerminalSettingsModel/Theme.cpp @@ -170,12 +170,12 @@ winrt::Windows::UI::Xaml::Media::Brush ThemeColor::Evaluate(const winrt::Windows return nullptr; } -#define THEME_SETTINGS_FROM_JSON(type, name, jsonKey, ...) \ - { \ - std::optional _val; \ - _val = JsonUtils::GetValueForKey>(json, jsonKey); \ - if (_val) \ - result->name(*_val); \ +#define THEME_SETTINGS_FROM_JSON(type, name, jsonKey, ...) \ + { \ + std::optional _val; \ + _val = JsonUtils::GetValueForKey>(json, jsonKey); \ + if (_val) \ + result->name(*_val); \ } #define THEME_SETTINGS_TO_JSON(type, name, jsonKey, ...) \ @@ -187,6 +187,8 @@ winrt::Windows::UI::Xaml::Media::Brush ThemeColor::Evaluate(const winrt::Windows { \ nameSpace::name FromJson(const Json::Value& json) \ { \ + if (json == Json::Value::null) \ + return nullptr; \ auto result = winrt::make_self(); \ macro(THEME_SETTINGS_FROM_JSON); \ return *result; \ @@ -284,7 +286,13 @@ void Theme::LayerJson(const Json::Value& json) // This will use each of the ConversionTrait's from above to quickly parse the sub-objects #define THEME_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \ - JsonUtils::GetValueForKey(json, jsonKey, _##name); + { \ + std::optional _val; \ + _val = JsonUtils::GetValueForKey>(json, jsonKey); \ + if (_val) \ + _##name = *_val; \ + else _##name=nullptr; \ + } MTSM_THEME_SETTINGS(THEME_SETTINGS_LAYER_JSON) #undef THEME_SETTINGS_LAYER_JSON @@ -317,3 +325,14 @@ winrt::hstring Theme::ToString() { return Name(); } +// Method Description: +// - A helper for retreiving the RequestedTheme out of the window property. +// There's a bunch of places throughout the app that all ask for the +// RequestedTheme, this saves some hassle. If there wasn't a `window` defined +// for this theme, this'll quickly just return `system`, to use the OS theme. +// Return Value: +// - the set applicationTheme for this Theme, otherwise the system theme. +winrt::Windows::UI::Xaml::ElementTheme Theme::RequestedTheme() const noexcept +{ + return _Window ? _Window.RequestedTheme() : winrt::Windows::UI::Xaml::ElementTheme::Default; +} diff --git a/src/cascadia/TerminalSettingsModel/Theme.h b/src/cascadia/TerminalSettingsModel/Theme.h index 624329acb6f..02e94a55ce1 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.h +++ b/src/cascadia/TerminalSettingsModel/Theme.h @@ -90,6 +90,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation void LayerJson(const Json::Value& json); Json::Value ToJson() const; + winrt::Windows::UI::Xaml::ElementTheme RequestedTheme() const noexcept; + WINRT_PROPERTY(winrt::hstring, Name); MTSM_THEME_SETTINGS(THEME_SETTINGS_INITIALIZE) diff --git a/src/cascadia/TerminalSettingsModel/Theme.idl b/src/cascadia/TerminalSettingsModel/Theme.idl index 00406deea34..3fd5943f22a 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.idl +++ b/src/cascadia/TerminalSettingsModel/Theme.idl @@ -48,5 +48,8 @@ namespace Microsoft.Terminal.Settings.Model // tabRow.* Namespace TabRowTheme TabRow { get; }; + // A helper for retreiving the RequestedTheme out of the window property + Windows.UI.Xaml.ElementTheme RequestedTheme { get; }; + } } diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 23f8ffafd50..9861ad7031e 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -1331,7 +1331,7 @@ void AppHost::_updateTheme() { auto theme = _logic.Theme(); - _window->OnApplicationThemeChanged(theme.Window().RequestedTheme()); + _window->OnApplicationThemeChanged(theme.RequestedTheme()); int attribute = theme.Window().UseMica() ? /* DWMSBT_MAINWINDOW */ 2 : /*DWMSBT_NONE*/ 1; DwmSetWindowAttribute(_window->GetHandle(), /* DWMWA_SYSTEMBACKDROP_TYPE */ 38, &attribute, sizeof(attribute)); From 331b98f008c3920fdb3a037a673573733eb275ff Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 6 May 2022 15:24:19 -0500 Subject: [PATCH 57/61] sensible defaults --- .../LocalTests_SettingsModel/ThemeTests.cpp | 55 +++++++++++++++++++ src/cascadia/TerminalApp/AppLogic.cpp | 1 + .../Resources/en-US/Resources.resw | 4 ++ .../CascadiaSettings.cpp | 12 ++++ .../TerminalSettingsModel/CascadiaSettings.h | 1 + .../TerminalWarnings.idl | 1 + 6 files changed, 74 insertions(+) diff --git a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp index 2475f2e8d09..666889b467b 100644 --- a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp +++ b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp @@ -41,6 +41,7 @@ namespace SettingsModelLocalTests TEST_METHOD(ParseNoWindowTheme); TEST_METHOD(ParseNullWindowTheme); TEST_METHOD(ParseThemeWithNullThemeColor); + TEST_METHOD(InvalidCurrentTheme); static Core::Color rgb(uint8_t r, uint8_t g, uint8_t b) noexcept { @@ -222,4 +223,58 @@ namespace SettingsModelLocalTests throw e; } } + + void ThemeTests::InvalidCurrentTheme() + { + Log::Comment(L"Make sure specifying an invalid theme falls back to a sensible default."); + + static constexpr std::string_view settingsString{ R"json({ + "theme": "foo", + "themes": [ + { + "name": "bar", + "tabRow": {}, + "window": + { + "applicationTheme": "light", + "useMica": true + } + } + ] + })json" }; + + try + { + const auto settings{ winrt::make_self(settingsString, DefaultJson) }; + + VERIFY_ARE_EQUAL(1u, settings->Warnings().Size()); + VERIFY_ARE_EQUAL(Settings::Model::SettingsLoadWarnings::UnknownTheme, settings->Warnings().GetAt(0)); + + const auto& themes{ settings->GlobalSettings().Themes() }; + { + const auto& bar{ themes.Lookup(L"bar") }; + VERIFY_ARE_EQUAL(L"bar", bar.Name()); + VERIFY_IS_NOT_NULL(bar.TabRow()); + VERIFY_IS_NULL(bar.TabRow().Background()); + } + + const auto currentTheme{ settings->GlobalSettings().CurrentTheme() }; + VERIFY_IS_NOT_NULL(currentTheme); + VERIFY_ARE_EQUAL(L"system", currentTheme.Name()); + } + catch (const SettingsException& ex) + { + auto loadError = ex.Error(); + loadError; + DebugBreak(); + throw ex; + } + catch (const SettingsTypedDeserializationException& e) + { + auto deserializationErrorMessage = til::u8u16(e.what()); + Log::Comment(NoThrowString().Format(deserializationErrorMessage.c_str())); + DebugBreak(); + throw e; + } + } } diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index a15b7c5372e..6fa6481f5fe 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -51,6 +51,7 @@ static const std::array settingsLoadWarningsLabels { USES_RESOURCE(L"InvalidSplitSize"), USES_RESOURCE(L"FailedToParseStartupActions"), USES_RESOURCE(L"FailedToParseSubCommands"), + USES_RESOURCE(L"UnknownTheme"), }; static const std::array settingsLoadErrorsLabels { USES_RESOURCE(L"NoProfilesText"), diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index b2133af1816..cc0c20f5846 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -242,6 +242,10 @@ • Found a keybinding that was missing a required parameter value. This keybinding will be ignored. {Locked="•"} This glyph is a bullet, used in a bulleted list. + + • The specified "theme" was not found in the list of themes. Temporarily falling back to the default value. + {Locked="•"} This glyph is a bullet, used in a bulleted list. + The "globals" property is deprecated - your settings might need updating. {Locked="\"globals\""} diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp index b34661a3cb6..5fa487232dd 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp @@ -408,6 +408,7 @@ void CascadiaSettings::_validateSettings() _validateMediaResources(); _validateKeybindings(); _validateColorSchemesInCommands(); + _validateThemeExists(); } // Method Description: @@ -1136,3 +1137,14 @@ void CascadiaSettings::ExportFile(winrt::hstring path, winrt::hstring content) } CATCH_LOG(); } + +void CascadiaSettings::_validateThemeExists() +{ + if (!_globals->Themes().HasKey(_globals->Theme())) + { + _warnings.Append(SettingsLoadWarnings::UnknownTheme); + + // safely fall back to system as the theme. + _globals->Theme(L"system"); + } +} diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.h b/src/cascadia/TerminalSettingsModel/CascadiaSettings.h index e5424d77047..dfb093cbefb 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.h +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.h @@ -158,6 +158,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation void _validateKeybindings() const; void _validateColorSchemesInCommands() const; bool _hasInvalidColorScheme(const Model::Command& command) const; + void _validateThemeExists(); // user settings winrt::com_ptr _globals = winrt::make_self(); diff --git a/src/cascadia/TerminalSettingsModel/TerminalWarnings.idl b/src/cascadia/TerminalSettingsModel/TerminalWarnings.idl index c8aea6b95ab..43dee4e5a61 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalWarnings.idl +++ b/src/cascadia/TerminalSettingsModel/TerminalWarnings.idl @@ -21,6 +21,7 @@ namespace Microsoft.Terminal.Settings.Model InvalidSplitSize, FailedToParseStartupActions, FailedToParseSubCommands, + UnknownTheme, WARNINGS_SIZE // IMPORTANT: This MUST be the last value in this enum. It's an unused placeholder. }; From f38dc5cf5a89ec604fe93b33350a24ded5298576 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 6 May 2022 15:26:18 -0500 Subject: [PATCH 58/61] typos --- src/cascadia/TerminalSettingsModel/Theme.cpp | 11 ++++++----- src/cascadia/TerminalSettingsModel/Theme.idl | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/cascadia/TerminalSettingsModel/Theme.cpp b/src/cascadia/TerminalSettingsModel/Theme.cpp index 8fe7d3fb23e..0703d916487 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.cpp +++ b/src/cascadia/TerminalSettingsModel/Theme.cpp @@ -125,7 +125,7 @@ winrt::Windows::UI::Xaml::Media::Brush ThemeColor::Evaluate(const winrt::Windows } case ThemeColorType::TerminalBackground: { - // If we're evaluating this color for the tab row, there are some rulse + // If we're evaluating this color for the tab row, there are some rules // we have to follow, unfortunately. We can't allow a transparent // background, so we have to make sure to fill that in with Opacity(1.0) // manually. @@ -285,13 +285,14 @@ void Theme::LayerJson(const Json::Value& json) // This will use each of the ConversionTrait's from above to quickly parse the sub-objects -#define THEME_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \ +#define THEME_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \ { \ std::optional _val; \ _val = JsonUtils::GetValueForKey>(json, jsonKey); \ if (_val) \ - _##name = *_val; \ - else _##name=nullptr; \ + _##name = *_val; \ + else \ + _##name = nullptr; \ } MTSM_THEME_SETTINGS(THEME_SETTINGS_LAYER_JSON) @@ -326,7 +327,7 @@ winrt::hstring Theme::ToString() return Name(); } // Method Description: -// - A helper for retreiving the RequestedTheme out of the window property. +// - A helper for retrieving the RequestedTheme out of the window property. // There's a bunch of places throughout the app that all ask for the // RequestedTheme, this saves some hassle. If there wasn't a `window` defined // for this theme, this'll quickly just return `system`, to use the OS theme. diff --git a/src/cascadia/TerminalSettingsModel/Theme.idl b/src/cascadia/TerminalSettingsModel/Theme.idl index 3fd5943f22a..f2932a5e1fd 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.idl +++ b/src/cascadia/TerminalSettingsModel/Theme.idl @@ -48,7 +48,7 @@ namespace Microsoft.Terminal.Settings.Model // tabRow.* Namespace TabRowTheme TabRow { get; }; - // A helper for retreiving the RequestedTheme out of the window property + // A helper for retrieving the RequestedTheme out of the window property Windows.UI.Xaml.ElementTheme RequestedTheme { get; }; } From 45c6239d77ca5ca8837f0d3d0db9bad396f6190b Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 26 May 2022 15:27:41 -0500 Subject: [PATCH 59/61] this is not idomatic at all --- src/cascadia/TerminalApp/TerminalPage.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 16789c4fed6..5bf3a86c882 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -4065,17 +4065,15 @@ namespace winrt::TerminalApp::implementation if (const auto tabRowBg{ _activated ? theme.TabRow().Background() : theme.TabRow().UnfocusedBackground() }) { - const auto terminalBrush = [this]() -> Media::Brush { - if (const auto& control{ _GetActiveControl() }) - { - return control.BackgroundBrush(); - } - else if (auto settingsTab = _GetFocusedTab().try_as()) - { - return settingsTab.Content().try_as().Background(); - } - return nullptr; - }(); + Media::Brush terminalBrush{ nullptr }; + if (const auto& control{ _GetActiveControl() }) + { + terminalBrush = control.BackgroundBrush(); + } + else if (auto settingsTab = _GetFocusedTab().try_as()) + { + terminalBrush = settingsTab.Content().try_as().Background(); + } const auto themeBrush{ tabRowBg.Evaluate(res, terminalBrush, true) }; bgColor = ThemeColor::ColorFromBrush(themeBrush); From bcab4d30f76e8c0cf17e15e1a16c058fb0a8efd7 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 7 Jul 2022 10:30:40 -0500 Subject: [PATCH 60/61] a comment --- src/cascadia/TerminalSettingsModel/Theme.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cascadia/TerminalSettingsModel/Theme.cpp b/src/cascadia/TerminalSettingsModel/Theme.cpp index 27826d6bb4e..46e7b52f71a 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.cpp +++ b/src/cascadia/TerminalSettingsModel/Theme.cpp @@ -104,6 +104,10 @@ winrt::WUX::Media::Brush ThemeColor::Evaluate(const winrt::WUX::ResourceDictiona { case ThemeColorType::Accent: { + // NOTE: There is no canonical way to get the unfocused ACCENT titlebar + // color in Windows. Edge uses it's own heuristic, and in Windows 11, + // much of this logic is rapidly changing. We're not gonna mess with + // that, since it seems there's no good way to reverse engineer that. til::color accentColor = forTitlebar ? _getAccentColorForTitlebar() : til::color{ winrt::unbox_value(res.Lookup(accentColorKey)) }; From 32ea170ec1af423fd92b02e19cc9e8cee41a0221 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 7 Jul 2022 12:22:39 -0500 Subject: [PATCH 61/61] how the --- src/cascadia/WindowsTerminal/pch.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cascadia/WindowsTerminal/pch.h b/src/cascadia/WindowsTerminal/pch.h index a583ec8203b..d5490a62039 100644 --- a/src/cascadia/WindowsTerminal/pch.h +++ b/src/cascadia/WindowsTerminal/pch.h @@ -66,7 +66,6 @@ Module Name: #include #include #include -#include #include #include #include