Add support for DECSCUSR "0" to restore cursor to user default (#7379)

This PR is about the behavior of DECSCUSR. This PR changes the meaning
of DECSCUSR 0 to restore the cursor style back to user default. This
differs from what VT spec says but it’s used in popular terminal
emulators like iTerm2 and VTE-based ones. See #1604. 

Another change is that for parameter greater than 6, DECSCUSR should be
ignored, instead of restoring the cursor to legacy. This PR fixes it.
See #7382.

Fixes #1604.
This commit is contained in:
Chester Liu 2020-09-05 04:36:09 +08:00 committed by GitHub
parent 5ba992a803
commit 7ab4d45a9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 42 additions and 8 deletions

View File

@ -134,6 +134,8 @@ void Terminal::UpdateSettings(ICoreSettings settings)
cursorShape);
}
_defaultCursorShape = cursorShape;
for (int i = 0; i < 16; i++)
{
_colorTable.at(i) = settings.GetColorTableEntry(i);

View File

@ -221,6 +221,7 @@ private:
std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
COLORREF _defaultFg;
COLORREF _defaultBg;
CursorType _defaultCursorShape;
bool _screenReversed;
bool _snapOnInput;

View File

@ -389,8 +389,10 @@ bool Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) noex
switch (cursorStyle)
{
case DispatchTypes::CursorStyle::BlinkingBlockDefault:
[[fallthrough]];
case DispatchTypes::CursorStyle::UserDefault:
finalCursorType = _defaultCursorShape;
shouldBlink = true;
break;
case DispatchTypes::CursorStyle::BlinkingBlock:
finalCursorType = CursorType::FullBox;
shouldBlink = true;
@ -415,9 +417,10 @@ bool Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) noex
finalCursorType = CursorType::VerticalBar;
shouldBlink = false;
break;
default:
finalCursorType = CursorType::Legacy;
shouldBlink = false;
// Invalid argument should be ignored.
return true;
}
_buffer->GetCursor().SetType(finalCursorType);

View File

@ -513,6 +513,19 @@ bool ConhostInternalGetSet::PrivateEraseAll()
return SUCCEEDED(DoSrvPrivateEraseAll(_io.GetActiveOutputBuffer()));
}
// Method Description:
// - Retrieves the current user default cursor style.
// Arguments:
// - style - Structure to receive cursor style.
// Return Value:
// - true if successful. false otherwise.
bool ConhostInternalGetSet::GetUserDefaultCursorStyle(CursorType& style)
{
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
style = gci.GetCursorType();
return true;
}
// Routine Description:
// - Connects the SetCursorStyle call directly into our Driver Message servicing call inside Conhost.exe
// SetCursorStyle is an internal-only "API" call that the vt commands can execute,

View File

@ -107,6 +107,7 @@ public:
bool PrivatePrependConsoleInput(std::deque<std::unique_ptr<IInputEvent>>& events,
size_t& eventsWritten) override;
bool GetUserDefaultCursorStyle(CursorType& style) override;
bool SetCursorStyle(CursorType const style) override;
bool SetCursorColor(COLORREF const color) override;

View File

@ -216,8 +216,8 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes
enum class CursorStyle : unsigned int
{
BlinkingBlock = 0,
BlinkingBlockDefault = 1,
UserDefault = 0, // Implemented as "restore cursor to user default".
BlinkingBlock = 1,
SteadyBlock = 2,
BlinkingUnderline = 3,
SteadyUnderline = 4,

View File

@ -2160,8 +2160,11 @@ bool AdaptDispatch::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle)
switch (cursorStyle)
{
case DispatchTypes::CursorStyle::UserDefault:
_pConApi->GetUserDefaultCursorStyle(actualType);
fEnableBlinking = true;
break;
case DispatchTypes::CursorStyle::BlinkingBlock:
case DispatchTypes::CursorStyle::BlinkingBlockDefault:
fEnableBlinking = true;
actualType = CursorType::FullBox;
break;
@ -2187,6 +2190,10 @@ bool AdaptDispatch::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle)
fEnableBlinking = false;
actualType = CursorType::VerticalBar;
break;
default:
// Invalid argument should be handled by the connected terminal.
return false;
}
bool success = _pConApi->SetCursorStyle(actualType);

View File

@ -70,6 +70,7 @@ namespace Microsoft::Console::VirtualTerminal
virtual bool PrivateEnableAnyEventMouseMode(const bool enabled) = 0;
virtual bool PrivateEnableAlternateScroll(const bool enabled) = 0;
virtual bool PrivateEraseAll() = 0;
virtual bool GetUserDefaultCursorStyle(CursorType& style) = 0;
virtual bool SetCursorStyle(const CursorType style) = 0;
virtual bool SetCursorColor(const COLORREF color) = 0;
virtual bool PrivatePrependConsoleInput(std::deque<std::unique_ptr<IInputEvent>>& events,

View File

@ -434,6 +434,12 @@ public:
return TRUE;
}
bool GetUserDefaultCursorStyle(CursorType& style) override
{
style = CursorType::Legacy;
return true;
}
bool SetCursorStyle(const CursorType cursorType) override
{
Log::Comment(L"SetCursorStyle MOCK called...");

View File

@ -239,7 +239,7 @@ namespace Microsoft::Console::VirtualTerminal
bool _GetOscSetColor(const std::wstring_view string,
DWORD& rgb) const noexcept;
static constexpr DispatchTypes::CursorStyle DefaultCursorStyle = DispatchTypes::CursorStyle::BlinkingBlockDefault;
static constexpr DispatchTypes::CursorStyle DefaultCursorStyle = DispatchTypes::CursorStyle::UserDefault;
bool _GetCursorStyle(const gsl::span<const size_t> parameters,
DispatchTypes::CursorStyle& cursorStyle) const noexcept;