Skip to content

Commit

Permalink
Fix the DECTCEM reset position in the conpty stream (#17148)
Browse files Browse the repository at this point in the history
## Summary of the Pull Request

When the conpty renderer determines that it needs to hide the cursor,
it does so by inserting a `DECTCEM` reset sequence at the start of the
output buffer, assuming that is the start of the frame. But when the
`_noFlushOnEnd` flag is set, you can have multiple frames pending in the
buffer, and the `DECTCEM` sequence will then end up in the wrong place.

This PR fixes the issue by saving the buffer size at the start of the
frame, and using that saved offset as the insert position for the
`DECTCEM` sequence.

## Validation Steps Performed

I have a game that was frequently affected by this issue (the cursor
would be visible when it was meant to be hidden). With this PR applied,
it now works perfectly.

## PR Checklist
- [x] Closes #15449
  • Loading branch information
j4james authored Apr 29, 2024
1 parent 9bbe019 commit 172229d
Show file tree
Hide file tree
Showing 3 changed files with 4 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/renderer/vt/XtermEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe,
// visible, then PaintCursor will be called, and we'll set this to true
// during the frame.
_nextCursorIsVisible = false;
_startOfFrameBufferIndex = _buffer.size();

// Do not perform synchronization clearing in passthrough mode.
// In passthrough, the terminal leads and we follow what it is
Expand Down Expand Up @@ -112,7 +113,7 @@ XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe,
// by prepending a cursor off.
if (_lastCursorIsVisible != Tribool::False)
{
_buffer.insert(0, "\x1b[?25l");
_buffer.insert(_startOfFrameBufferIndex, "\x1b[?25l");
_lastCursorIsVisible = Tribool::False;
}
// If the cursor was NOT previously visible, then that's fine! we don't
Expand Down
1 change: 1 addition & 0 deletions src/renderer/vt/state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ void VtEngine::_flushImpl() noexcept
{
const auto fSuccess = WriteFile(_hFile.get(), _buffer.data(), gsl::narrow_cast<DWORD>(_buffer.size()), nullptr, nullptr);
_buffer.clear();
_startOfFrameBufferIndex = 0;
if (!fSuccess)
{
LOG_LAST_ERROR();
Expand Down
1 change: 1 addition & 0 deletions src/renderer/vt/vtrenderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ namespace Microsoft::Console::Render
protected:
wil::unique_hfile _hFile;
std::string _buffer;
size_t _startOfFrameBufferIndex = 0;

std::string _formatBuffer;
std::string _conversionBuffer;
Expand Down

0 comments on commit 172229d

Please sign in to comment.