mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-10 18:43:54 -06:00
Add support for DECSCNM in Windows Terminal (#6809)
## Summary of the Pull Request This PR adds full support for the `DECSCNM` reverse screen mode in the Windows Terminal to align with the implementation in conhost. ## References * The conhost implementation of `DECSCNM` was in PR #3817. * WT originally inherited that functionality via the colors being passed through, but that behaviour was lost in PR #6506. ## PR Checklist * [x] Closes #6622 * [x] CLA signed. * [ ] Tests added/passed * [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx * [ ] Schema updated. * [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #6622 ## Detailed Description of the Pull Request / Additional comments The `AdaptDispatch::SetScreenMode` now checks if it's in conpty mode and simply returns false to force a pass-through of the mode change. And the `TerminalDispatch` now has its own `SetScreenMode` implementation that tracks any changes to the reversed state, and triggers a redraw in the renderer. To make the renderer work, we just needed to update the `GetForegroundColor` and `GetBackgroundColor` methods of the terminal's `IRenderData` implementation to check the reversed state, and switch the colors being calculated, the same way the `LookupForegroundColor` and `LookupBackgroundColor` methods work in the conhost `Settings` class. ## Validation Steps Performed I've manually tested the `DECSCNM` functionality for Windows Terminal in Vttest, and also with some of my own test scripts.
This commit is contained in:
parent
9e26c020e4
commit
695ebffca1
@ -46,6 +46,7 @@ namespace Microsoft::Terminal::Core
|
||||
virtual bool EnableWin32InputMode(const bool win32InputMode) noexcept = 0;
|
||||
virtual bool SetCursorKeysMode(const bool applicationMode) noexcept = 0;
|
||||
virtual bool SetKeypadMode(const bool applicationMode) noexcept = 0;
|
||||
virtual bool SetScreenMode(const bool reverseMode) noexcept = 0;
|
||||
virtual bool EnableVT200MouseMode(const bool enabled) noexcept = 0;
|
||||
virtual bool EnableUTF8ExtendedMouseMode(const bool enabled) noexcept = 0;
|
||||
virtual bool EnableSGRExtendedMouseMode(const bool enabled) noexcept = 0;
|
||||
|
||||
@ -41,6 +41,7 @@ Terminal::Terminal() :
|
||||
_colorTable{},
|
||||
_defaultFg{ RGB(255, 255, 255) },
|
||||
_defaultBg{ ARGB(0, 0, 0, 0) },
|
||||
_screenReversed{ false },
|
||||
_pfnWriteInput{ nullptr },
|
||||
_scrollOffset{ 0 },
|
||||
_snapOnInput{ true },
|
||||
|
||||
@ -99,6 +99,7 @@ public:
|
||||
bool EnableWin32InputMode(const bool win32InputMode) noexcept override;
|
||||
bool SetCursorKeysMode(const bool applicationMode) noexcept override;
|
||||
bool SetKeypadMode(const bool applicationMode) noexcept override;
|
||||
bool SetScreenMode(const bool reverseMode) noexcept override;
|
||||
bool EnableVT200MouseMode(const bool enabled) noexcept override;
|
||||
bool EnableUTF8ExtendedMouseMode(const bool enabled) noexcept override;
|
||||
bool EnableSGRExtendedMouseMode(const bool enabled) noexcept override;
|
||||
@ -208,6 +209,7 @@ private:
|
||||
std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
|
||||
COLORREF _defaultFg;
|
||||
COLORREF _defaultBg;
|
||||
bool _screenReversed;
|
||||
|
||||
bool _snapOnInput;
|
||||
bool _altGrAliasing;
|
||||
|
||||
@ -471,6 +471,17 @@ bool Terminal::SetKeypadMode(const bool applicationMode) noexcept
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Terminal::SetScreenMode(const bool reverseMode) noexcept
|
||||
try
|
||||
{
|
||||
_screenReversed = reverseMode;
|
||||
|
||||
// Repaint everything - the colors will have changed
|
||||
_buffer->GetRenderTarget().TriggerRedrawAll();
|
||||
return true;
|
||||
}
|
||||
CATCH_LOG_RETURN_FALSE()
|
||||
|
||||
bool Terminal::EnableVT200MouseMode(const bool enabled) noexcept
|
||||
{
|
||||
_terminalInput->EnableDefaultTracking(enabled);
|
||||
|
||||
@ -253,6 +253,18 @@ bool TerminalDispatch::SetCursorKeysMode(const bool applicationMode) noexcept
|
||||
return true;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - DECSCNM - Sets the screen mode to either normal or reverse.
|
||||
// When in reverse screen mode, the background and foreground colors are switched.
|
||||
// Arguments:
|
||||
// - reverseMode - set to true to enable reverse screen mode, false for normal mode.
|
||||
// Return Value:
|
||||
// - True if handled successfully. False otherwise.
|
||||
bool TerminalDispatch::SetScreenMode(const bool reverseMode) noexcept
|
||||
{
|
||||
return _terminalApi.SetScreenMode(reverseMode);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - win32-input-mode: Enable sending full input records encoded as a string of
|
||||
// characters to the client application.
|
||||
@ -390,6 +402,9 @@ bool TerminalDispatch::_PrivateModeParamsHelper(const DispatchTypes::PrivateMode
|
||||
// set - Enable Application Mode, reset - Normal mode
|
||||
success = SetCursorKeysMode(enable);
|
||||
break;
|
||||
case DispatchTypes::PrivateModeParams::DECSCNM_ScreenMode:
|
||||
success = SetScreenMode(enable);
|
||||
break;
|
||||
case DispatchTypes::PrivateModeParams::VT200_MOUSE_MODE:
|
||||
success = EnableVT200MouseMode(enable);
|
||||
break;
|
||||
@ -493,8 +508,8 @@ bool TerminalDispatch::HardReset() noexcept
|
||||
success = EraseInDisplay(DispatchTypes::EraseType::All) && success;
|
||||
success = EraseInDisplay(DispatchTypes::EraseType::Scrollback) && success;
|
||||
|
||||
// // Set the DECSCNM screen mode back to normal.
|
||||
// success = SetScreenMode(false) && success;
|
||||
// Set the DECSCNM screen mode back to normal.
|
||||
success = SetScreenMode(false) && success;
|
||||
|
||||
// Cursor to 1,1 - the Soft Reset guarantees this is absolute
|
||||
success = CursorPosition(1, 1) && success;
|
||||
|
||||
@ -47,6 +47,7 @@ public:
|
||||
|
||||
bool SetCursorKeysMode(const bool applicationMode) noexcept override; // DECCKM
|
||||
bool SetKeypadMode(const bool applicationMode) noexcept override; // DECKPAM, DECKPNM
|
||||
bool SetScreenMode(const bool reverseMode) noexcept override; // DECSCNM
|
||||
|
||||
bool SoftReset() noexcept override; // DECSTR
|
||||
bool HardReset() noexcept override; // RIS
|
||||
|
||||
@ -52,15 +52,32 @@ const TextAttribute Terminal::GetDefaultBrushColors() noexcept
|
||||
|
||||
const COLORREF Terminal::GetForegroundColor(const TextAttribute& attr) const noexcept
|
||||
{
|
||||
return 0xff000000 | attr.CalculateRgbForeground({ _colorTable.data(), _colorTable.size() }, _defaultFg, _defaultBg);
|
||||
COLORREF fgColor{};
|
||||
if (_screenReversed)
|
||||
{
|
||||
fgColor = attr.CalculateRgbBackground({ _colorTable.data(), _colorTable.size() }, _defaultFg, _defaultBg);
|
||||
}
|
||||
else
|
||||
{
|
||||
fgColor = attr.CalculateRgbForeground({ _colorTable.data(), _colorTable.size() }, _defaultFg, _defaultBg);
|
||||
}
|
||||
return 0xff000000 | fgColor;
|
||||
}
|
||||
|
||||
const COLORREF Terminal::GetBackgroundColor(const TextAttribute& attr) const noexcept
|
||||
{
|
||||
const auto bgColor = attr.CalculateRgbBackground({ _colorTable.data(), _colorTable.size() }, _defaultFg, _defaultBg);
|
||||
COLORREF bgColor{};
|
||||
if (_screenReversed)
|
||||
{
|
||||
bgColor = attr.CalculateRgbForeground({ _colorTable.data(), _colorTable.size() }, _defaultFg, _defaultBg);
|
||||
}
|
||||
else
|
||||
{
|
||||
bgColor = attr.CalculateRgbBackground({ _colorTable.data(), _colorTable.size() }, _defaultFg, _defaultBg);
|
||||
}
|
||||
// We only care about alpha for the default BG (which enables acrylic)
|
||||
// If the bg isn't the default bg color, or reverse video is enabled, make it fully opaque.
|
||||
if (!attr.BackgroundIsDefault() || attr.IsReverseVideo())
|
||||
if (!attr.BackgroundIsDefault() || (attr.IsReverseVideo() ^ _screenReversed))
|
||||
{
|
||||
return 0xff000000 | bgColor;
|
||||
}
|
||||
@ -213,10 +230,9 @@ void Terminal::UnlockConsole() noexcept
|
||||
|
||||
// Method Description:
|
||||
// - Returns whether the screen is inverted;
|
||||
// This state is not currently known to Terminal.
|
||||
// Return Value:
|
||||
// - false.
|
||||
bool Terminal::IsScreenReversed() const noexcept
|
||||
{
|
||||
return false;
|
||||
return _screenReversed;
|
||||
}
|
||||
|
||||
@ -1205,6 +1205,12 @@ bool AdaptDispatch::SetAnsiMode(const bool ansiMode)
|
||||
// - True if handled successfully. False otherwise.
|
||||
bool AdaptDispatch::SetScreenMode(const bool reverseMode)
|
||||
{
|
||||
// If we're a conpty, always return false
|
||||
if (_pConApi->IsConsolePty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _pConApi->PrivateSetScreenMode(reverseMode);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user