Skip to content

Commit 839bae6

Browse files
Fix DECSTR cursor restore in alt screen buffer (#19918)
1 parent a1a43a4 commit 839bae6

2 files changed

Lines changed: 32 additions & 8 deletions

File tree

src/host/ut_host/ScreenBufferTests.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ class ScreenBufferTests
122122
TEST_METHOD(VtResizeDECCOLM);
123123
TEST_METHOD(VtResizePreservingAttributes);
124124

125-
TEST_METHOD(VtSoftResetCursorPosition);
125+
TEST_METHOD(VtSoftResetCursorPosition);
126+
TEST_METHOD(VtSoftResetAltBufferCursorState);
126127

127128
TEST_METHOD(VtScrollMarginsNewlineColor);
128129

@@ -1458,7 +1459,7 @@ void ScreenBufferTests::VtResizePreservingAttributes()
14581459
VERIFY_ARE_EQUAL(testAttr, si.GetTextBuffer().GetCurrentAttributes());
14591460
}
14601461

1461-
void ScreenBufferTests::VtSoftResetCursorPosition()
1462+
void ScreenBufferTests::VtSoftResetCursorPosition()
14621463
{
14631464
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
14641465
auto& si = gci.GetActiveOutputBuffer().GetActiveBuffer();
@@ -1508,7 +1509,31 @@ void ScreenBufferTests::VtSoftResetCursorPosition()
15081509
stateMachine.ProcessString(L"\x1b[5;10r");
15091510
stateMachine.ProcessString(L"\x1b[2;2H");
15101511
VERIFY_ARE_EQUAL(til::point(1, 1), cursor.GetPosition());
1511-
}
1512+
}
1513+
1514+
void ScreenBufferTests::VtSoftResetAltBufferCursorState()
1515+
{
1516+
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
1517+
gci.LockConsole(); // Lock must be taken to manipulate buffer.
1518+
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
1519+
1520+
auto& si = gci.GetActiveOutputBuffer();
1521+
auto& stateMachine = si.GetStateMachine();
1522+
1523+
Log::Comment(L"Move cursor on the main buffer.");
1524+
stateMachine.ProcessString(L"\x1b[4;7H");
1525+
VERIFY_ARE_EQUAL(til::point(6, 3), si.GetTextBuffer().GetCursor().GetPosition());
1526+
1527+
Log::Comment(L"Enter alt buffer, soft reset, and return to main buffer.");
1528+
stateMachine.ProcessString(L"\x1b[?1049h");
1529+
VERIFY_IS_TRUE(gci.GetActiveOutputBuffer()._IsAltBuffer());
1530+
stateMachine.ProcessString(L"\x1b[!p");
1531+
stateMachine.ProcessString(L"\x1b[?1049l");
1532+
VERIFY_IS_FALSE(gci.GetActiveOutputBuffer()._IsAltBuffer());
1533+
1534+
Log::Comment(L"Returning from alt buffer should restore the main cursor position.");
1535+
VERIFY_ARE_EQUAL(til::point(6, 3), gci.GetActiveOutputBuffer().GetTextBuffer().GetCursor().GetPosition());
1536+
}
15121537

15131538
void ScreenBufferTests::VtScrollMarginsNewlineColor()
15141539
{

src/terminal/adapter/adaptDispatch.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2981,11 +2981,10 @@ void AdaptDispatch::SoftReset()
29812981
SetGraphicsRendition({}); // Normal rendition.
29822982
SetCharacterProtectionAttribute({}); // Default (unprotected)
29832983

2984-
// Reset the saved cursor state.
2985-
// Note that XTerm only resets the main buffer state, but that
2986-
// seems likely to be a bug. Most other terminals reset both.
2987-
_savedCursorState.at(0) = {}; // Main buffer
2988-
_savedCursorState.at(1) = {}; // Alt buffer
2984+
// Reset only the active saved cursor state.
2985+
// This matches xterm behavior when DECSTR is processed while using
2986+
// the alternate screen buffer (GH#19918).
2987+
_savedCursorState.at(_usingAltBuffer ? 1 : 0) = {};
29892988

29902989
// The TerminalOutput state in these buffers must be reset to
29912990
// the same state as the _termOutput instance, which is not

0 commit comments

Comments
 (0)