Skip to content

Commit bdc7c4f

Browse files
authored
Show parts of the scrollback on restore (microsoft#17334)
First, this makes use of `PSEUDOCONSOLE_INHERIT_CURSOR` to stop ConPTY from emitting a CSI 2 J on startup. Then, it uses `Terminal::SetViewportPosition` to fake-scroll the viewport down so that only 3 lines of scrollback are visible. It avoids printing actual newlines because if we later change the text buffer to actually track the written contents, we don't want those newlines to end up in the next buffer snapshot. Closes microsoft#17274 ## Validation Steps Performed * Restore cmd multiple times * There's always exactly 3 lines visible ✅
1 parent ad362fc commit bdc7c4f

File tree

2 files changed

+25
-16
lines changed

2 files changed

+25
-16
lines changed

src/cascadia/TerminalApp/TerminalPage.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2994,15 +2994,6 @@ namespace winrt::TerminalApp::implementation
29942994

29952995
const auto content = _manager.CreateCore(settings.DefaultSettings(), settings.UnfocusedSettings(), connection);
29962996
const TermControl control{ content };
2997-
2998-
if (const auto id = settings.DefaultSettings().SessionId(); id != winrt::guid{})
2999-
{
3000-
const auto settingsDir = CascadiaSettings::SettingsDirectory();
3001-
const auto idStr = Utils::GuidToPlainString(id);
3002-
const auto path = fmt::format(FMT_COMPILE(L"{}\\buffer_{}.txt"), settingsDir, idStr);
3003-
control.RestoreFromPath(path);
3004-
}
3005-
30062997
return _SetupControl(control);
30072998
}
30082999

@@ -3102,7 +3093,10 @@ namespace winrt::TerminalApp::implementation
31023093
return nullptr;
31033094
}
31043095

3105-
auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profile, controlSettings.DefaultSettings(), false);
3096+
const auto sessionId = controlSettings.DefaultSettings().SessionId();
3097+
const auto hasSessionId = sessionId != winrt::guid{};
3098+
3099+
auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profile, controlSettings.DefaultSettings(), hasSessionId);
31063100
if (existingConnection)
31073101
{
31083102
connection.Resize(controlSettings.DefaultSettings().InitialRows(), controlSettings.DefaultSettings().InitialCols());
@@ -3124,6 +3118,14 @@ namespace winrt::TerminalApp::implementation
31243118

31253119
const auto control = _CreateNewControlAndContent(controlSettings, connection);
31263120

3121+
if (hasSessionId)
3122+
{
3123+
const auto settingsDir = CascadiaSettings::SettingsDirectory();
3124+
const auto idStr = Utils::GuidToPlainString(sessionId);
3125+
const auto path = fmt::format(FMT_COMPILE(L"{}\\buffer_{}.txt"), settingsDir, idStr);
3126+
control.RestoreFromPath(path);
3127+
}
3128+
31273129
auto paneContent{ winrt::make<TerminalPaneContent>(profile, _terminalSettingsCache, control) };
31283130

31293131
auto resultPane = std::make_shared<Pane>(paneContent);

src/cascadia/TerminalControl/ControlCore.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1787,12 +1787,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
17871787
// * prints " [Restored <date> <time>] <spaces until end of line> "
17881788
// * resets the color ("\x1b[m")
17891789
// * newlines
1790-
// * clears the screen ("\x1b[2J")
1791-
// The last step is necessary because we launch ConPTY without PSEUDOCONSOLE_INHERIT_CURSOR by default.
1792-
// This will cause ConPTY to emit a \x1b[2J sequence on startup to ensure it and the terminal are in-sync.
1793-
// If we didn't do a \x1b[2J ourselves as well, the user would briefly see the last state of the terminal,
1794-
// before it's quickly scrolled away once ConPTY has finished starting up, which looks weird.
1795-
message = fmt::format(FMT_COMPILE(L"\x1b[100;37m [{} {} {}]\x1b[K\x1b[m\r\n\x1b[2J"), msg, date, time);
1790+
message = fmt::format(FMT_COMPILE(L"\x1b[100;37m [{} {} {}]\x1b[K\x1b[m\r\n"), msg, date, time);
17961791
}
17971792

17981793
wchar_t buffer[32 * 1024];
@@ -1830,6 +1825,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation
18301825
}
18311826

18321827
_terminal->Write(message);
1828+
1829+
// Show 3 lines of scrollback to the user, so they know it's there. Otherwise, in particular with the well
1830+
// hidden touch scrollbars in WinUI 2 and later, there's no indication that there's something to scroll up to.
1831+
//
1832+
// We only show 3 lines because ConPTY doesn't know about our restored buffer contents initially,
1833+
// and so ReadConsole calls will return whitespace.
1834+
//
1835+
// We also avoid using actual newlines or similar here, because if we ever change our text buffer implementation
1836+
// to actually track the written contents, we don't want this to be part of the next buffer snapshot.
1837+
const auto cursorPosition = _terminal->GetCursorPosition();
1838+
const auto y = std::max(0, cursorPosition.y - 4);
1839+
_terminal->SetViewportPosition({ 0, y });
18331840
}
18341841
}
18351842

0 commit comments

Comments
 (0)