Skip to content

Persist window layout every few minutes #18898

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 14, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/cascadia/TerminalApp/IPaneContent.idl
Original file line number Diff line number Diff line change
@@ -8,7 +8,8 @@ namespace TerminalApp
None,
Content,
MovePane,
Persist,
PersistLayout,
PersistAll
};

runtimeclass BellEventArgs
4 changes: 2 additions & 2 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
@@ -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()));
}

2 changes: 1 addition & 1 deletion src/cascadia/TerminalApp/TerminalPage.h
Original file line number Diff line number Diff line change
@@ -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();
3 changes: 2 additions & 1 deletion src/cascadia/TerminalApp/TerminalPaneContent.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
4 changes: 2 additions & 2 deletions src/cascadia/TerminalApp/TerminalWindow.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
}

2 changes: 1 addition & 1 deletion src/cascadia/TerminalApp/TerminalWindow.h
Original file line number Diff line number Diff line change
@@ -71,7 +71,7 @@ namespace winrt::TerminalApp::implementation

void Create();

void PersistState();
void PersistState(bool serializeBuffer);

void UpdateSettings(winrt::TerminalApp::SettingsLoadEventArgs args);

2 changes: 1 addition & 1 deletion src/cascadia/TerminalApp/TerminalWindow.idl
Original file line number Diff line number Diff line change
@@ -59,7 +59,7 @@ namespace TerminalApp
Boolean ShouldImmediatelyHandoffToElevated();
void HandoffToElevated();

void PersistState();
void PersistState(Boolean serializeBuffer);

Windows.UI.Xaml.UIElement GetRoot();

29 changes: 25 additions & 4 deletions src/cascadia/WindowsTerminal/WindowEmperor.cpp
Original file line number Diff line number Diff line change
@@ -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)
{
3 changes: 3 additions & 0 deletions src/cascadia/WindowsTerminal/WindowEmperor.h
Original file line number Diff line number Diff line change
@@ -64,6 +64,8 @@ class WindowEmperor
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 @@ class WindowEmperor
bool _notificationIconShown = false;
bool _forcePersistence = false;
bool _needsPersistenceCleanup = false;
SafeDispatcherTimer _persistStateTimer;
std::optional<bool> _currentSystemThemeIsDark;
int32_t _windowCount = 0;
int32_t _messageBoxCount = 0;
Loading
Oops, something went wrong.