Fix bugs introduced in #18623 (#18635)

The logic didn't work when persistence was enabled and you had 2 windows
and closed the 2nd one, or when dragging the last tab out of the only
window.

## Validation Steps Performed
* 2 windows, close the 2nd one, app doesn't exit 
* 1 window, 1 tab, drag the tab out of the window, app doesn't exit 

(cherry picked from commit 96d1407c5928330dc4cf4b3411d5bcd84341b310)
Service-Card-Id: PVTI_lADOAF3p4s4AxadtzgXxggc
Service-Version: 1.23
This commit is contained in:
Leonard Hecker 2025-02-28 14:19:35 -08:00 committed by Dustin L. Howett
parent d938f924bb
commit c1cd6d3d1d
2 changed files with 24 additions and 26 deletions

View File

@ -246,6 +246,8 @@ void WindowEmperor::CreateNewWindow(winrt::TerminalApp::WindowRequestedArgs args
auto host = std::make_shared<AppHost>(this, _app.Logic(), std::move(args));
host->Initialize();
_windowCount += 1;
_windows.emplace_back(std::move(host));
}
@ -354,10 +356,7 @@ void WindowEmperor::HandleCommandlineArgs(int nCmdShow)
}
// If we created no windows, e.g. because the args are "/?" we can just exit now.
if (_windows.empty())
{
_postQuitMessageIfNeeded();
}
_postQuitMessageIfNeeded();
}
// ALWAYS change the _real_ CWD of the Terminal to system32,
@ -738,30 +737,14 @@ void WindowEmperor::_createMessageWindow(const wchar_t* className)
StringCchCopy(_notificationIcon.szTip, ARRAYSIZE(_notificationIcon.szTip), appNameLoc.c_str());
}
// Counterpart to _postQuitMessageIfNeeded:
// If it returns true, don't close that last window, if any.
// This ensures we persist the last window.
bool WindowEmperor::_shouldSkipClosingWindows() const
{
const auto globalSettings = _app.Logic().Settings().GlobalSettings();
const size_t windowLimit = globalSettings.ShouldUsePersistedLayout() ? 1 : 0;
return _windows.size() <= windowLimit;
}
// Posts a WM_QUIT as soon as we have no reason to exist anymore.
// That basically means no windows [^1] and no message boxes.
//
// [^1] Unless:
// * We've been asked to persist the last remaining window
// in which case we exit with 1 remaining window.
// * We're allowed to be headless
// in which case we never exit.
// That basically means no windows and no message boxes.
void WindowEmperor::_postQuitMessageIfNeeded() const
{
const auto globalSettings = _app.Logic().Settings().GlobalSettings();
const size_t windowLimit = globalSettings.ShouldUsePersistedLayout() ? 1 : 0;
if (_messageBoxCount <= 0 && _windows.size() <= windowLimit && !globalSettings.AllowHeadless())
if (
_messageBoxCount <= 0 &&
_windowCount <= 0 &&
!_app.Logic().Settings().GlobalSettings().AllowHeadless())
{
PostQuitMessage(0);
}
@ -795,8 +778,20 @@ LRESULT WindowEmperor::_messageHandler(HWND window, UINT const message, WPARAM c
{
case WM_CLOSE_TERMINAL_WINDOW:
{
if (!_shouldSkipClosingWindows())
const auto globalSettings = _app.Logic().Settings().GlobalSettings();
// Keep the last window in the array so that we can persist it on exit.
// We check for AllowHeadless(), as that being true prevents us from ever quitting in the first place.
// (= If we avoided closing the last window you wouldn't be able to reach a headless state.)
const auto shouldKeepWindow =
_windows.size() == 1 &&
globalSettings.ShouldUsePersistedLayout() &&
!globalSettings.AllowHeadless();
if (!shouldKeepWindow)
{
// Did the window counter get out of sync? It shouldn't.
assert(_windowCount == gsl::narrow_cast<int32_t>(_windows.size()));
const auto host = reinterpret_cast<AppHost*>(lParam);
auto it = _windows.begin();
const auto end = _windows.end();
@ -812,6 +807,8 @@ LRESULT WindowEmperor::_messageHandler(HWND window, UINT const message, WPARAM c
}
}
// Counterpart specific to CreateNewWindow().
_windowCount -= 1;
_postQuitMessageIfNeeded();
return 0;
}

View File

@ -78,6 +78,7 @@ private:
bool _forcePersistence = false;
bool _needsPersistenceCleanup = false;
std::optional<bool> _currentSystemThemeIsDark;
int32_t _windowCount = 0;
int32_t _messageBoxCount = 0;
#ifdef NDEBUG