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
9 changes: 5 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 @@ -416,8 +418,7 @@ bool Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) noex
shouldBlink = false;
break;
default:
finalCursorType = CursorType::Legacy;
shouldBlink = false;
return true;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: If we're now treating unrecognised parameters as a no-op in Windows Terminal (which is good), should we not be doing the same thing for conhost in AdaptDispatch?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don’t know how can we debug conhost now. So I intended to keep this. By the way do we want to fix this kind of small bug in conhost, or do we want to keep its behavior. I mean conhost itself is the legacy thing that shouldn’t be changed much for compatibility

Copy link
Collaborator

Choose a reason for hiding this comment

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

None of the VT code in conhost is legacy, and this area of the code base is changing all the time. But we can always fix it in a follow-up PR if you don't want to do it now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks. I’m a little uncomfortable that I cannot unittest or manually test conhost. So I don’t feel right about changing that.

I think there’s no need to rush this. And Dustin is not available the next several days. I’m OK waiting for more voices and comments

Copy link
Collaborator

Choose a reason for hiding this comment

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

If you look in the Conhost folder of the of the OpenConsole solution, there's a Host.EXE project that you can run to debug conhost. In the Debugging section of the properties, the Command Arguments specify what shell to use - cmd.exe, bash.exe, etc.

As for the conhost unit testing, it'll depend on what exactly you're doing, but often that will be handled in ScreenBufferTests.cpp and/or adapterTest.cpp.

}

_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
5 changes: 4 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 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;
DHowett marked this conversation as resolved.
Show resolved Hide resolved
}

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