Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
15 commits merged into from
Sep 4, 2020
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 @@ -214,6 +214,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;
skyline75489 marked this conversation as resolved.
Show resolved Hide resolved
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();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we’re on older Windows 10 or Windows 7, will this still work? I assume it will always return legacy.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the VT support was only added to conhost in build 10586 of Windows 10, so nothing prior to that should have any of this code. Maybe one of the core devs can confirm this, but I don't think we need to worry about older versions of Windows at all.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is totally fine. Conhost is also shipped as a totally independent unit -- so if conhost can run on an older version of Windows, it will bring with it full VT support and this cursor change.

(incidentally, it works on Windows 8.1 and brings full VT support 😉)

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".
skyline75489 marked this conversation as resolved.
Show resolved Hide resolved
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:
skyline75489 marked this conversation as resolved.
Show resolved Hide resolved
case DispatchTypes::CursorStyle::BlinkingBlockDefault:
fEnableBlinking = true;
actualType = CursorType::FullBox;
break;
Comment on lines 2167 to 2170
Copy link
Collaborator

@j4james j4james Aug 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the behaviour for conhost is right. We should either leave UserDefault as an alias for BlinkingBlock, which is at least compatible with the DEC standard, or we should try and map it to the actual user preference (which I'm honestly not sure how to do). Worst case we could possibly map it to blinking legacy, which I think is the system default. But as it stands, it looks like you're going to get non-blinking legacy, which is neither one thing nor the other.

Edit: Sorry this is essentially a long-winded dup of DHowett's comment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More detail = more good

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 @@ -238,7 +238,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