Skip to content

Commit

Permalink
Add support for OSC 10 and 11 to set the default colors (#891)
Browse files Browse the repository at this point in the history
* Support OSC to set default background and foreground colors

* Update the Terminal theme when the background changes

* Fix whitespace per code-review

* Add Documentation Comments

Also fix a few outdated comments and whitespace

* Update Telemetry codes per code review

* Add Unit Tests for OSC ForegroundColor and BackgroundColor

* Add a couple additional test cases

* Minor doc and whitespace change per PR review

* Update comment help per code review

* Add another OSC 10 & 11 test case, improve output

* Comments and syntax cleanup per code reviews
  • Loading branch information
Jaykul authored and miniksa committed May 24, 2019
1 parent 2fdcb67 commit efd6999
Show file tree
Hide file tree
Showing 23 changed files with 482 additions and 72 deletions.
81 changes: 49 additions & 32 deletions src/cascadia/TerminalControl/TermControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,46 +158,16 @@ 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:
// - <none>
// Return Value:
// - <none>
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());
Expand All @@ -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:
// - <none>
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
Expand Down Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalControl/TermControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalCore/ITerminalApi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
}
9 changes: 9 additions & 0 deletions src/cascadia/TerminalCore/Terminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,15 @@ void Terminal::SetScrollPositionChangedCallback(std::function<void(const int, co
_pfnScrollPositionChanged = pfn;
}

// Method Description:
// - Allows setting a callback for when the background color is changed
// Arguments:
// - pfn: a function callback that takes a uint32 (DWORD COLORREF) color in the format 0x00BBGGRR
void Terminal::SetBackgroundCallback(std::function<void(const uint32_t)> pfn) noexcept
{
_pfnBackgroundColorChanged = pfn;
}

// Method Description:
// - Checks if selection is active
// Return Value:
Expand Down
6 changes: 5 additions & 1 deletion src/cascadia/TerminalCore/Terminal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,10 @@ class Microsoft::Terminal::Core::Terminal final :
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
Expand Down Expand Up @@ -113,6 +115,7 @@ class Microsoft::Terminal::Core::Terminal final :
void SetWriteInputCallback(std::function<void(std::wstring&)> pfn) noexcept;
void SetTitleChangedCallback(std::function<void(const std::wstring_view&)> pfn) noexcept;
void SetScrollPositionChangedCallback(std::function<void(const int, const int, const int)> pfn) noexcept;
void SetBackgroundCallback(std::function<void(const uint32_t)> pfn) noexcept;

void SetCursorVisible(const bool isVisible) noexcept;
bool IsCursorBlinkingAllowed() const noexcept;
Expand All @@ -131,6 +134,7 @@ class Microsoft::Terminal::Core::Terminal final :
std::function<void(std::wstring&)> _pfnWriteInput;
std::function<void(const std::wstring_view&)> _pfnTitleChanged;
std::function<void(const int, const int, const int)> _pfnScrollPositionChanged;
std::function<void(const uint32_t)> _pfnBackgroundColorChanged;

std::unique_ptr<::Microsoft::Console::VirtualTerminal::StateMachine> _stateMachine;
std::unique_ptr<::Microsoft::Console::VirtualTerminal::TerminalInput> _terminalInput;
Expand Down
33 changes: 32 additions & 1 deletion src/cascadia/TerminalCore/TerminalApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
{
Expand Down Expand Up @@ -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;
}
24 changes: 23 additions & 1 deletion src/cascadia/TerminalCore/TerminalDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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);
}
3 changes: 3 additions & 0 deletions src/cascadia/TerminalCore/TerminalDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ class TerminalDispatch : public Microsoft::Console::VirtualTerminal::TermDispatc
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;

Expand Down
56 changes: 56 additions & 0 deletions src/host/getset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
6 changes: 6 additions & 0 deletions src/host/getset.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
24 changes: 24 additions & 0 deletions src/host/outputStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
4 changes: 4 additions & 0 deletions src/host/outputStream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ class ConhostInternalGetSet final : public Microsoft::Console::VirtualTerminal::

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;
};
Loading

0 comments on commit efd6999

Please sign in to comment.