Skip to content

Commit 0c3c747

Browse files
authored
Add a system message to session restore (microsoft#17113)
This adds a system message which displays the time at which the buffer snapshot was written to disk. Additionally, this PR moves the snapshot loading into a background thread, so that the UI thread is unblocked and that multiple tabs/panes can load simultaneously. Closes microsoft#17031 Closes microsoft#17074 ## Validation Steps Performed Repeatedly closing and opening WT adds more and more messages. Currently, the messages get somewhat corrupted due to a bug in our line-wrap handling, or some similar part.
1 parent 19f43f7 commit 0c3c747

File tree

5 files changed

+92
-7
lines changed

5 files changed

+92
-7
lines changed

.github/actions/spelling/expect/expect.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,6 +1718,7 @@ sysparams
17181718
sysparamsext
17191719
SYSTEMHAND
17201720
SYSTEMMENU
1721+
SYSTEMTIME
17211722
tabview
17221723
TAdd
17231724
taef

src/cascadia/TerminalControl/ControlCore.cpp

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1777,6 +1777,38 @@ namespace winrt::Microsoft::Terminal::Control::implementation
17771777
return;
17781778
}
17791779

1780+
FILETIME lastWriteTime;
1781+
SYSTEMTIME lastWriteSystemTime;
1782+
if (!GetFileTime(file.get(), nullptr, nullptr, &lastWriteTime) ||
1783+
!FileTimeToSystemTime(&lastWriteTime, &lastWriteSystemTime))
1784+
{
1785+
return;
1786+
}
1787+
1788+
wchar_t dateBuf[256];
1789+
const auto dateLen = GetDateFormatEx(nullptr, 0, &lastWriteSystemTime, nullptr, &dateBuf[0], ARRAYSIZE(dateBuf), nullptr);
1790+
wchar_t timeBuf[256];
1791+
const auto timeLen = GetTimeFormatEx(nullptr, 0, &lastWriteSystemTime, nullptr, &timeBuf[0], ARRAYSIZE(timeBuf));
1792+
1793+
std::wstring message;
1794+
if (dateLen > 0 && timeLen > 0)
1795+
{
1796+
const auto msg = RS_(L"SessionRestoreMessage");
1797+
const std::wstring_view date{ &dateBuf[0], gsl::narrow_cast<size_t>(dateLen) };
1798+
const std::wstring_view time{ &timeBuf[0], gsl::narrow_cast<size_t>(timeLen) };
1799+
// This escape sequence string
1800+
// * sets the color to white on a bright black background ("\x1b[100;37m")
1801+
// * prints " [Restored <date> <time>] <spaces until end of line> "
1802+
// * resets the color ("\x1b[m")
1803+
// * newlines
1804+
// * clears the screen ("\x1b[2J")
1805+
// The last step is necessary because we launch ConPTY without PSEUDOCONSOLE_INHERIT_CURSOR by default.
1806+
// This will cause ConPTY to emit a \x1b[2J sequence on startup to ensure it and the terminal are in-sync.
1807+
// If we didn't do a \x1b[2J ourselves as well, the user would briefly see the last state of the terminal,
1808+
// before it's quickly scrolled away once ConPTY has finished starting up, which looks weird.
1809+
message = fmt::format(FMT_COMPILE(L"\x1b[100;37m [{} {} {}]\x1b[K\x1b[m\r\n\x1b[2J"), msg, date, time);
1810+
}
1811+
17801812
wchar_t buffer[32 * 1024];
17811813
DWORD read = 0;
17821814

@@ -1802,9 +1834,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
18021834
}
18031835
}
18041836

1805-
// This pushes the restored contents up into the scrollback.
1806-
const auto lock = _terminal->LockForWriting();
1807-
_terminal->Write(L"\x1b[2J");
1837+
{
1838+
const auto lock = _terminal->LockForWriting();
1839+
1840+
// Normally the cursor should already be at the start of the line, but let's be absolutely sure it is.
1841+
if (_terminal->GetCursorPosition().x != 0)
1842+
{
1843+
_terminal->Write(L"\r\n");
1844+
}
1845+
1846+
_terminal->Write(message);
1847+
}
18081848
}
18091849

18101850
void ControlCore::_rendererWarning(const HRESULT hr, wil::zwstring_view parameter)

src/cascadia/TerminalControl/Resources/en-US/Resources.resw

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,4 +296,8 @@ Please either install the missing font or choose another one.</value>
296296
<value>Select output</value>
297297
<comment>The tooltip for a button for selecting all of a command's output</comment>
298298
</data>
299+
<data name="SessionRestoreMessage" xml:space="preserve">
300+
<value>Restored</value>
301+
<comment>"Restored" as in "This content was restored"</comment>
302+
</data>
299303
</root>

src/cascadia/TerminalControl/TermControl.cpp

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,11 +1187,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
11871187

11881188
if (!_restorePath.empty())
11891189
{
1190-
winrt::get_self<ControlCore>(_core)->RestoreFromPath(_restorePath.c_str());
1191-
_restorePath = {};
1190+
_restoreInBackground();
1191+
}
1192+
else
1193+
{
1194+
_core.Connection().Start();
11921195
}
1193-
1194-
_core.Connection().Start();
11951196
}
11961197
else
11971198
{
@@ -1278,6 +1279,44 @@ namespace winrt::Microsoft::Terminal::Control::implementation
12781279
return true;
12791280
}
12801281

1282+
winrt::fire_and_forget TermControl::_restoreInBackground()
1283+
{
1284+
const auto path = std::exchange(_restorePath, {});
1285+
const auto weakSelf = get_weak();
1286+
winrt::apartment_context uiThread;
1287+
1288+
try
1289+
{
1290+
co_await winrt::resume_background();
1291+
1292+
const auto self = weakSelf.get();
1293+
if (!self)
1294+
{
1295+
co_return;
1296+
}
1297+
1298+
winrt::get_self<ControlCore>(_core)->RestoreFromPath(path.c_str());
1299+
}
1300+
CATCH_LOG();
1301+
1302+
try
1303+
{
1304+
co_await uiThread;
1305+
1306+
const auto self = weakSelf.get();
1307+
if (!self)
1308+
{
1309+
co_return;
1310+
}
1311+
1312+
if (const auto connection = _core.Connection())
1313+
{
1314+
connection.Start();
1315+
}
1316+
}
1317+
CATCH_LOG();
1318+
}
1319+
12811320
void TermControl::_CharacterHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
12821321
const Input::CharacterReceivedRoutedEventArgs& e)
12831322
{

src/cascadia/TerminalControl/TermControl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
319319
Reattach
320320
};
321321
bool _InitializeTerminal(const InitializeReason reason);
322+
winrt::fire_and_forget _restoreInBackground();
322323
void _SetFontSize(int fontSize);
323324
void _TappedHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& e);
324325
void _KeyDownHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::KeyRoutedEventArgs& e);

0 commit comments

Comments
 (0)