-
Notifications
You must be signed in to change notification settings - Fork 8.8k
Move all blink handling into Renderer #19330
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
base: main
Are you sure you want to change the base?
Conversation
This comment has been minimized.
This comment has been minimized.
4de989d
to
8d17e85
Compare
8d17e85
to
8390d60
Compare
Goal: Remove `CursorBlinker`. Problem: Spooky action at a distance via `Cursor::HasMoved`. Solution: Moved all the a11y event raising into `_stream.cpp` and pray for the best. Goal: Prevent node.js from tanking conhost performance via MSAA (WHY). Problem: `ServiceLocator`. Solution: Unserviced the locator. Debounced event raising. Performance increased by >10x. Problem 2: Lots of files changed. This PR is a prerequisite for #19330 ## Validation Steps Performed Ran NVDA with and without UIA enabled and with different delays. ✅
8390d60
to
5742c64
Compare
5742c64
to
1c23430
Compare
|
||
void _stdcall TerminalSetCursorVisible(void* terminal, const bool visible) | ||
try | ||
void HwndTerminal::_setFocused(bool focused) noexcept |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Big fan of this. It's nice that it's all in one function 😊
#define FOREACH_ENGINE(var) \ | ||
for (auto var : _engines) \ | ||
if (!var) \ | ||
break; \ | ||
else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh. We don't need the if (!var) break
anymore?
else if (!IsTimerRunning(_cursorBlinker)) | ||
{ | ||
const auto actual = GetTimerInterval(_cursorBlinker); | ||
auto expected = _pData->GetBlinkInterval(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto expected = _pData->GetBlinkInterval(); | |
const auto expected = _pData->GetBlinkInterval(); |
const?
|
||
bool RenderData::IsUiaDataInitialized() const noexcept | ||
{ | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Double checking) In terminalrenderdata.cpp, we have this:
terminal/src/cascadia/TerminalCore/terminalrenderdata.cpp
Lines 226 to 234 in 1b712b2
bool Terminal::IsUiaDataInitialized() const noexcept | |
{ | |
// GH#11135: Windows Terminal needs to create and return an automation peer | |
// when a screen reader requests it. However, the terminal might not be fully | |
// initialized yet. So we use this to check if any crucial components of | |
// UiaData are not yet initialized. | |
_assertLocked(); | |
return !!_mainBuffer; | |
} |
We don't need to check the buffer here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Terminal's startup is less consistent and orderly than conhost
// initialize cursor GH#4102 - Typically, the cursor is set to on by the | ||
// cursor blinker. Unfortunately, in conpty mode, there is no cursor | ||
// blinker. So, in conpty mode, we need to leave the cursor on always. The | ||
// cursor can still be set to hidden, and whether the cursor should be | ||
// blinking will still be passed through to the terminal, but internally, | ||
// the cursor should always be on. | ||
// | ||
// In particular, some applications make use of a calling | ||
// `SetConsoleScreenBuffer` and `SetCursorPosition` without printing any | ||
// text in between these calls. If we initialize the cursor to Off in conpty | ||
// mode, then the cursor will remain off until they print text. This can | ||
// lead to alignment problems in the terminal, because we won't move the | ||
// terminal's cursor in this _exact_ scenario. | ||
screenInfo.GetTextBuffer().GetCursor().SetIsOn(gci.IsInVtIoMode()); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... Do we need to worry about this scenario still?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope. ConPTY no longer renders, so it no longer needs to even care about the cursor being On, and now IsOn
is also dead because IsOn
was the thing we toggled every half second and that responsibility has left this planet.
// We trigger a scroll rather than a redraw, since that's more efficient, | ||
// but we need to turn the cursor off before doing so; otherwise, a ghost | ||
// cursor can be left behind in the previous position. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update the comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
50/56
<ClCompile Include="..\renderer.cpp"> | ||
<Filter>Source Files</Filter> | ||
</ClCompile> | ||
<ClCompile Include="..\thread.cpp"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove the whole file as well, and update sources
. that will also help git tell us which lines are the same in the old and new code
// - <none> | ||
// Return Value: | ||
// - <none> | ||
void Window::_UpdateSystemMetrics() const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 Make sure nobody else called this who cares about the cursor metrics (probably not)
cursor.SetSize(_d->ulSavedCursorSize); | ||
cursor.SetIsVisible(_d->fSavedCursorVisible); | ||
cursor.SetType(_d->savedCursorType); | ||
cursor.SetIsOn(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 make sure selection has the same cursor behavior
|
||
bool RenderData::IsUiaDataInitialized() const noexcept | ||
{ | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Terminal's startup is less consistent and orderly than conhost
// initialize cursor GH#4102 - Typically, the cursor is set to on by the | ||
// cursor blinker. Unfortunately, in conpty mode, there is no cursor | ||
// blinker. So, in conpty mode, we need to leave the cursor on always. The | ||
// cursor can still be set to hidden, and whether the cursor should be | ||
// blinking will still be passed through to the terminal, but internally, | ||
// the cursor should always be on. | ||
// | ||
// In particular, some applications make use of a calling | ||
// `SetConsoleScreenBuffer` and `SetCursorPosition` without printing any | ||
// text in between these calls. If we initialize the cursor to Off in conpty | ||
// mode, then the cursor will remain off until they print text. This can | ||
// lead to alignment problems in the terminal, because we won't move the | ||
// terminal's cursor in this _exact_ scenario. | ||
screenInfo.GetTextBuffer().GetCursor().SetIsOn(gci.IsInVtIoMode()); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope. ConPTY no longer renders, so it no longer needs to even care about the cursor being On, and now IsOn
is also dead because IsOn
was the thing we toggled every half second and that responsibility has left this planet.
return; | ||
} | ||
|
||
// NOTE: The assumption is that you're holding the console lock when calling any of the member functions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm - what happened here? doesn't this check above need to be under lock?
{ | ||
// Enter Mark Mode | ||
// NOTE: directly set cursor state. We already should have locked before calling this function. | ||
_activeBuffer().GetCursor().SetIsOn(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need to inhibit the cursor?
|
||
void Terminal::BlinkCursor() noexcept | ||
{ | ||
if (_selectionMode != SelectionInteractionMode::Mark) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need to inhibit the cursor for mark mode
return; | ||
} | ||
|
||
if (_displayCursorWhileBlurred()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 we still need the "force blinking when unfocused" behavior - need to confirm it still works
|
||
// Set up blinking attributes | ||
auto animationsEnabled = TRUE; | ||
SystemParametersInfoW(SPI_GETCLIENTAREAANIMATION, 0, &animationsEnabled, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 must make sure disabling animations windows-wide disables blink too
Note that this PR is not quite finished (~90%?). Missing:
This PR moves the cursor blinker and VT blink rendition timer into
Renderer
. To do so, this PR introduces a generic timer system with which you can schedule arbitrary timer jobs. Thanks to this, this PR removes a crapton of code, particularly throughout conhost, and improves throughput by another ~10%. On my PC it can now churn through >400MB/s while rendering at 240FPS. Fun fact: Processing 100kB of text and rendering it in conhost now takes less time than MSCTF (TSF) needs to process 1 keyboard character. When I look at our shell code.Validation Steps Performed