mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-10 00:48:23 -06:00
Persist window layout every few minutes (#18898)
If `persistedWindowLayout` is enabled, we now persist the window layout every few minutes (excluding the text buffer). This was done by adding a `SafeDispatcherTimer` to the `WindowEmperor` that calls `PersistState()` every 5 minutes. For `BuildStartupKind`, I split up `Persist` into `PersistAll` and `PersistLayout`. This way, we go through all the same code flow that `Persist` had except for specifically serializing the buffer. ## Validation Steps Performed ✅ (with the timer set to 3 seconds) create a window layout and ensure the layout is restored after forcefully stopping Terminal (aka simulating a "crash") Closes #18838
This commit is contained in:
parent
9e0ca3aac0
commit
f769597d89
@ -8,7 +8,8 @@ namespace TerminalApp
|
||||
None,
|
||||
Content,
|
||||
MovePane,
|
||||
Persist,
|
||||
PersistLayout,
|
||||
PersistAll
|
||||
};
|
||||
|
||||
runtimeclass BellEventArgs
|
||||
|
||||
@ -1953,7 +1953,7 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::PersistState()
|
||||
void TerminalPage::PersistState(bool serializeBuffer)
|
||||
{
|
||||
// This method may be called for a window even if it hasn't had a tab yet or lost all of them.
|
||||
// We shouldn't persist such windows.
|
||||
@ -1968,7 +1968,7 @@ namespace winrt::TerminalApp::implementation
|
||||
for (auto tab : _tabs)
|
||||
{
|
||||
auto t = winrt::get_self<implementation::TabBase>(tab);
|
||||
auto tabActions = t->BuildStartupActions(BuildStartupKind::Persist);
|
||||
auto tabActions = t->BuildStartupActions(serializeBuffer ? BuildStartupKind::PersistAll : BuildStartupKind::PersistLayout);
|
||||
actions.insert(actions.end(), std::make_move_iterator(tabActions.begin()), std::make_move_iterator(tabActions.end()));
|
||||
}
|
||||
|
||||
|
||||
@ -113,7 +113,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
safe_void_coroutine RequestQuit();
|
||||
safe_void_coroutine CloseWindow();
|
||||
void PersistState();
|
||||
void PersistState(bool serializeBuffer);
|
||||
|
||||
void ToggleFocusMode();
|
||||
void ToggleFullscreen();
|
||||
|
||||
@ -141,7 +141,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// "attach existing" rather than a "create"
|
||||
args.ContentId(_control.ContentId());
|
||||
break;
|
||||
case BuildStartupKind::Persist:
|
||||
case BuildStartupKind::PersistAll:
|
||||
{
|
||||
const auto connection = _control.Connection();
|
||||
const auto id = connection ? connection.SessionId() : winrt::guid{};
|
||||
@ -156,6 +156,7 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BuildStartupKind::PersistLayout:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -266,11 +266,11 @@ namespace winrt::TerminalApp::implementation
|
||||
AppLogic::Current()->NotifyRootInitialized();
|
||||
}
|
||||
|
||||
void TerminalWindow::PersistState()
|
||||
void TerminalWindow::PersistState(bool serializeBuffer)
|
||||
{
|
||||
if (_root)
|
||||
{
|
||||
_root->PersistState();
|
||||
_root->PersistState(serializeBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -71,7 +71,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void Create();
|
||||
|
||||
void PersistState();
|
||||
void PersistState(bool serializeBuffer);
|
||||
|
||||
void UpdateSettings(winrt::TerminalApp::SettingsLoadEventArgs args);
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ namespace TerminalApp
|
||||
Boolean ShouldImmediatelyHandoffToElevated();
|
||||
void HandoffToElevated();
|
||||
|
||||
void PersistState();
|
||||
void PersistState(Boolean serializeBuffer);
|
||||
|
||||
Windows.UI.Xaml.UIElement GetRoot();
|
||||
|
||||
|
||||
@ -314,6 +314,7 @@ void WindowEmperor::HandleCommandlineArgs(int nCmdShow)
|
||||
_createMessageWindow(windowClassName.c_str());
|
||||
_setupGlobalHotkeys();
|
||||
_checkWindowsForNotificationIcon();
|
||||
_setupSessionPersistence(_app.Logic().Settings().GlobalSettings().ShouldUsePersistedLayout());
|
||||
|
||||
// When the settings change, we'll want to update our global hotkeys
|
||||
// and our notification icon based on the new settings.
|
||||
@ -323,6 +324,7 @@ void WindowEmperor::HandleCommandlineArgs(int nCmdShow)
|
||||
_assertIsMainThread();
|
||||
_setupGlobalHotkeys();
|
||||
_checkWindowsForNotificationIcon();
|
||||
_setupSessionPersistence(args.NewSettings().GlobalSettings().ShouldUsePersistedLayout());
|
||||
}
|
||||
});
|
||||
|
||||
@ -921,10 +923,22 @@ LRESULT WindowEmperor::_messageHandler(HWND window, UINT const message, WPARAM c
|
||||
return DefWindowProcW(window, message, wParam, lParam);
|
||||
}
|
||||
|
||||
void WindowEmperor::_finalizeSessionPersistence() const
|
||||
void WindowEmperor::_setupSessionPersistence(bool enabled)
|
||||
{
|
||||
const auto state = ApplicationState::SharedInstance();
|
||||
if (!enabled)
|
||||
{
|
||||
_persistStateTimer.Stop();
|
||||
return;
|
||||
}
|
||||
_persistStateTimer.Interval(std::chrono::minutes(5));
|
||||
_persistStateTimer.Tick([&](auto&&, auto&&) {
|
||||
_persistState(ApplicationState::SharedInstance(), false);
|
||||
});
|
||||
_persistStateTimer.Start();
|
||||
}
|
||||
|
||||
void WindowEmperor::_persistState(const ApplicationState& state, bool serializeBuffer) const
|
||||
{
|
||||
// Calling an `ApplicationState` setter triggers a write to state.json.
|
||||
// With this if condition we avoid an unnecessary write when persistence is disabled.
|
||||
if (state.PersistedWindowLayouts())
|
||||
@ -936,12 +950,19 @@ void WindowEmperor::_finalizeSessionPersistence() const
|
||||
{
|
||||
for (const auto& w : _windows)
|
||||
{
|
||||
w->Logic().PersistState();
|
||||
w->Logic().PersistState(serializeBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure to write the state.json before we TerminateProcess()
|
||||
// Ensure to write the state.json
|
||||
state.Flush();
|
||||
}
|
||||
|
||||
void WindowEmperor::_finalizeSessionPersistence() const
|
||||
{
|
||||
const auto state = ApplicationState::SharedInstance();
|
||||
|
||||
_persistState(state, true);
|
||||
|
||||
if (_needsPersistenceCleanup)
|
||||
{
|
||||
|
||||
@ -64,6 +64,8 @@ private:
|
||||
void _registerHotKey(int index, const winrt::Microsoft::Terminal::Control::KeyChord& hotkey) noexcept;
|
||||
void _unregisterHotKey(int index) noexcept;
|
||||
void _setupGlobalHotkeys();
|
||||
void _setupSessionPersistence(bool enabled);
|
||||
void _persistState(const winrt::Microsoft::Terminal::Settings::Model::ApplicationState& state, bool serializeBuffer) const;
|
||||
void _finalizeSessionPersistence() const;
|
||||
void _checkWindowsForNotificationIcon();
|
||||
|
||||
@ -77,6 +79,7 @@ private:
|
||||
bool _notificationIconShown = false;
|
||||
bool _forcePersistence = false;
|
||||
bool _needsPersistenceCleanup = false;
|
||||
SafeDispatcherTimer _persistStateTimer;
|
||||
std::optional<bool> _currentSystemThemeIsDark;
|
||||
int32_t _windowCount = 0;
|
||||
int32_t _messageBoxCount = 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user