TeamsLauncher.cs was 665 lines / 30KB and mixed two unrelated lifecycles:
launch / hide / show / in-call orchestration (the bulk of the file), and
the Phase E.4 experimental SetParent-based embedding (~160 lines of
distinct Win32 surface area + its own state machine).
* Services/TeamsEmbedHost.cs (177L, new) — public static class owning
EmbedTeamsInto / ResizeEmbedded / RestoreEmbed / IsEmbedded plus the
Win32 p/invokes specific to embedding (SetParent, GetWindowLongPtr,
SetWindowLongPtr, MoveWindow, SetWindowPos), the WS_* / SWP_* style
+ position constants, and the embed-state fields. The whole lifecycle
(reparent → resize → restore) now lives in one place; the comment
about WebView2 fragility moves with the code.
* Services/TeamsLauncher.cs (was 665L → now 510L) — keeps launch /
stop / join / hide / show / window-title / shortcut concerns. The
internal helper that enumerates Teams top-level windows is now
named EnumerateTopLevelTeamsWindows (was FindTeamsTopLevelWindows)
and marked `internal` so TeamsEmbedHost can call it without
duplicating the EnumWindows traversal — both classes use the same
process-name heuristic and the launcher's hide/show paths also
consume it.
* TeamsEmbedWindow.xaml.cs — call sites moved from TeamsLauncher.* to
TeamsEmbedHost.* (three references).
No behavior change. Build clean; 56 + 104 tests still pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>