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

Fix potential cursor redrawing crash #2965

Merged
merged 2 commits into from
Oct 18, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/cascadia/TerminalCore/Terminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,18 @@ void Terminal::UpdateSettings(winrt::Microsoft::Terminal::Settings::ICoreSetting
proposedTop -= (proposedBottom - bufferSize.Y);
}

Cursor& cursor = _buffer->GetCursor();
auto cursorPosition = cursor.GetPosition();

// If the cursor is positioned beyond the range of the viewport, then
// set the cursor position to a legal value.
cursorPosition.X = std::min(cursorPosition.X, static_cast<SHORT>(viewportSize.X - 1));
cursorPosition.Y = std::min(cursorPosition.Y, static_cast<SHORT>(viewportSize.Y - 1));

cursor.StartDeferDrawing();
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This looks strange but it's necessary. Because SetPosition will call RedrawCursor, and eventually find its way to Terminal::IsCursorDoubleWidth(), causing the crash. So I had to disable redrawing first, correct the position, and enable redrawing. IMO the SetPosition (and related method) are too aggresive doing redrawing, which is not a good design.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, you're right. We should likely fix the design on the redrawing and come up with something better. We can take this for now. I know it's ugly and complicated to fix the right way, but I'm glad you found something workable.

cursor.SetPosition(cursorPosition);
cursor.EndDeferDrawing();

_mutableViewport = Viewport::FromDimensions({ 0, proposedTop }, viewportSize);
_scrollOffset = 0;
_NotifyScrollEvent();
Expand Down Expand Up @@ -425,6 +437,11 @@ void Terminal::_WriteBuffer(const std::wstring_view& stringView)
}
}

if (proposedCursorPosition.X > bufferSize.RightInclusive())
Copy link
Member

Choose a reason for hiding this comment

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

Did you intentionally put this back? It looks like @DHowett-MSFT just removed this in #3212

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The line the caused regression was proposedCursorPosition.Y++;. I only took the first line and reset position.X to a legal value.

Copy link
Member

Choose a reason for hiding this comment

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

OK.

Copy link
Contributor

Choose a reason for hiding this comment

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

This unfortunately caused #3277.

{
proposedCursorPosition.X = 0;
}

// If we're about to scroll past the bottom of the buffer, instead cycle the buffer.
const auto newRows = proposedCursorPosition.Y - bufferSize.Height() + 1;
if (newRows > 0)
Expand Down Expand Up @@ -533,6 +550,8 @@ void Terminal::_InitializeColorTable()
// - isVisible: whether the cursor should be visible
void Terminal::SetCursorVisible(const bool isVisible) noexcept
{
auto lock = LockForWriting();

auto& cursor = _buffer->GetCursor();
cursor.SetIsVisible(isVisible);
}
Expand Down