Fix a crash in _makeCursorVisible (#19329)

Fixes the crash and also makes `SnapOnOutput` a bit nicer.

Closes #19325

## Validation Steps Performed
* Launch vim in WSL
* Exit
* No crash ✅
This commit is contained in:
Leonard Hecker authored and GitHub committed 2025-09-10 21:21:46 +02:00
1 parent 5a05f82f7c
commit 384932183f
2 files changed
+33 -10

No files matched your search

+13
View File
@@ -1718,6 +1718,19 @@ void SCREEN_INFORMATION::SnapOnInput(const WORD vkey)
}
}
SCREEN_INFORMATION::SnapOnScopeExit SCREEN_INFORMATION::SnapOnOutput() noexcept
{
const auto call =
// We don't need to snap-on-output the alt buffer since it doesn't scroll anyway.
// More importantly though, in the current architecture the alt buffer gets deallocated
// the second we receive a \033[?1049l, which makes our this pointer hazardous to use.
_psiMainBuffer == nullptr &&
// We only want to snap if the user didn't intentionally scroll away.
// The snapping logic could be improved, but it's alright for now.
_viewport.IsInBounds(_textBuffer->GetCursor().GetPosition());
return SnapOnScopeExit{ call ? this : nullptr };
}
void SCREEN_INFORMATION::_makeCursorVisible()
{
if (_textBuffer->GetCursor().IsVisible())
+20 -10
View File
@@ -50,6 +50,25 @@ class ConversionAreaInfo; // forward decl window. circular reference
class SCREEN_INFORMATION : public ConsoleObjectHeader, public Microsoft::Console::IIoProvider
{
public:
// This little helper works like wil::scope_exit but is slimmer
// (= easier to optimize) and has a concrete type (= can declare).
struct SnapOnScopeExit
{
~SnapOnScopeExit()
{
if (self)
{
try
{
self->_makeCursorVisible();
}
CATCH_LOG();
}
}
SCREEN_INFORMATION* self;
};
[[nodiscard]] static NTSTATUS CreateInstance(_In_ til::size coordWindowSize,
const FontInfo fontInfo,
_In_ til::size coordScreenBufferSize,
@@ -73,16 +92,7 @@ public:
void MakeCurrentCursorVisible();
void MakeCursorVisible(til::point position);
void SnapOnInput(WORD vkey);
auto SnapOnOutput() noexcept
{
const auto inBounds = _viewport.IsInBounds(_textBuffer->GetCursor().GetPosition());
return wil::scope_exit([this, inBounds]() {
if (inBounds)
{
_makeCursorVisible();
}
});
}
SnapOnScopeExit SnapOnOutput() noexcept;
void ClipToScreenBuffer(_Inout_ til::inclusive_rect* const psrClip) const;