Allow OSC 17 to set the selection background color (#17742)

This pull request adds support for setting and querying the selection
color with `OSC 17`.

To make this possible, I had to move selection color down into the color
table where it always belonged. This lets us get rid of the special
`SetSelectionColor` method from the surface of AtlasEngine, and reunites
selection colors with the rest of the special colors.
This commit is contained in:
Dustin L. Howett 2024-08-22 12:58:11 -05:00 committed by GitHub
parent eabebc4cb2
commit cbb4a0a01c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 31 additions and 27 deletions

View File

@ -82,7 +82,8 @@ public:
static constexpr size_t FRAME_FOREGROUND = 263;
static constexpr size_t FRAME_BACKGROUND = 264;
static constexpr size_t CURSOR_COLOR = 265;
static constexpr size_t TABLE_SIZE = 266;
static constexpr size_t SELECTION_BACKGROUND = 266;
static constexpr size_t TABLE_SIZE = 267;
constexpr TextColor() noexcept :
_meta{ ColorType::IsDefault },

View File

@ -349,9 +349,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto viewInPixels = Viewport::FromDimensions({ 0, 0 }, windowSize);
LOG_IF_FAILED(_renderEngine->SetWindowSize({ viewInPixels.Width(), viewInPixels.Height() }));
// Update AtlasEngine's SelectionBackground
_renderEngine->SetSelectionBackground(til::color{ _settings->SelectionBackground() });
const auto vp = _renderEngine->GetViewportInCharacters(viewInPixels);
const auto width = vp.Width();
const auto height = vp.Height();
@ -900,7 +897,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (_renderEngine)
{
// Update AtlasEngine settings under the lock
_renderEngine->SetSelectionBackground(til::color{ newAppearance->SelectionBackground() });
_renderEngine->SetRetroTerminalEffect(newAppearance->RetroTerminalEffect());
_renderEngine->SetPixelShaderPath(newAppearance->PixelShaderPath());
_renderEngine->SetPixelShaderImagePath(newAppearance->PixelShaderImagePath());
@ -2412,7 +2408,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto lock = _terminal->LockForWriting();
_terminal->ApplyScheme(scheme);
_renderEngine->SetSelectionBackground(til::color{ _settings->SelectionBackground() });
_renderer->TriggerRedrawAll(true);
}

View File

@ -881,8 +881,7 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
auto& renderSettings = publicTerminal->_terminal->GetRenderSettings();
renderSettings.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, theme.DefaultForeground);
renderSettings.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, theme.DefaultBackground);
publicTerminal->_renderEngine->SetSelectionBackground(theme.DefaultSelectionBackground);
renderSettings.SetColorTableEntry(TextColor::SELECTION_BACKGROUND, theme.DefaultSelectionBackground);
// Set the font colors
for (size_t tableIndex = 0; tableIndex < 16; tableIndex++)

View File

@ -5,7 +5,6 @@ namespace Microsoft.Terminal.Control
{
interface IControlAppearance requires Microsoft.Terminal.Core.ICoreAppearance
{
Microsoft.Terminal.Core.Color SelectionBackground { get; };
String BackgroundImage { get; };
Single BackgroundImageOpacity { get; };
Windows.UI.Xaml.Media.Stretch BackgroundImageStretchMode { get; };

View File

@ -115,6 +115,7 @@ namespace Microsoft.Terminal.Core
{
Microsoft.Terminal.Core.Color DefaultForeground;
Microsoft.Terminal.Core.Color DefaultBackground;
Microsoft.Terminal.Core.Color SelectionBackground;
Microsoft.Terminal.Core.Color GetColorTableEntry(Int32 index);
Microsoft.Terminal.Core.Color CursorColor;
CursorStyle CursorShape;

View File

@ -155,6 +155,8 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
renderSettings.SetColorAlias(ColorAlias::DefaultForeground, TextColor::DEFAULT_FOREGROUND, newForegroundColor);
const til::color newCursorColor{ appearance.CursorColor() };
renderSettings.SetColorTableEntry(TextColor::CURSOR_COLOR, newCursorColor);
const til::color newSelectionColor{ appearance.SelectionBackground() };
renderSettings.SetColorTableEntry(TextColor::SELECTION_BACKGROUND, newSelectionColor);
for (auto i = 0; i < 16; i++)
{
@ -1275,8 +1277,8 @@ Scheme Terminal::GetColorScheme() const
s.Foreground = til::color{ renderSettings.GetColorAlias(ColorAlias::DefaultForeground) };
s.Background = til::color{ renderSettings.GetColorAlias(ColorAlias::DefaultBackground) };
// SelectionBackground is stored in the ControlAppearance
s.CursorColor = til::color{ renderSettings.GetColorTableEntry(TextColor::CURSOR_COLOR) };
s.SelectionBackground = til::color{ renderSettings.GetColorTableEntry(TextColor::SELECTION_BACKGROUND) };
s.Black = til::color{ renderSettings.GetColorTableEntry(TextColor::DARK_BLACK) };
s.Red = til::color{ renderSettings.GetColorTableEntry(TextColor::DARK_RED) };
@ -1322,6 +1324,7 @@ void Terminal::ApplyScheme(const Scheme& colorScheme)
renderSettings.SetColorTableEntry(TextColor::BRIGHT_WHITE, til::color{ colorScheme.BrightWhite });
renderSettings.SetColorTableEntry(TextColor::CURSOR_COLOR, til::color{ colorScheme.CursorColor });
renderSettings.SetColorTableEntry(TextColor::SELECTION_BACKGROUND, til::color{ colorScheme.SelectionBackground });
// Tell the control that the scrollbar has somehow changed. Used as a
// workaround to force the control to redraw any scrollbar marks whose color

View File

@ -11,6 +11,7 @@
X(til::color, CursorColor, DEFAULT_CURSOR_COLOR) \
X(winrt::Microsoft::Terminal::Core::CursorStyle, CursorShape, winrt::Microsoft::Terminal::Core::CursorStyle::Vintage) \
X(uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT) \
X(til::color, SelectionBackground, DEFAULT_FOREGROUND) \
X(bool, IntenseIsBold) \
X(bool, IntenseIsBright, true) \
X(winrt::Microsoft::Terminal::Core::AdjustTextMode, AdjustIndistinguishableColors, winrt::Microsoft::Terminal::Core::AdjustTextMode::Never)
@ -18,7 +19,6 @@
// --------------------------- Control Appearance ---------------------------
// All of these settings are defined in IControlAppearance.
#define CONTROL_APPEARANCE_SETTINGS(X) \
X(til::color, SelectionBackground, DEFAULT_FOREGROUND) \
X(float, Opacity, 1.0f) \
X(bool, UseAcrylic, false) \
X(winrt::hstring, BackgroundImage) \

View File

@ -7,7 +7,6 @@
#include "Backend.h"
#include "../../buffer/out/textBuffer.hpp"
#include "../base/FontCache.h"
#include "../../types/inc/ColorFix.hpp"
// #### NOTE ####
// If you see any code in here that contains "_r." you might be seeing a race condition.
@ -425,18 +424,6 @@ void AtlasEngine::SetRetroTerminalEffect(bool enable) noexcept
}
}
void AtlasEngine::SetSelectionBackground(const COLORREF color) noexcept
{
const u32 selectionColor = (color & 0xffffff) | 0xff000000;
if (_api.s->misc->selectionColor != selectionColor)
{
auto misc = _api.s.write()->misc.write();
misc->selectionColor = selectionColor;
// Select a black or white foreground based on the perceptual lightness of the background.
misc->selectionForeground = ColorFix::GetLuminosity(selectionColor) < 0.5f ? 0xffffffff : 0xff000000;
}
}
void AtlasEngine::SetSoftwareRendering(bool enable) noexcept
{
if (_api.s->target->useWARP != enable)

View File

@ -315,6 +315,21 @@ CATCH_RETURN()
}
_api.selectionSpans = til::point_span_subspan_within_rect(info.selectionSpans, dr);
const u32 newSelectionColor{ static_cast<COLORREF>(info.selectionBackground) | 0xff000000 };
if (_api.s->misc->selectionColor != newSelectionColor)
{
auto misc = _api.s.write()->misc.write();
misc->selectionColor = newSelectionColor;
// Select a black or white foreground based on the perceptual lightness of the background.
misc->selectionForeground = ColorFix::GetLuminosity(newSelectionColor) < 0.5f ? 0xffffffff : 0xff000000;
// We copied the selection colors into _p during StartPaint, which happened just before PrepareRenderInfo
// This keeps their generations in sync.
auto pm = _p.s.write()->misc.write();
pm->selectionColor = misc->selectionColor;
pm->selectionForeground = misc->selectionForeground;
}
}
return S_OK;
@ -502,7 +517,7 @@ try
// Apply the highlighting colors to the highlighted cells
RETURN_IF_FAILED(_drawHighlighted(_api.searchHighlights, y, x, columnEnd, highlightFg, highlightBg));
RETURN_IF_FAILED(_drawHighlighted(_api.searchHighlightFocused, y, x, columnEnd, highlightFocusFg, highlightFocusBg));
RETURN_IF_FAILED(_drawHighlighted(_api.selectionSpans, y, x, columnEnd, _api.s->misc->selectionForeground, _api.s->misc->selectionColor));
RETURN_IF_FAILED(_drawHighlighted(_api.selectionSpans, y, x, columnEnd, _p.s->misc->selectionForeground, _p.s->misc->selectionColor));
_api.lastPaintBufferLineCoord = { x, y };
return S_OK;

View File

@ -71,7 +71,6 @@ namespace Microsoft::Console::Render::Atlas
void SetPixelShaderPath(std::wstring_view value) noexcept;
void SetPixelShaderImagePath(std::wstring_view value) noexcept;
void SetRetroTerminalEffect(bool enable) noexcept;
void SetSelectionBackground(COLORREF color) noexcept;
void SetSoftwareRendering(bool enable) noexcept;
void SetDisablePartialInvalidation(bool enable) noexcept;
void SetGraphicsAPI(GraphicsAPI graphicsAPI) noexcept;

View File

@ -20,6 +20,7 @@ RenderSettings::RenderSettings() noexcept
SetColorTableEntry(TextColor::FRAME_FOREGROUND, INVALID_COLOR);
SetColorTableEntry(TextColor::FRAME_BACKGROUND, INVALID_COLOR);
SetColorTableEntry(TextColor::CURSOR_COLOR, INVALID_COLOR);
SetColorTableEntry(TextColor::SELECTION_BACKGROUND, INVALID_COLOR);
SetColorAliasIndex(ColorAlias::DefaultForeground, TextColor::DARK_WHITE);
SetColorAliasIndex(ColorAlias::DefaultBackground, TextColor::DARK_BLACK);

View File

@ -1276,6 +1276,7 @@ void Renderer::_PaintCursor(_In_ IRenderEngine* const pEngine)
info.searchHighlights = _pData->GetSearchHighlights();
info.searchHighlightFocused = _pData->GetSearchHighlightFocused();
info.selectionSpans = _pData->GetSelectionSpans();
info.selectionBackground = _renderSettings.GetColorTableEntry(TextColor::SELECTION_BACKGROUND);
return pEngine->PrepareRenderInfo(std::move(info));
}

View File

@ -33,6 +33,7 @@ namespace Microsoft::Console::Render
std::span<const til::point_span> searchHighlights;
const til::point_span* searchHighlightFocused;
std::span<const til::point_span> selectionSpans;
til::color selectionBackground;
};
enum class GridLines

View File

@ -32,7 +32,7 @@ static constexpr std::array<XtermResourceColorTableEntry, 10> XtermResourceColor
/* 14 */ { -1, -1 },
/* 15 */ { -1, -1 },
/* 16 */ { -1, -1 },
/* 17 */ { -1, -1 },
/* 17 */ { TextColor::SELECTION_BACKGROUND, -1 },
/* 18 */ { -1, -1 },
/* 19 */ { -1, -1 },
} };

View File

@ -804,6 +804,7 @@ bool OutputStateMachineEngine::ActionOscDispatch(const size_t parameter, const s
case OscActionCodes::SetForegroundColor:
case OscActionCodes::SetBackgroundColor:
case OscActionCodes::SetCursorColor:
case OscActionCodes::SetHighlightColor:
{
std::vector<DWORD> colors;
success = _GetOscSetColor(string, colors);

View File

@ -213,6 +213,7 @@ namespace Microsoft::Console::VirtualTerminal
SetForegroundColor = 10,
SetBackgroundColor = 11,
SetCursorColor = 12,
SetHighlightColor = 17,
DECSWT_SetWindowTitle = 21,
SetClipboard = 52,
ResetForegroundColor = 110, // Not implemented