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

Prevent the VT engine painting unnecessarily #17194

Merged
merged 1 commit into from
May 6, 2024

Conversation

j4james
Copy link
Collaborator

@j4james j4james commented May 5, 2024

When the VT render engine starts a paint operation, it first checks to
see whether there is actually something to do, and if not it can end the
frame early. However, the result of that check was being ignored, which
could sometimes result in an unwanted SGR reset being written to the
conpty pipe.

This was particular concerning when passing through DCS sequences,
because an unexpected SGR in the middle of the DCS string would
cause it to abort early.

This PR addresses the problem by making sure the VtEngine::StartPaint
return value is appropriately handled in the XtermEngine class.

Detailed Description of the Pull Request / Additional comments

To make this work, I also needed to correct the _cursorMoved flag,
because that is one of things that determines whether a paint is needed
or not, but it was being set in the InvalidateCursor method at the
start of ever frame, regardless of whether the cursor had actually
moved.

I also took this opportunity to get rid of the _WillWriteSingleChar
method and the _quickReturn flag, which have been mostly obsolete for
a long time now. The only place the flag was still used was to optimize
single char writes when line renditions are active. But that could more
easily be handled by testing the _invalidMap directly.

Validation Steps Performed

I've confirmed that the test case in issue #17117 is no longer aborting
the DCS color table sequence early.

Closes #17117

if (_usingLineRenditions && !_quickReturn)
// when we're writing out a single character, which should preclude there
// being a rendition switch.
if (_usingLineRenditions && !_invalidMap.one())
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure if .one() returns true for a single invalid wide char, but on the other hand... meh?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, this was very much a "meh" solution, even more so when it was using quickReturn. I just wanted something that was easy to test, and not risk false positives by overcomplicating it. Most people will never be impacted by this anyway.

Copy link
Member

@DHowett DHowett left a comment

Choose a reason for hiding this comment

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

Both concise and an improvement. Thanks!

@DHowett DHowett added this pull request to the merge queue May 6, 2024
@DHowett DHowett removed this pull request from the merge queue due to a manual request May 6, 2024
@DHowett DHowett merged commit 432dfcc into microsoft:main May 6, 2024
15 checks passed
DHowett pushed a commit that referenced this pull request May 6, 2024
When the VT render engine starts a paint operation, it first checks to
see whether there is actually something to do, and if not it can end the
frame early. However, the result of that check was being ignored, which
could sometimes result in an unwanted `SGR` reset being written to the
conpty pipe.

This was particular concerning when passing through `DCS` sequences,
because an unexpected `SGR` in the middle of the `DCS` string would
cause it to abort early.

This PR addresses the problem by making sure the `VtEngine::StartPaint`
return value is appropriately handled in the `XtermEngine` class.

## Detailed Description of the Pull Request / Additional comments

To make this work, I also needed to correct the `_cursorMoved` flag,
because that is one of things that determines whether a paint is needed
or not, but it was being set in the `InvalidateCursor` method at the
start of ever frame, regardless of whether the cursor had actually
moved.

I also took this opportunity to get rid of the `_WillWriteSingleChar`
method and the `_quickReturn` flag, which have been mostly obsolete for
a long time now. The only place the flag was still used was to optimize
single char writes when line renditions are active. But that could more
easily be handled by testing the `_invalidMap` directly.

## Validation Steps Performed

I've confirmed that the test case in issue #17117 is no longer aborting
the `DCS` color table sequence early.

Closes #17117

(cherry picked from commit 432dfcc)
Service-Card-Id: 92501130
Service-Version: 1.21
github-merge-queue bot pushed a commit that referenced this pull request May 10, 2024
When the VT render engine checks whether the cursor has moved in the
`InvalidateCursor` method, it does so by comparing the origin of the
given cursor region with the last text output coordinates. But these two
values are actually from different coordinate systems, and when on a
double-width line, the x text coordinate is half of the corresponding
screen coordinate. As a result, the movement detection is sometimes
incorrect.

This PR fixes the issue by adding another field to track the last cursor
origin in screen coordinates, so we have a meaningful value to compare
against.

## References and Relevant Issues

The previous cursor movement detection was added in PR #17194 to fix
issue #17117.

## Validation Steps Performed

I've confirmed that the test case from issue #17232 is now fixed, and
the test case from issue #17117 is still working as expected.

## PR Checklist
- [x] Closes #17232
@j4james j4james deleted the fix-conpty-quickreturn branch May 20, 2024 23:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

Successfully merging this pull request may close these issues.

DCS sequences split across multiple "packets" can be corrupted by conpty
4 participants