diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 3af4b73e9..e082a8ad1 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -451,7 +451,31 @@ namespace winrt::TerminalApp::implementation { if (const auto scheme = _settings.GlobalSettings().ColorSchemes().TryLookup(realArgs.SchemeName())) { - const auto res = _ApplyToActiveControls([&](auto& /*control*/) { + const auto res = _ApplyToActiveControls([&](auto& control) { + Core::Scheme coreScheme{}; + + coreScheme.Foreground = scheme.Foreground(); + coreScheme.Background = scheme.Background(); + coreScheme.CursorColor = scheme.CursorColor(); + coreScheme.SelectionBackground = scheme.SelectionBackground(); + coreScheme.Black = scheme.Table()[0]; + coreScheme.Red = scheme.Table()[1]; + coreScheme.Green = scheme.Table()[2]; + coreScheme.Yellow = scheme.Table()[3]; + coreScheme.Blue = scheme.Table()[4]; + coreScheme.Purple = scheme.Table()[5]; + coreScheme.Cyan = scheme.Table()[6]; + coreScheme.White = scheme.Table()[7]; + coreScheme.BrightBlack = scheme.Table()[8]; + coreScheme.BrightRed = scheme.Table()[9]; + coreScheme.BrightGreen = scheme.Table()[10]; + coreScheme.BrightYellow = scheme.Table()[11]; + coreScheme.BrightBlue = scheme.Table()[12]; + coreScheme.BrightPurple = scheme.Table()[13]; + coreScheme.BrightCyan = scheme.Table()[14]; + coreScheme.BrightWhite = scheme.Table()[15]; + + control.ColorScheme(coreScheme); //// Start by getting the current settings of the control //auto controlSettings = control.Settings().as(); //auto parentSettings = controlSettings; @@ -479,7 +503,7 @@ namespace winrt::TerminalApp::implementation // We'll need a dedicated method for this. The Control's // settings are hosted in the Core, which could be OOP. // We'll need to manually tell the control to update its - // core's scheme. + // core's scheme. }); args.Handled(res); } diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index 9948d40b6..8c25cea00 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -159,6 +159,7 @@ NewTerminalArgs Pane::GetTerminalArgsForPane() const // TODO!: Will we be able to persist this? Or will runtime-changed settings // always be lost? Think like, changing the font size with an action. That's // lost. + // Come back to this after previewing. May end up with some data we can use there. // // if (controlSettings.AppliedColorScheme()) // { diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 700bb9db6..6b851190f 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -1595,4 +1595,51 @@ namespace winrt::Microsoft::Terminal::Control::implementation return VerifyVersionInfoW(&osver, VER_BUILDNUMBER, dwlConditionMask) != FALSE; } + + Core::Scheme ControlCore::ColorScheme() const noexcept + { + auto s = _terminal->GetColorScheme(); + // This might be a tad bit of a hack. This only evet gets called by set + // color scheme / preview color scheme, and in that case, we know the + // control _is_ focused. + s.SelectionBackground = _settings->FocusedAppearance()->SelectionBackground(); + return s; + } + + void ControlCore::ColorScheme(Core::Scheme scheme) const noexcept + { + _terminal->ApplyScheme(scheme); + + // _settings->FocusedAppearance()->DefaultForeground(colorScheme.Foreground); + // _settings->FocusedAppearance()->DefaultBackground(colorScheme.Background); + // _settings->FocusedAppearance()->CursorColor(colorScheme.CursorColor); + // _settings->FocusedAppearance()->SelectionBackground(colorScheme.SelectionBackground); + + // // _defaultFg = colorScheme.Foreground; + // // // Set the default background as transparent to prevent the + // // // DX layer from overwriting the background image or acrylic effect + // // til::color newBackgroundColor{ colorScheme.Background }; + // // _defaultBg = newBackgroundColor.with_alpha(0); + + // _settings->FocusedAppearance()->Table()[0] = scheme.Black; + // _settings->FocusedAppearance()->Table()[1] = scheme.Red; + // _settings->FocusedAppearance()->Table()[2] = scheme.Green; + // _settings->FocusedAppearance()->Table()[3] = scheme.Yellow; + // _settings->FocusedAppearance()->Table()[4] = scheme.Blue; + // _settings->FocusedAppearance()->Table()[5] = scheme.Purple; + // _settings->FocusedAppearance()->Table()[6] = scheme.Cyan; + // _settings->FocusedAppearance()->Table()[7] = scheme.White; + // _settings->FocusedAppearance()->Table()[8] = scheme.BrightBlack; + // _settings->FocusedAppearance()->Table()[9] = scheme.BrightRed; + // _settings->FocusedAppearance()->Table()[10] = scheme.BrightGreen; + // _settings->FocusedAppearance()->Table()[11] = scheme.BrightYellow; + // _settings->FocusedAppearance()->Table()[12] = scheme.BrightBlue; + // _settings->FocusedAppearance()->Table()[13] = scheme.BrightPurple; + // _settings->FocusedAppearance()->Table()[14] = scheme.BrightCyan; + // _settings->FocusedAppearance()->Table()[15] = scheme.BrightWhite; + + // _buffer->GetCursor().SetColor(til::color{ colorScheme.CursorColor }); + + _renderer->TriggerRedrawAll(); + } } diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index e184ce347..4f50c76aa 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -65,6 +65,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation }; Control::IControlAppearance FocusedAppearance() const { return *_settings->FocusedAppearance(); }; Control::IControlAppearance UnfocusedAppearance() const { return *_settings->UnfocusedAppearance(); }; + winrt::Microsoft::Terminal::Core::Scheme ColorScheme() const noexcept; + void ColorScheme(winrt::Microsoft::Terminal::Core::Scheme scheme) const noexcept; void SizeChanged(const double width, const double height); void ScaleChanged(const double scale); diff --git a/src/cascadia/TerminalControl/ICoreState.idl b/src/cascadia/TerminalControl/ICoreState.idl index ad5217bf6..ac9a2a346 100644 --- a/src/cascadia/TerminalControl/ICoreState.idl +++ b/src/cascadia/TerminalControl/ICoreState.idl @@ -22,5 +22,7 @@ namespace Microsoft.Terminal.Control Boolean BracketedPasteEnabled { get; }; Microsoft.Terminal.TerminalConnection.ConnectionState ConnectionState { get; }; + + Microsoft.Terminal.Core.Scheme ColorScheme { get; set; }; }; } diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 91805f1e0..22d70e09b 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1501,13 +1501,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation _blinkTimer->Start(); } - // Only update the appearance here if an unfocused config exists - - // if an unfocused config does not exist then we never would have switched - // appearances anyway so there's no need to switch back upon gaining focus - if (_core.UnfocusedAppearance()) - { - UpdateAppearance(_core.FocusedAppearance()); - } + // // Only update the appearance here if an unfocused config exists - + // // if an unfocused config does not exist then we never would have switched + // // appearances anyway so there's no need to switch back upon gaining focus + // if (_core.UnfocusedAppearance()) + // { + // UpdateAppearance(_core.FocusedAppearance()); + // } } // Method Description: @@ -2594,4 +2594,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation { return _core.ReadEntireBuffer(); } + + Core::Scheme TermControl::ColorScheme() const noexcept + { + return _core.ColorScheme(); + } + + void TermControl::ColorScheme(Core::Scheme scheme) const noexcept + { + _core.ColorScheme(scheme); + } } diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index e08b0455a..5cce42cc1 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -112,6 +112,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation hstring ReadEntireBuffer() const; + winrt::Microsoft::Terminal::Core::Scheme ColorScheme() const noexcept; + void ColorScheme(winrt::Microsoft::Terminal::Core::Scheme scheme) const noexcept; + // -------------------------------- WinRT Events --------------------------------- // clang-format off WINRT_CALLBACK(FontSizeChanged, Control::FontSizeChangedEventArgs); diff --git a/src/cascadia/TerminalCore/ICoreAppearance.idl b/src/cascadia/TerminalCore/ICoreAppearance.idl index ddeb5b838..f58e9a490 100644 --- a/src/cascadia/TerminalCore/ICoreAppearance.idl +++ b/src/cascadia/TerminalCore/ICoreAppearance.idl @@ -50,6 +50,37 @@ namespace Microsoft.Terminal.Core UInt32 Value; }; + struct Scheme + { + Microsoft.Terminal.Core.Color Foreground; + Microsoft.Terminal.Core.Color Background; + + Microsoft.Terminal.Core.Color SelectionBackground; + + Microsoft.Terminal.Core.Color CursorColor; + + // Table: A WinRT struct doesn't allow pointers (like an array) in + // structs, but we very much would like this object to be a struct. So + // we'll call out each color individually. There's only 16, it's not + // that bad. + Microsoft.Terminal.Core.Color Black; + Microsoft.Terminal.Core.Color Red; + Microsoft.Terminal.Core.Color Green; + Microsoft.Terminal.Core.Color Yellow; + Microsoft.Terminal.Core.Color Blue; + Microsoft.Terminal.Core.Color Purple; + Microsoft.Terminal.Core.Color Cyan; + Microsoft.Terminal.Core.Color White; + Microsoft.Terminal.Core.Color BrightBlack; + Microsoft.Terminal.Core.Color BrightRed; + Microsoft.Terminal.Core.Color BrightGreen; + Microsoft.Terminal.Core.Color BrightYellow; + Microsoft.Terminal.Core.Color BrightBlue; + Microsoft.Terminal.Core.Color BrightPurple; + Microsoft.Terminal.Core.Color BrightCyan; + Microsoft.Terminal.Core.Color BrightWhite; + }; + declare { // Forward declare this parameterized specialization so that it lives diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 3433b60d9..eb1794be2 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -170,13 +170,14 @@ void Terminal::UpdateSettings(ICoreSettings settings) // - appearance: an ICoreAppearance with new settings values for us to use. void Terminal::UpdateAppearance(const ICoreAppearance& appearance) { + _intenseIsBright = appearance.IntenseIsBright(); + _adjustIndistinguishableColors = appearance.AdjustIndistinguishableColors(); + // Set the default background as transparent to prevent the // DX layer from overwriting the background image or acrylic effect til::color newBackgroundColor{ appearance.DefaultBackground() }; _defaultBg = newBackgroundColor.with_alpha(0); _defaultFg = appearance.DefaultForeground(); - _intenseIsBright = appearance.IntenseIsBright(); - _adjustIndistinguishableColors = appearance.AdjustIndistinguishableColors(); for (int i = 0; i < 16; i++) { @@ -1292,3 +1293,65 @@ const size_t Microsoft::Terminal::Core::Terminal::GetTaskbarProgress() const noe { return _taskbarProgress; } + +Scheme Terminal::GetColorScheme() const noexcept +{ + Scheme s; + + s.Foreground = til::color{ _defaultFg }; + s.Background = til::color{ _defaultBg }; + // SelectionBackground is stored in the ControlAppearance + // s.SelectionBackground; + s.CursorColor = til::color{ _buffer->GetCursor().GetColor() }; + s.Black = til::color{ _colorTable[0] }; + s.Red = til::color{ _colorTable[1] }; + s.Green = til::color{ _colorTable[2] }; + s.Yellow = til::color{ _colorTable[3] }; + s.Blue = til::color{ _colorTable[4] }; + s.Purple = til::color{ _colorTable[5] }; + s.Cyan = til::color{ _colorTable[6] }; + s.White = til::color{ _colorTable[7] }; + s.BrightBlack = til::color{ _colorTable[8] }; + s.BrightRed = til::color{ _colorTable[9] }; + s.BrightGreen = til::color{ _colorTable[10] }; + s.BrightYellow = til::color{ _colorTable[11] }; + s.BrightBlue = til::color{ _colorTable[12] }; + s.BrightPurple = til::color{ _colorTable[13] }; + s.BrightCyan = til::color{ _colorTable[14] }; + s.BrightWhite = til::color{ _colorTable[15] }; + return s; +} + +void Terminal::ApplyScheme(Scheme colorScheme) +{ + _defaultFg = colorScheme.Foreground; + // Set the default background as transparent to prevent the + // DX layer from overwriting the background image or acrylic effect + til::color newBackgroundColor{ colorScheme.Background }; + _defaultBg = newBackgroundColor.with_alpha(0); + + _colorTable[0] = til::color{ colorScheme.Black }; + _colorTable[1] = til::color{ colorScheme.Red }; + _colorTable[2] = til::color{ colorScheme.Green }; + _colorTable[3] = til::color{ colorScheme.Yellow }; + _colorTable[4] = til::color{ colorScheme.Blue }; + _colorTable[5] = til::color{ colorScheme.Purple }; + _colorTable[6] = til::color{ colorScheme.Cyan }; + _colorTable[7] = til::color{ colorScheme.White }; + _colorTable[8] = til::color{ colorScheme.BrightBlack }; + _colorTable[9] = til::color{ colorScheme.BrightRed }; + _colorTable[10] = til::color{ colorScheme.BrightGreen }; + _colorTable[11] = til::color{ colorScheme.BrightYellow }; + _colorTable[12] = til::color{ colorScheme.BrightBlue }; + _colorTable[13] = til::color{ colorScheme.BrightPurple }; + _colorTable[14] = til::color{ colorScheme.BrightCyan }; + _colorTable[15] = til::color{ colorScheme.BrightWhite }; + + _buffer->GetCursor().SetColor(til::color{ colorScheme.CursorColor }); + + if (_adjustIndistinguishableColors) + { + _MakeAdjustedColorArray(); + } + +} diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 3a2f3dff1..77b7a15c7 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -30,6 +30,7 @@ namespace winrt::Microsoft::Terminal::Core { struct ICoreSettings; struct ICoreAppearance; + struct Scheme; } namespace Microsoft::Terminal::Core @@ -221,6 +222,9 @@ public: const std::optional GetTabColor() const noexcept; til::color GetDefaultBackground() const noexcept; + winrt::Microsoft::Terminal::Core::Scheme GetColorScheme() const noexcept; + void ApplyScheme(winrt::Microsoft::Terminal::Core::Scheme scheme); + Microsoft::Console::Render::BlinkingState& GetBlinkingState() const noexcept; const size_t GetTaskbarState() const noexcept;