Skip to content

Commit

Permalink
Add support for DECSCUSR "0" to restore cursor to user default (#7379)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
skyline75489 committed Sep 4, 2020
1 parent 5ba992a commit 7ab4d45
Show file tree
Hide file tree
Showing 10 changed files with 42 additions and 8 deletions.
2 changes: 2 additions & 0 deletions src/cascadia/TerminalCore/Terminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalCore/Terminal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ class Microsoft::Terminal::Core::Terminal final :
std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
COLORREF _defaultFg;
COLORREF _defaultBg;
CursorType _defaultCursorShape;
bool _screenReversed;

bool _snapOnInput;
Expand Down
11 changes: 7 additions & 4 deletions src/cascadia/TerminalCore/TerminalApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
13 changes: 13 additions & 0 deletions src/host/outputStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions src/host/outputStream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ class ConhostInternalGetSet final : public Microsoft::Console::VirtualTerminal::
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;

Expand Down
4 changes: 2 additions & 2 deletions src/terminal/adapter/DispatchTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
9 changes: 8 additions & 1 deletion src/terminal/adapter/adaptDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/terminal/adapter/conGetSet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 6 additions & 0 deletions src/terminal/adapter/ut_adapter/adapterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,12 @@ class TestGetSet final : public ConGetSet
return TRUE;
}

bool GetUserDefaultCursorStyle(CursorType& style) override
{
style = CursorType::Legacy;
return true;
}

bool SetCursorStyle(const CursorType cursorType) override
{
Log::Comment(L"SetCursorStyle MOCK called...");
Expand Down
2 changes: 1 addition & 1 deletion src/terminal/parser/OutputStateMachineEngine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down

0 comments on commit 7ab4d45

Please sign in to comment.