Defer layout restoration for COM activation - #551
Conversation
Keep -Embedding launches headless without discarding persisted layouts, then restore them when a normal Terminal activation is handed off. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR adjusts WindowEmperor startup/handoff behavior so that a -Embedding (COM activation) instance stays headless even when “persisted layout restore” is enabled, while preserving the previously-saved persisted layout until a subsequent normal Terminal launch is handed off to that COM instance.
Changes:
- Added a
_deferPersistedLayoutRestoreflag to gate persisted layout restoration and state persistence during-EmbeddingCOM activation. - Extracted persisted window restoration into
_restorePersistedWindows(...)and used it both at normal startup and during WM_COPYDATA handoff. - Suppressed periodic persistence writes while layout restore is deferred, to avoid overwriting the saved layout during the COM-only lifetime.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/cascadia/WindowsTerminal/WindowEmperor.h | Adds _restorePersistedWindows declaration and the _deferPersistedLayoutRestore state flag. |
| src/cascadia/WindowsTerminal/WindowEmperor.cpp | Implements deferred restore/persist logic for -Embedding COM activation and restores persisted windows on subsequent normal handoff. |
| _needsPersistenceCleanup = true; | ||
|
|
||
| uint32_t startIdx = 0; | ||
| for (const auto layout : layouts) | ||
| { | ||
| hstring args[] = { L"wt", L"-w", L"new", L"-s", winrt::to_hstring(startIdx) }; | ||
| _dispatchCommandlineCommon(args, currentDirectory, envString, showWindowCommand); | ||
| startIdx += 1; | ||
| } |
…ut-restore-for-com # Conflicts: # src/cascadia/WindowsTerminal/WindowEmperor.cpp
| const auto restoredPersistedWindows = _deferPersistedLayoutRestore && _restorePersistedWindows(handoff.cwd, handoff.env, handoff.show); | ||
| if (!restoredPersistedWindows || argv.size() != 1) | ||
| { | ||
| _dispatchCommandlineCommon(argv, handoff.cwd, handoff.env, handoff.show); | ||
| } |
| { | ||
| _deferPersistedLayoutRestore = false; | ||
| const auto previousWindowCount = _windows.size(); | ||
|
|
The headless COM activation path deferred the saved-layout restore but only replayed it on a WM_COPYDATA handoff. A defterm ConPTY handoff or a named window request would create a window without ever restoring the layout, stranding it until the next process start. Route the deferred restore through _restoreDeferredPersistedLayouts() and call it from the ConPTY handoff and OpenWindow() paths as well. Capture the startup directory, environment and show command so those later entry points can supply the launch context. Also guard _finalizeSessionPersistence() and make the restore exception safe. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 75cc51f7-c713-48cb-a8d7-c8e0d54b39d5
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/cascadia/WindowsTerminal/WindowEmperor.cpp:1393
- The deferred-layout restore path is not actually reached from all UI activation entry points. If the process is started with
-Embedding(so_deferPersistedLayoutRestoreis true) and the first visible activation happens via a global hotkey,_hotkeyPressedcalls_dispatchCommandlineCommondirectly (no_restoreDeferredPersistedLayouts), andCreateNewWindowclears_deferPersistedLayoutRestore—so the persisted layout may never be restored and can be overwritten by subsequent persistence.
Consider invoking _restoreDeferredPersistedLayouts(...) in _hotkeyPressed (and any other code paths that can create the first visible window) before dispatching commandlines.
// Runs the layout restore that a headless COM activation skipped. Called from
// every entry point that turns this process into a visible Terminal, so the
// saved layout comes back with the first real window instead of being stranded
// until the next process start. Returns false when there was nothing deferred
// or nothing to restore, so callers can fall back to their usual behavior.
bool WindowEmperor::_restoreDeferredPersistedLayouts(wil::zwstring_view currentDirectory, wil::zwstring_view envString, uint32_t showWindowCommand)
Our ExeServer registers both the defterm handoff class and TerminalProtocolComServer, so an -Embedding launch is just as likely a wtcli protocol activation as a console handoff. Say so where we decide to stay headless. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 75cc51f7-c713-48cb-a8d7-c8e0d54b39d5
| { | ||
| std::lock_guard lock{ _windowsMutex }; | ||
| _windows.emplace_back(std::move(host)); | ||
| } | ||
| _deferPersistedLayoutRestore = false; |
Summary
-EmbeddingCOM activation headless when persisted layout restore is enabledValidation
WindowsTerminalCascadiaPackageDebug