diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index dd42f8f49..6f51d2222 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -158,8 +158,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - Style our UI elements based on the values in our _settings, and set up // other control-specific settings. This method will be called whenever // the settings are reloaded. - // * Sets up the background of the control with the provided BG color, - // acrylic or not, and if acrylic, then uses the opacity from _settings. + // * Calls _BackgroundColorChanged to style the background of the control // - Core settings will be passed to the terminal in _InitializeTerminal // Arguments: // - @@ -167,37 +166,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - void TermControl::_ApplyUISettings() { - winrt::Windows::UI::Color bgColor{}; uint32_t bg = _settings.DefaultBackground(); - const auto R = GetRValue(bg); - const auto G = GetGValue(bg); - const auto B = GetBValue(bg); - bgColor.R = R; - bgColor.G = G; - bgColor.B = B; - bgColor.A = 255; - - if (_settings.UseAcrylic()) - { - Media::AcrylicBrush acrylic{}; - acrylic.BackgroundSource(Media::AcrylicBackgroundSource::HostBackdrop); - acrylic.FallbackColor(bgColor); - acrylic.TintColor(bgColor); - acrylic.TintOpacity(_settings.TintOpacity()); - _root.Background(acrylic); - - // If we're acrylic, we want to make sure that the default BG color - // is transparent, so we can see the acrylic effect on text with the - // default BG color. - _settings.DefaultBackground(ARGB(0, R, G, B)); - } - else - { - Media::SolidColorBrush solidColor{}; - solidColor.Color(bgColor); - _root.Background(solidColor); - _settings.DefaultBackground(RGB(R, G, B)); - } + _BackgroundColorChanged(bg); // Apply padding to the root Grid auto thickness = _ParseThicknessFromPadding(_settings.Padding()); @@ -216,6 +186,50 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation _desiredFont = { _actualFont }; } + // Method Description: + // - Style the background of the control with the provided background color + // - Respects the settings for acrylic and opacity from _settings + // Arguments: + // - color: The background color to use as a uint32 (aka DWORD COLORREF) + // Return Value: + // - + void TermControl::_BackgroundColorChanged(const uint32_t color) + { + _root.Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [this, color]() { + const auto R = GetRValue(color); + const auto G = GetGValue(color); + const auto B = GetBValue(color); + + winrt::Windows::UI::Color bgColor{}; + bgColor.R = R; + bgColor.G = G; + bgColor.B = B; + bgColor.A = 255; + + if (_settings.UseAcrylic()) + { + Media::AcrylicBrush acrylic{}; + acrylic.BackgroundSource(Media::AcrylicBackgroundSource::HostBackdrop); + acrylic.FallbackColor(bgColor); + acrylic.TintColor(bgColor); + acrylic.TintOpacity(_settings.TintOpacity()); + _root.Background(acrylic); + + // If we're acrylic, we want to make sure that the default BG color + // is transparent, so we can see the acrylic effect on text with the + // default BG color. + _settings.DefaultBackground(ARGB(0, R, G, B)); + } + else + { + Media::SolidColorBrush solidColor{}; + solidColor.Color(bgColor); + _root.Background(solidColor); + _settings.DefaultBackground(RGB(R, G, B)); + } + }); + } + // Method Description: // - Create a connection based on the values in our settings object. // * Gets the commandline and working directory out of the _settings and @@ -406,6 +420,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation auto pfnTitleChanged = std::bind(&TermControl::_TerminalTitleChanged, this, std::placeholders::_1); _terminal->SetTitleChangedCallback(pfnTitleChanged); + auto pfnBackgroundColorChanged = std::bind(&TermControl::_BackgroundColorChanged, this, std::placeholders::_1); + _terminal->SetBackgroundCallback(pfnBackgroundColorChanged); + auto pfnScrollPositionChanged = std::bind(&TermControl::_TerminalScrollPositionChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); _terminal->SetScrollPositionChangedCallback(pfnScrollPositionChanged); diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 00d566980..29bfc91b8 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -95,6 +95,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void _Create(); void _ApplyUISettings(); + void _BackgroundColorChanged(const uint32_t color); void _ApplyConnectionSettings(); void _InitializeTerminal(); void _UpdateFont(); diff --git a/src/cascadia/TerminalCore/ITerminalApi.hpp b/src/cascadia/TerminalCore/ITerminalApi.hpp index f356c8be0..9e4e2a376 100644 --- a/src/cascadia/TerminalCore/ITerminalApi.hpp +++ b/src/cascadia/TerminalCore/ITerminalApi.hpp @@ -31,5 +31,8 @@ namespace Microsoft::Terminal::Core virtual bool SetColorTableEntry(const size_t tableIndex, const DWORD dwColor) = 0; virtual bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) = 0; + + virtual bool SetDefaultForeground(const DWORD dwColor) = 0; + virtual bool SetDefaultBackground(const DWORD dwColor) = 0; }; } diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 75d4345a1..12107ed26 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -442,6 +442,15 @@ void Terminal::SetScrollPositionChangedCallback(std::function pfn) noexcept +{ + _pfnBackgroundColorChanged = pfn; +} + // Method Description: // - Checks if selection is active // Return Value: diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 7e880962e..593321694 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -70,8 +70,10 @@ public: COORD GetCursorPosition() override; bool EraseCharacters(const unsigned int numChars) override; bool SetWindowTitle(std::wstring_view title) override; - bool SetColorTableEntry(const size_t tableIndex, const DWORD dwColor) override; + bool SetColorTableEntry(const size_t tableIndex, const COLORREF dwColor) override; bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) override; + bool SetDefaultForeground(const COLORREF dwColor) override; + bool SetDefaultBackground(const COLORREF dwColor) override; #pragma endregion #pragma region ITerminalInput @@ -113,6 +115,7 @@ public: void SetWriteInputCallback(std::function pfn) noexcept; void SetTitleChangedCallback(std::function pfn) noexcept; void SetScrollPositionChangedCallback(std::function pfn) noexcept; + void SetBackgroundCallback(std::function pfn) noexcept; void SetCursorVisible(const bool isVisible) noexcept; bool IsCursorBlinkingAllowed() const noexcept; @@ -131,6 +134,7 @@ public: std::function _pfnWriteInput; std::function _pfnTitleChanged; std::function _pfnScrollPositionChanged; + std::function _pfnBackgroundColorChanged; std::unique_ptr<::Microsoft::Console::VirtualTerminal::StateMachine> _stateMachine; std::unique_ptr<::Microsoft::Console::VirtualTerminal::TerminalInput> _terminalInput; diff --git a/src/cascadia/TerminalCore/TerminalApi.cpp b/src/cascadia/TerminalCore/TerminalApi.cpp index d6793bb63..745696ff9 100644 --- a/src/cascadia/TerminalCore/TerminalApi.cpp +++ b/src/cascadia/TerminalCore/TerminalApi.cpp @@ -157,7 +157,7 @@ bool Terminal::SetWindowTitle(std::wstring_view title) // - dwColor: the new COLORREF to use as that color table value. // Return Value: // - true iff we successfully updated the color table entry. -bool Terminal::SetColorTableEntry(const size_t tableIndex, const DWORD dwColor) +bool Terminal::SetColorTableEntry(const size_t tableIndex, const COLORREF dwColor) { if (tableIndex > _colorTable.size()) { @@ -219,3 +219,34 @@ bool Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) return true; } + +// Method Description: +// - Updates the default foreground color from a COLORREF, format 0x00BBGGRR. +// Arguments: +// - dwColor: the new COLORREF to use as the default foreground color +// Return Value: +// - true +bool Terminal::SetDefaultForeground(const COLORREF dwColor) +{ + _defaultFg = dwColor; + + // Repaint everything - the colors might have changed + _buffer->GetRenderTarget().TriggerRedrawAll(); + return true; +} + +// Method Description: +// - Updates the default background color from a COLORREF, format 0x00BBGGRR. +// Arguments: +// - dwColor: the new COLORREF to use as the default background color +// Return Value: +// - true +bool Terminal::SetDefaultBackground(const COLORREF dwColor) +{ + _defaultBg = dwColor; + _pfnBackgroundColorChanged(dwColor); + + // Repaint everything - the colors might have changed + _buffer->GetRenderTarget().TriggerRedrawAll(); + return true; +} diff --git a/src/cascadia/TerminalCore/TerminalDispatch.cpp b/src/cascadia/TerminalCore/TerminalDispatch.cpp index 8b836310c..154ee53e0 100644 --- a/src/cascadia/TerminalCore/TerminalDispatch.cpp +++ b/src/cascadia/TerminalCore/TerminalDispatch.cpp @@ -64,7 +64,7 @@ bool TerminalDispatch::SetWindowTitle(std::wstring_view title) // - tableIndex: The VT color table index // - dwColor: The new RGB color value to use. // Return Value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool TerminalDispatch::SetColorTableEntry(const size_t tableIndex, const DWORD dwColor) { @@ -75,3 +75,25 @@ bool TerminalDispatch::SetCursorStyle(const DispatchTypes::CursorStyle cursorSty { return _terminalApi.SetCursorStyle(cursorStyle); } + +// Method Description: +// - Sets the default foreground color to a new value +// Arguments: +// - dwColor: The new RGB color value to use, in 0x00BBGGRR form +// Return Value: +// True if handled successfully. False otherwise. +bool TerminalDispatch::SetDefaultForeground(const DWORD dwColor) +{ + return _terminalApi.SetDefaultForeground(dwColor); +} + +// Method Description: +// - Sets the default background color to a new value +// Arguments: +// - dwColor: The new RGB color value to use, in 0x00BBGGRR form +// Return Value: +// True if handled successfully. False otherwise. +bool TerminalDispatch::SetDefaultBackground(const DWORD dwColor) +{ + return _terminalApi.SetDefaultBackground(dwColor); +} diff --git a/src/cascadia/TerminalCore/TerminalDispatch.hpp b/src/cascadia/TerminalCore/TerminalDispatch.hpp index e24a3e14e..68bfcfb52 100644 --- a/src/cascadia/TerminalCore/TerminalDispatch.hpp +++ b/src/cascadia/TerminalCore/TerminalDispatch.hpp @@ -27,6 +27,9 @@ public: bool SetColorTableEntry(const size_t tableIndex, const DWORD dwColor) override; bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) override; + bool SetDefaultForeground(const DWORD dwColor) override; + bool SetDefaultBackground(const DWORD dwColor) override; + private: ::Microsoft::Terminal::Core::ITerminalApi& _terminalApi; diff --git a/src/host/getset.cpp b/src/host/getset.cpp index e36fab96f..d2ec5be42 100644 --- a/src/host/getset.cpp +++ b/src/host/getset.cpp @@ -2170,3 +2170,59 @@ HRESULT DoSrvPrivateSetColorTableEntry(const short index, const COLORREF value) CATCH_RETURN(); } + +// Method Description: +// - Sets the default foreground color to the color specified in value. +// Arguments: +// - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR. +// Return Value: +// - S_OK +[[nodiscard]] +HRESULT DoSrvPrivateSetDefaultForegroundColor(const COLORREF value) noexcept +{ + try + { + Globals& g = ServiceLocator::LocateGlobals(); + CONSOLE_INFORMATION& gci = g.getConsoleInformation(); + + gci.SetDefaultForegroundColor(value); + + // Update the screen colors if we're not a pty + // No need to force a redraw in pty mode. + if (g.pRender && !gci.IsInVtIoMode()) + { + g.pRender->TriggerRedrawAll(); + } + + return S_OK; + } + CATCH_RETURN(); +} + +// Method Description: +// - Sets the default background color to the color specified in value. +// Arguments: +// - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR. +// Return Value: +// - S_OK +[[nodiscard]] +HRESULT DoSrvPrivateSetDefaultBackgroundColor(const COLORREF value) noexcept +{ + try + { + Globals& g = ServiceLocator::LocateGlobals(); + CONSOLE_INFORMATION& gci = g.getConsoleInformation(); + + gci.SetDefaultBackgroundColor(value); + + // Update the screen colors if we're not a pty + // No need to force a redraw in pty mode. + if (g.pRender && !gci.IsInVtIoMode()) + { + g.pRender->TriggerRedrawAll(); + } + + return S_OK; + } + CATCH_RETURN(); +} diff --git a/src/host/getset.h b/src/host/getset.h index 1676c8b63..22784375e 100644 --- a/src/host/getset.h +++ b/src/host/getset.h @@ -99,3 +99,9 @@ void DoSrvPrivateMoveToBottom(SCREEN_INFORMATION& screenInfo); [[nodiscard]] HRESULT DoSrvPrivateSetColorTableEntry(const short index, const COLORREF value) noexcept; + +[[nodiscard]] +HRESULT DoSrvPrivateSetDefaultForegroundColor(const COLORREF value) noexcept; + +[[nodiscard]] +HRESULT DoSrvPrivateSetDefaultBackgroundColor(const COLORREF value) noexcept; diff --git a/src/host/outputStream.cpp b/src/host/outputStream.cpp index 1ddf0fc48..58f0bb91e 100644 --- a/src/host/outputStream.cpp +++ b/src/host/outputStream.cpp @@ -761,3 +761,27 @@ BOOL ConhostInternalGetSet::PrivateSetColorTableEntry(const short index, const C { return SUCCEEDED(DoSrvPrivateSetColorTableEntry(index, value)); } + +// Method Description: +// - Connects the PrivateSetDefaultForeground call directly into our Driver Message servicing +// call inside Conhost.exe +// Arguments: +// - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR. +// Return Value: +// - TRUE if successful (see DoSrvPrivateSetDefaultForegroundColor). FALSE otherwise. +BOOL ConhostInternalGetSet::PrivateSetDefaultForeground(const COLORREF value) const noexcept +{ + return SUCCEEDED(DoSrvPrivateSetDefaultForegroundColor(value)); +} + +// Method Description: +// - Connects the PrivateSetDefaultBackground call directly into our Driver Message servicing +// call inside Conhost.exe +// Arguments: +// - value: the new RGB value to use, as a COLORREF, format 0x00BBGGRR. +// Return Value: +// - TRUE if successful (see DoSrvPrivateSetDefaultBackgroundColor). FALSE otherwise. +BOOL ConhostInternalGetSet::PrivateSetDefaultBackground(const COLORREF value) const noexcept +{ + return SUCCEEDED(DoSrvPrivateSetDefaultBackgroundColor(value)); +} diff --git a/src/host/outputStream.hpp b/src/host/outputStream.hpp index b450edced..b87d10082 100644 --- a/src/host/outputStream.hpp +++ b/src/host/outputStream.hpp @@ -157,6 +157,10 @@ public: BOOL PrivateSetColorTableEntry(const short index, const COLORREF value) const noexcept override; + BOOL PrivateSetDefaultForeground(const COLORREF value) const noexcept override; + + BOOL PrivateSetDefaultBackground(const COLORREF value) const noexcept override; + private: Microsoft::Console::IIoProvider& _io; }; diff --git a/src/host/ut_host/ScreenBufferTests.cpp b/src/host/ut_host/ScreenBufferTests.cpp index 200059579..c77f42e54 100644 --- a/src/host/ut_host/ScreenBufferTests.cpp +++ b/src/host/ut_host/ScreenBufferTests.cpp @@ -149,6 +149,10 @@ class ScreenBufferTests TEST_METHOD(SetColorTableThreeDigits); + TEST_METHOD(SetDefaultForegroundColor); + + TEST_METHOD(SetDefaultBackgroundColor); + TEST_METHOD(DeleteCharsNearEndOfLine); TEST_METHOD(DeleteCharsNearEndOfLineSimpleFirstCase); TEST_METHOD(DeleteCharsNearEndOfLineSimpleSecondCase); @@ -2502,6 +2506,126 @@ void ScreenBufferTests::SetColorTableThreeDigits() } + +void ScreenBufferTests::SetDefaultForegroundColor() +{ + // Setting the default foreground color should work + + CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); + gci.LockConsole(); // Lock must be taken to swap buffers. + auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); }); + + SCREEN_INFORMATION& mainBuffer = gci.GetActiveOutputBuffer(); + VERIFY_IS_FALSE(mainBuffer._IsAltBuffer()); + WI_SetFlag(mainBuffer.OutputMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING); + VERIFY_IS_TRUE(WI_IsFlagSet(mainBuffer.OutputMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING)); + + StateMachine& stateMachine = mainBuffer.GetStateMachine(); + + COLORREF originalColor = gci.GetDefaultForegroundColor(); + COLORREF newColor = gci.GetDefaultForegroundColor(); + COLORREF testColor = RGB(0x33, 0x66, 0x99); + VERIFY_ARE_NOT_EQUAL(originalColor, testColor); + + Log::Comment(L"Valid Hexadecimal Notation"); + std::wstring seq = L"\x1b]10;rgb:33/66/99\x1b\\"; + stateMachine.ProcessString(seq); + + newColor = gci.GetDefaultForegroundColor(); + VERIFY_ARE_EQUAL(testColor, newColor); + + Log::Comment(L"Valid Hexadecimal Notation"); + originalColor = newColor; + testColor = RGB(0xff, 0xff, 0xff); + seq = L"\x1b]10;rgb:ff/ff/ff\x1b\\"; + stateMachine.ProcessString(seq); + + newColor = gci.GetDefaultForegroundColor(); + VERIFY_ARE_EQUAL(testColor, newColor); + + Log::Comment(L"Invalid Decimal Notation"); + originalColor = newColor; + testColor = RGB(153, 102, 51); + seq = L"\x1b]10;rgb:153/102/51\x1b\\"; + stateMachine.ProcessString(seq); + + newColor = gci.GetDefaultForegroundColor(); + VERIFY_ARE_NOT_EQUAL(testColor, newColor); + // it will, in fact leave the color the way it was + VERIFY_ARE_EQUAL(originalColor, newColor); + + Log::Comment(L"Invalid syntax"); + testColor = RGB(153, 102, 51); + seq = L"\x1b]10;99/66/33\x1b\\"; + stateMachine.ProcessString(seq); + + newColor = gci.GetDefaultForegroundColor(); + VERIFY_ARE_NOT_EQUAL(testColor, newColor); + // it will, in fact leave the color the way it was + VERIFY_ARE_EQUAL(originalColor, newColor); +} + + +void ScreenBufferTests::SetDefaultBackgroundColor() +{ + // Setting the default Background color should work + + CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); + gci.LockConsole(); // Lock must be taken to swap buffers. + auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); }); + + SCREEN_INFORMATION& mainBuffer = gci.GetActiveOutputBuffer(); + VERIFY_IS_FALSE(mainBuffer._IsAltBuffer()); + WI_SetFlag(mainBuffer.OutputMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING); + VERIFY_IS_TRUE(WI_IsFlagSet(mainBuffer.OutputMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING)); + + StateMachine& stateMachine = mainBuffer.GetStateMachine(); + + COLORREF originalColor = gci.GetDefaultBackgroundColor(); + COLORREF newColor = gci.GetDefaultBackgroundColor(); + COLORREF testColor = RGB(0x33, 0x66, 0x99); + VERIFY_ARE_NOT_EQUAL(originalColor, testColor); + + Log::Comment(L"Valid Hexadecimal Notation"); + std::wstring seq = L"\x1b]11;rgb:33/66/99\x1b\\"; + stateMachine.ProcessString(seq); + + newColor = gci.GetDefaultBackgroundColor(); + VERIFY_ARE_EQUAL(testColor, newColor); + + Log::Comment(L"Valid Hexadecimal Notation"); + originalColor = newColor; + testColor = RGB(0xff, 0xff, 0xff); + seq = L"\x1b]11;rgb:ff/ff/ff\x1b\\"; + stateMachine.ProcessString(seq); + + newColor = gci.GetDefaultBackgroundColor(); + VERIFY_ARE_EQUAL(testColor, newColor); + + Log::Comment(L"Invalid Decimal Notation"); + originalColor = newColor; + testColor = RGB(153, 102, 51); + seq = L"\x1b]11;rgb:153/102/51\x1b\\"; + stateMachine.ProcessString(seq); + + newColor = gci.GetDefaultBackgroundColor(); + VERIFY_ARE_NOT_EQUAL(testColor, newColor); + // it will, in fact leave the color the way it was + VERIFY_ARE_EQUAL(originalColor, newColor); + + Log::Comment(L"Invalid Syntax"); + testColor = RGB(153, 102, 51); + seq = L"\x1b]11;99/66/33\x1b\\"; + stateMachine.ProcessString(seq); + + newColor = gci.GetDefaultBackgroundColor(); + VERIFY_ARE_NOT_EQUAL(testColor, newColor); + // it will, in fact leave the color the way it was + VERIFY_ARE_EQUAL(originalColor, newColor); +} + + + void ScreenBufferTests::DeleteCharsNearEndOfLine() { // Created for MSFT:19888564. diff --git a/src/terminal/adapter/ITermDispatch.hpp b/src/terminal/adapter/ITermDispatch.hpp index 6f4bcd9a2..fec42544b 100644 --- a/src/terminal/adapter/ITermDispatch.hpp +++ b/src/terminal/adapter/ITermDispatch.hpp @@ -65,6 +65,8 @@ public: virtual bool EnableAnyEventMouseMode(const bool fEnabled) = 0; // ?1003 virtual bool EnableAlternateScroll(const bool fEnabled) = 0; // ?1007 virtual bool SetColorTableEntry(const size_t tableIndex, const DWORD dwColor) = 0; // OSCColorTable + virtual bool SetDefaultForeground(const DWORD dwColor) = 0; // OSCDefaultForeground + virtual bool SetDefaultBackground(const DWORD dwColor) = 0; // OSCDefaultBackground virtual bool EraseInDisplay(const DispatchTypes::EraseType eraseType) = 0; // ED virtual bool EraseInLine(const DispatchTypes::EraseType eraseType) = 0; // EL @@ -97,4 +99,3 @@ public: }; inline Microsoft::Console::VirtualTerminal::ITermDispatch::~ITermDispatch() { } - diff --git a/src/terminal/adapter/adaptDispatch.cpp b/src/terminal/adapter/adaptDispatch.cpp index 23489a102..8e1da0e32 100644 --- a/src/terminal/adapter/adaptDispatch.cpp +++ b/src/terminal/adapter/adaptDispatch.cpp @@ -1389,7 +1389,7 @@ bool AdaptDispatch::UseMainScreenBuffer() //Arguments: // - None // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::HorizontalTabSet() { return !!_conApi->PrivateHorizontalTabSet(); @@ -1403,7 +1403,7 @@ bool AdaptDispatch::HorizontalTabSet() //Arguments: // - sNumTabs - the number of tabs to perform // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::ForwardTab(const SHORT sNumTabs) { return !!_conApi->PrivateForwardTab(sNumTabs); @@ -1415,7 +1415,7 @@ bool AdaptDispatch::ForwardTab(const SHORT sNumTabs) //Arguments: // - sNumTabs - the number of tabs to perform // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::BackwardsTab(const SHORT sNumTabs) { return !!_conApi->PrivateBackwardsTab(sNumTabs); @@ -1428,7 +1428,7 @@ bool AdaptDispatch::BackwardsTab(const SHORT sNumTabs) //Arguments: // - sClearType - Whether to clear the current column, or all columns, defined in DispatchTypes::TabClearType // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::TabClear(const SHORT sClearType) { bool fSuccess = false; @@ -1453,7 +1453,7 @@ bool AdaptDispatch::TabClear(const SHORT sClearType) //Arguments: // - wchCharset - The character indicating the charset we should switch to. // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::DesignateCharset(const wchar_t wchCharset) { return _TermOutput.DesignateCharset(wchCharset); @@ -1489,7 +1489,7 @@ bool AdaptDispatch::DesignateCharset(const wchar_t wchCharset) //Arguments: // // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::SoftReset() { bool fSuccess = CursorVisibility(true); // Cursor enabled. @@ -1542,7 +1542,7 @@ bool AdaptDispatch::SoftReset() //Arguments: // // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::HardReset() { // Clears the screen - Needs to be done in two operations. @@ -1581,7 +1581,7 @@ bool AdaptDispatch::HardReset() //Arguments: // // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::_EraseScrollback() { CONSOLE_SCREEN_BUFFER_INFOEX csbiex = { 0 }; @@ -1667,7 +1667,7 @@ bool AdaptDispatch::_EraseScrollback() //Arguments: // // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::_EraseAll() { return !!_conApi->PrivateEraseAll(); @@ -1678,7 +1678,7 @@ bool AdaptDispatch::_EraseAll() //Arguments: // - fEnabled - true to enable, false to disable. // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::EnableVT200MouseMode(const bool fEnabled) { return !!_conApi->PrivateEnableVT200MouseMode(fEnabled); @@ -1690,7 +1690,7 @@ bool AdaptDispatch::EnableVT200MouseMode(const bool fEnabled) //Arguments: // - fEnabled - true to enable, false to disable. // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::EnableUTF8ExtendedMouseMode(const bool fEnabled) { return !!_conApi->PrivateEnableUTF8ExtendedMouseMode(fEnabled); @@ -1702,7 +1702,7 @@ bool AdaptDispatch::EnableUTF8ExtendedMouseMode(const bool fEnabled) //Arguments: // - fEnabled - true to enable, false to disable. // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::EnableSGRExtendedMouseMode(const bool fEnabled) { return !!_conApi->PrivateEnableSGRExtendedMouseMode(fEnabled); @@ -1713,7 +1713,7 @@ bool AdaptDispatch::EnableSGRExtendedMouseMode(const bool fEnabled) //Arguments: // - fEnabled - true to enable, false to disable. // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::EnableButtonEventMouseMode(const bool fEnabled) { return !!_conApi->PrivateEnableButtonEventMouseMode(fEnabled); @@ -1725,7 +1725,7 @@ bool AdaptDispatch::EnableButtonEventMouseMode(const bool fEnabled) //Arguments: // - fEnabled - true to enable, false to disable. // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::EnableAnyEventMouseMode(const bool fEnabled) { return !!_conApi->PrivateEnableAnyEventMouseMode(fEnabled); @@ -1737,7 +1737,7 @@ bool AdaptDispatch::EnableAnyEventMouseMode(const bool fEnabled) //Arguments: // - fEnabled - true to enable, false to disable. // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::EnableAlternateScroll(const bool fEnabled) { return !!_conApi->PrivateEnableAlternateScroll(fEnabled); @@ -1749,7 +1749,7 @@ bool AdaptDispatch::EnableAlternateScroll(const bool fEnabled) //Arguments: // - cursorStyle - The unix-like cursor style to apply to the cursor // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) { bool isPty = false; @@ -1808,7 +1808,7 @@ bool AdaptDispatch::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) // - tableIndex: The VT color table index // - dwColor: The new RGB color value to use. // Return Value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::SetCursorColor(const COLORREF cursorColor) { bool isPty = false; @@ -1827,9 +1827,8 @@ bool AdaptDispatch::SetCursorColor(const COLORREF cursorColor) // - tableIndex: The VT color table index // - dwColor: The new RGB color value to use. // Return Value: -// True if handled successfully. False othewise. -bool AdaptDispatch::SetColorTableEntry(const size_t tableIndex, - const DWORD dwColor) +// True if handled successfully. False otherwise. +bool AdaptDispatch::SetColorTableEntry(const size_t tableIndex, const DWORD dwColor) { bool fSuccess = tableIndex < 256; @@ -1853,6 +1852,56 @@ bool AdaptDispatch::SetColorTableEntry(const size_t tableIndex, return fSuccess; } +// Method Description: +// - Sets the default foreground color to a new value +// Arguments: +// - dwColor: The new RGB color value to use, as a COLORREF, format 0x00BBGGRR. +// Return Value: +// True if handled successfully. False otherwise. +bool Microsoft::Console::VirtualTerminal::AdaptDispatch::SetDefaultForeground(const DWORD dwColor) +{ + bool fSuccess = true; + fSuccess = !!_conApi->PrivateSetDefaultForeground(dwColor); + + // If we're a conpty, always return false, so that we send the updated color + // value to the terminal. Still handle the sequence so apps that use + // the API or VT to query the values of the color table still read the + // correct color. + bool isPty = false; + _conApi->IsConsolePty(&isPty); + if (isPty) + { + return false; + } + + return fSuccess; +} + +// Method Description: +// - Sets the default background color to a new value +// Arguments: +// - dwColor: The new RGB color value to use, as a COLORREF, format 0x00BBGGRR. +// Return Value: +// True if handled successfully. False otherwise. +bool Microsoft::Console::VirtualTerminal::AdaptDispatch::SetDefaultBackground(const DWORD dwColor) +{ + bool fSuccess = true; + fSuccess = !!_conApi->PrivateSetDefaultBackground(dwColor); + + // If we're a conpty, always return false, so that we send the updated color + // value to the terminal. Still handle the sequence so apps that use + // the API or VT to query the values of the color table still read the + // correct color. + bool isPty = false; + _conApi->IsConsolePty(&isPty); + if (isPty) + { + return false; + } + + return fSuccess; +} + //Routine Description: // Window Manipulation - Performs a variety of actions relating to the window, // such as moving the window position, resizing the window, querying @@ -1864,7 +1913,7 @@ bool AdaptDispatch::SetColorTableEntry(const size_t tableIndex, // - rgusParams - Additional parameters to pass to the function // - cParams - size of rgusParams // Return value: -// True if handled successfully. False othewise. +// True if handled successfully. False otherwise. bool AdaptDispatch::WindowManipulation(const DispatchTypes::WindowManipulationType uiFunction, _In_reads_(cParams) const unsigned short* const rgusParams, const size_t cParams) diff --git a/src/terminal/adapter/adaptDispatch.hpp b/src/terminal/adapter/adaptDispatch.hpp index b40c9f976..53ce1de4e 100644 --- a/src/terminal/adapter/adaptDispatch.hpp +++ b/src/terminal/adapter/adaptDispatch.hpp @@ -96,8 +96,10 @@ namespace Microsoft::Console::VirtualTerminal virtual bool SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle); // DECSCUSR virtual bool SetCursorColor(const COLORREF cursorColor); - virtual bool SetColorTableEntry(const size_t tableIndex, - const DWORD dwColor); // OscColorTable + virtual bool SetColorTableEntry(const size_t tableIndex, const DWORD dwColor); // OscColorTable + virtual bool SetDefaultForeground(const DWORD dwColor); // OSCDefaultForeground + virtual bool SetDefaultBackground(const DWORD dwColor); // OSCDefaultBackground + virtual bool WindowManipulation(const DispatchTypes::WindowManipulationType uiFunction, _In_reads_(cParams) const unsigned short* const rgusParams, const size_t cParams); // DTTERM_WindowManipulation diff --git a/src/terminal/adapter/conGetSet.hpp b/src/terminal/adapter/conGetSet.hpp index 2f2733b03..ecf7e215e 100644 --- a/src/terminal/adapter/conGetSet.hpp +++ b/src/terminal/adapter/conGetSet.hpp @@ -107,6 +107,8 @@ namespace Microsoft::Console::VirtualTerminal virtual BOOL MoveToBottom() const = 0; virtual BOOL PrivateSetColorTableEntry(const short index, const COLORREF value) const = 0; + virtual BOOL PrivateSetDefaultForeground(const COLORREF value) const = 0; + virtual BOOL PrivateSetDefaultBackground(const COLORREF value) const = 0; }; } diff --git a/src/terminal/adapter/termDispatch.hpp b/src/terminal/adapter/termDispatch.hpp index ea3f2fce1..a56352367 100644 --- a/src/terminal/adapter/termDispatch.hpp +++ b/src/terminal/adapter/termDispatch.hpp @@ -62,6 +62,8 @@ public: virtual bool EnableAnyEventMouseMode(const bool /*fEnabled*/) { return false; } // ?1003 virtual bool EnableAlternateScroll(const bool /*fEnabled*/) { return false; } // ?1007 virtual bool SetColorTableEntry(const size_t /*tableIndex*/, const DWORD /*dwColor*/) { return false; } // OSCColorTable + virtual bool SetDefaultForeground(const DWORD /*dwColor*/) { return false; } // OSCDefaultForeground + virtual bool SetDefaultBackground(const DWORD /*dwColor*/) { return false; } // OSCDefaultBackground virtual bool EraseInDisplay(const DispatchTypes::EraseType /* eraseType*/) { return false; } // ED virtual bool EraseInLine(const DispatchTypes::EraseType /* eraseType*/) { return false; } // EL diff --git a/src/terminal/adapter/ut_adapter/adapterTest.cpp b/src/terminal/adapter/ut_adapter/adapterTest.cpp index ee83e53ff..7289d6bed 100644 --- a/src/terminal/adapter/ut_adapter/adapterTest.cpp +++ b/src/terminal/adapter/ut_adapter/adapterTest.cpp @@ -776,6 +776,28 @@ public: return _fPrivateSetColorTableEntryResult; } + BOOL PrivateSetDefaultForeground(const COLORREF value) const noexcept override + { + Log::Comment(L"PrivateSetDefaultForeground MOCK called..."); + if (_fPrivateSetDefaultForegroundResult) + { + VERIFY_ARE_EQUAL(_expectedDefaultForegroundColorValue, value); + } + + return _fPrivateSetDefaultForegroundResult; + } + + BOOL PrivateSetDefaultBackground(const COLORREF value) const noexcept override + { + Log::Comment(L"PrivateSetDefaultForeground MOCK called..."); + if (_fPrivateSetDefaultBackgroundResult) + { + VERIFY_ARE_EQUAL(_expectedDefaultBackgroundColorValue, value); + } + + return _fPrivateSetDefaultBackgroundResult; + } + void _IncrementCoordPos(_Inout_ COORD* pcoord) { pcoord->X++; @@ -1378,6 +1400,12 @@ public: short _expectedColorTableIndex = -1; COLORREF _expectedColorValue = INVALID_COLOR; + bool _fPrivateSetDefaultForegroundResult = false; + COLORREF _expectedDefaultForegroundColorValue = INVALID_COLOR; + + bool _fPrivateSetDefaultBackgroundResult = false; + COLORREF _expectedDefaultBackgroundColorValue = INVALID_COLOR; + private: HANDLE _hCon; }; diff --git a/src/terminal/parser/OutputStateMachineEngine.cpp b/src/terminal/parser/OutputStateMachineEngine.cpp index e68a8ce1e..7037975cc 100644 --- a/src/terminal/parser/OutputStateMachineEngine.cpp +++ b/src/terminal/parser/OutputStateMachineEngine.cpp @@ -697,8 +697,10 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/, case OscActionCodes::SetColor: fSuccess = _GetOscSetColorTable(pwchOscStringBuffer, cchOscString, &tableIndex, &dwColor); break; + case OscActionCodes::SetForegroundColor: + case OscActionCodes::SetBackgroundColor: case OscActionCodes::SetCursorColor: - fSuccess = _GetOscSetCursorColor(pwchOscStringBuffer, cchOscString, &dwColor); + fSuccess = _GetOscSetColor(pwchOscStringBuffer, cchOscString, &dwColor); break; case OscActionCodes::ResetCursorColor: // the console uses 0xffffffff as an "invalid color" value @@ -724,6 +726,14 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/, fSuccess = _dispatch->SetColorTableEntry(tableIndex, dwColor); TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCCT); break; + case OscActionCodes::SetForegroundColor: + fSuccess = _dispatch->SetDefaultForeground(dwColor); + TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCFG); + break; + case OscActionCodes::SetBackgroundColor: + fSuccess = _dispatch->SetDefaultBackground(dwColor); + TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCBG); + break; case OscActionCodes::SetCursorColor: fSuccess = _dispatch->SetCursorColor(dwColor); TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCSCC); @@ -1162,7 +1172,7 @@ bool OutputStateMachineEngine::_VerifyDeviceAttributesParams(_In_reads_(cParams) // - Null terminates, then returns, the string that we've collected as part of the OSC string. // Arguments: // - ppwchTitle - a pointer to point to the Osc String to use as a title. -// - pcchTitleLength - a pointer place the length of ppwchTitle into. +// - pcchTitle - a pointer place the length of ppwchTitle into. // Return Value: // - True if there was a title to output. (a title with length=0 is still valid) _Success_(return) @@ -1476,10 +1486,12 @@ bool OutputStateMachineEngine::s_ParseColorSpec(_In_reads_(cchBuffer) const wcha // "rgb://" // where is two hex digits // Arguments: -// - ppwchTitle - a pointer to point to the Osc String to use as a title. -// - pcchTitleLength - a pointer place the length of ppwchTitle into. +// - pwchOscStringBuffer - a pointer to the Osc String to parse +// - cchOscString - the length of the Osc String +// - pTableIndex - a pointer that recieves the table index +// - pRgb - a pointer that recieves the color that we parsed in the format: 0x00BBGGRR // Return Value: -// - True if there was a title to output. (a title with length=0 is still valid) +// - True if a table index and color was parsed successfully. False otherwise. bool OutputStateMachineEngine::_GetOscSetColorTable(_In_reads_(cchOscString) const wchar_t* const pwchOscStringBuffer, const size_t cchOscString, _Out_ size_t* const pTableIndex, @@ -1548,16 +1560,17 @@ bool OutputStateMachineEngine::_GetOscSetColorTable(_In_reads_(cchOscString) con } // Routine Description: -// - OSC 12 ; spec ST +// - OSC 10, 11, 12 ; spec ST // spec: a color in the following format: // "rgb://" // where is two hex digits // Arguments: -// - ppwchTitle - a pointer to point to the Osc String to use as a title. -// - pcchTitleLength - a pointer place the length of ppwchTitle into. +// - pwchOscStringBuffer - a pointer to the Osc String to parse +// - cchOscString - the length of the Osc String +// - pRgb - a pointer that recieves the color that we parsed in the format: 0x00BBGGRR // Return Value: -// - True if there was a title to output. (a title with length=0 is still valid) -bool OutputStateMachineEngine::_GetOscSetCursorColor(_In_reads_(cchOscString) const wchar_t* const pwchOscStringBuffer, +// - True if a table index and color was parsed successfully. False otherwise. +bool OutputStateMachineEngine::_GetOscSetColor(_In_reads_(cchOscString) const wchar_t* const pwchOscStringBuffer, const size_t cchOscString, _Out_ DWORD* const pRgb) const { diff --git a/src/terminal/parser/OutputStateMachineEngine.hpp b/src/terminal/parser/OutputStateMachineEngine.hpp index bafedc958..11ad0d8bf 100644 --- a/src/terminal/parser/OutputStateMachineEngine.hpp +++ b/src/terminal/parser/OutputStateMachineEngine.hpp @@ -131,8 +131,13 @@ namespace Microsoft::Console::VirtualTerminal SetIconAndWindowTitle = 0, SetWindowIcon = 1, SetWindowTitle = 2, + SetWindowProperty = 3, // Not implemented SetColor = 4, + SetForegroundColor = 10, + SetBackgroundColor = 11, SetCursorColor = 12, + ResetForegroundColor = 110, // Not implemented + ResetBackgroundColor = 111, // Not implemented ResetCursorColor = 112, }; @@ -251,9 +256,9 @@ namespace Microsoft::Console::VirtualTerminal const size_t cchBuffer, _Out_ DWORD* const pRgb); - bool _GetOscSetCursorColor(_In_reads_(cchOscString) const wchar_t* const pwchOscStringBuffer, - const size_t cchOscString, - _Out_ DWORD* const pRgb) const; + bool _GetOscSetColor(_In_reads_(cchOscString) const wchar_t* const pwchOscStringBuffer, + const size_t cchOscString, + _Out_ DWORD* const pRgb) const; static const DispatchTypes::CursorStyle s_defaultCursorStyle = DispatchTypes::CursorStyle::BlinkingBlockDefault; _Success_(return) diff --git a/src/terminal/parser/telemetry.cpp b/src/terminal/parser/telemetry.cpp index 2d227514e..90d81f08f 100644 --- a/src/terminal/parser/telemetry.cpp +++ b/src/terminal/parser/telemetry.cpp @@ -243,6 +243,8 @@ void TermTelemetry::WriteFinalTraceLog() const TraceLoggingUInt32(_uiTimesUsed[OSCCT], "OscColorTable"), TraceLoggingUInt32(_uiTimesUsed[OSCSCC], "OscSetCursorColor"), TraceLoggingUInt32(_uiTimesUsed[OSCRCC], "OscResetCursorColor"), + TraceLoggingUInt32(_uiTimesUsed[OSCFG], "OscForegroundColor"), + TraceLoggingUInt32(_uiTimesUsed[OSCBG], "OscBackgroundColor"), TraceLoggingUInt32(_uiTimesUsed[REP], "REP"), TraceLoggingUInt32Array(_uiTimesFailed, ARRAYSIZE(_uiTimesFailed), "Failed"), TraceLoggingUInt32(_uiTimesFailedOutsideRange, "FailedOutsideRange")); diff --git a/src/terminal/parser/telemetry.hpp b/src/terminal/parser/telemetry.hpp index e73d75de1..59c8752d3 100644 --- a/src/terminal/parser/telemetry.hpp +++ b/src/terminal/parser/telemetry.hpp @@ -83,6 +83,8 @@ namespace Microsoft::Console::VirtualTerminal OSCSCC, OSCRCC, REP, + OSCFG, + OSCBG, // Only use this last enum as a count of the number of codes. NUMBER_OF_CODES };