Repository: microsoft/terminal (language: cpp)

Issue:
Starting WT momentarily shows a black titlebar
### Windows Terminal version (or Windows build number)

10.0.19043.1288 1.12.2922.0

### Other Software

_No response_

### Steps to reproduce

Start WT.

### Expected Behavior

The GUI should start without showing a glitched black title bar, just as it did in v1.11.

### Actual Behavior

It shows a black title bar for a few milliseconds. See below:

![2](https://user-images.githubusercontent.com/46838874/138241520-f668f835-239c-45d9-a11d-409b016137c3.gif)

![1](https://user-images.githubusercontent.com/46838874/138241542-a7ec130a-2087-47e6-b34f-2f09a6642243.gif)

My [settings.json](https://github.com/rashil2000/dotfiles/blob/master/wt/settings.json) is the same as before I upgraded (through Store).
START /MIN WT?
<!-- 
🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨

I ACKNOWLEDGE THE FOLLOWING BEFORE PROCEEDING:
1. If I delete this entire template and go my own path, the core team may close my issue without further explanation or engagement.
2. If I list multiple bugs/concerns in this one issue, the core team may close my issue without further explanation or engagement.
3. If I write an issue that has many duplicates, the core team may close my issue without further explanation or engagement (and without necessarily spending time to find the exact duplicate ID number).
4. If I leave the title incomplete when filing the issue, the core team may close my issue without further explanation or engagement.
5. If I file something completely blank in the body, the core team may close my issue without further explanation or engagement.

All good? Then proceed!
-->

<!--
This bug tracker is monitored by Windows Terminal development team and other technical folks.

**Important: When reporting BSODs or security issues, DO NOT attach memory dumps, logs, or traces to Github issues**.
Instead, send dumps/traces to secure@microsoft.com, referencing this GitHub issue.

If this is an application crash, please also provide a Feedback Hub submission link so we can find your diagnostic data on the backend. Use the category "Apps > Windows Terminal (Preview)" and choose "Share My Feedback" after submission to get the link.

Please use this form and describe your issue, concisely but precisely, with as much detail as possible.

-->

# Environment
Microsoft Windows 10 Pro for Workstations
10.0.19042.746 (2009, 20H2)
WindowsTerminalPreview_1.6.10272.0_x64
```none
Windows build number: [run `[Environment]::OSVersion` for powershell, or `ver` for cmd]
Windows Terminal version (if applicable):

Any other software?
```

# Steps to reproduce

<!-- A description of how to trigger this bug. -->

In CMD.EXE, issue `START /MIN WT`

# Expected behavior
WT starts minimized and can be restored.
<!-- A description of what you're expecting, possibly containing screenshots or reference material. -->

# Actual behavior
WT starts minimized and can't be restored.  The taskbar icon is rather lame.
<!-- What's actually happening? -->

I couldn't get good pics of the taskbar icon's popup thumbnails because they close when I activate the screen clipper.
START /MIN WT?
<!-- 
🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨

I ACKNOWLEDGE THE FOLLOWING BEFORE PROCEEDING:
1. If I delete this entire template and go my own path, the core team may close my issue without further explanation or engagement.
2. If I list multiple bugs/concerns in this one issue, the core team may close my issue without further explanation or engagement.
3. If I write an issue that has many duplicates, the core team may close my issue without further explanation or engagement (and without necessarily spending time to find the exact duplicate ID number).
4. If I leave the title incomplete when filing the issue, the core team may close my issue without further explanation or engagement.
5. If I file something completely blank in the body, the core team may close my issue without further explanation or engagement.

All good? Then proceed!
-->

<!--
This bug tracker is monitored by Windows Terminal development team and other technical folks.

**Important: When reporting BSODs or security issues, DO NOT attach memory dumps, logs, or traces to Github issues**.
Instead, send dumps/traces to secure@microsoft.com, referencing this GitHub issue.

If this is an application crash, please also provide a Feedback Hub submission link so we can find your diagnostic data on the backend. Use the category "Apps > Windows Terminal (Preview)" and choose "Share My Feedback" after submission to get the link.

Please use this form and describe your issue, concisely but precisely, with as much detail as possible.

-->

# Environment
Microsoft Windows 10 Pro for Workstations
10.0.19042.746 (2009, 20H2)
WindowsTerminalPreview_1.6.10272.0_x64
```none
Windows build number: [run `[Environment]::OSVersion` for powershell, or `ver` for cmd]
Windows Terminal version (if applicable):

Any other software?
```

# Steps to reproduce

<!-- A description of how to trigger this bug. -->

In CMD.EXE, issue `START /MIN WT`

# Expected behavior
WT starts minimized and can be restored.
<!-- A description of what you're expecting, possibly containing screenshots or reference material. -->

# Actual behavior
WT starts minimized and can't be restored.  The taskbar icon is rather lame.
<!-- What's actually happening? -->

I couldn't get good pics of the taskbar icon's popup thumbnails because they close when I activate the screen clipper.


Discussion / hints:
showerthought: we could have a solid BG for the `TerminalPage` until initialization is completed, and _then_ drop out the bg. That might obscure the titlebar until the rest of the content initializes.
Note to self - that didn't work. Might need to do this higher up in Win32 land. Might need to actually start with the window painted with some color, then paint it all with `BLACK_BRUSH`


You also can't just hack this by immediately creating the window without `WS_EX_NOREDIRECTIONBITMAP` and then later turning that style on. You have to create the window with `WS_EX_NOREDIRECTIONBITMAP`, `SetWindowLong` won't work. 
see:
* https://stackoverflow.com/questions/40576394/setwindowlong-with-gwl-exstyle-and-ws-ex-noredirectionbitmap
This was something that I noticed with the upgrade to WinUI 2.7, in case that gives any help.
I suspect that this is more due to the changes we made to drop out the back of the window in #11180 
Yea, this was definitely regressed in #11180. I've spent enough time on this for this week, but made no real progress. I don't think we can just draw the BG manually in `WM_ERASEBKGND` or something, because there is not GDI redirection surface to draw to. my current crazy idea is using `CreateSwapChainForHwnd` to create a swapchain for the hwnd, draw the color to that, then make it transparent once the Island is initialized. Not sure I have time to futz with that now though. `DirectComposition` might be an easier way, but [this tutorial](https://docs.microsoft.com/en-us/windows/win32/directcomp/initialize-directcomposition) looks... long and maybe more complicated than we need. maybe next DoL. 

What we _really_ need is someone who actually understands user32 to come give us an assist on this one. 
Some gifs recorded this morning of the issue. No progress to report. 

![transparent-frame-on-launch-000](https://user-images.githubusercontent.com/18356694/142231718-05b95699-ea9b-4212-bb87-b2f690e368da.gif)
![transparent-frame-resizing-000](https://user-images.githubusercontent.com/18356694/142232692-2882b083-3142-405b-9323-e07e803dc893.gif)


Note to self: maybe we can DWM_CLOAK the window until it's initialized
Related issues, although not duplicates:

* <https://github.com/microsoft/terminal/issues/7374> a request for a `wt` command-line option that could be used instead of START /MIN.
* <https://github.com/microsoft/terminal/issues/7396> crash after START /MIN. As far as I know, it does not crash nowadays. This issue also mentions strange UI behaviour.

Yea, this is definitely unique compared to the other two. Repros easy enough. Real weird. I wonder if the OS is unhappy about us trying to set a window position when starting minimized is requested. Hard to know for sure, user32 is a mystery ¯\\\_(ツ)_/¯ 
Screenshots from Alt-Tab:

![WT weirdness](https://user-images.githubusercontent.com/75578443/107468138-7ad0d800-6b8d-11eb-810e-d197721ea1f6.png)

Related issues, although not duplicates:

* <https://github.com/microsoft/terminal/issues/7374> a request for a `wt` command-line option that could be used instead of START /MIN.
* <https://github.com/microsoft/terminal/issues/7396> crash after START /MIN. As far as I know, it does not crash nowadays. This issue also mentions strange UI behaviour.

Yea, this is definitely unique compared to the other two. Repros easy enough. Real weird. I wonder if the OS is unhappy about us trying to set a window position when starting minimized is requested. Hard to know for sure, user32 is a mystery ¯\\\_(ツ)_/¯ 
Screenshots from Alt-Tab:

![WT weirdness](https://user-images.githubusercontent.com/75578443/107468138-7ad0d800-6b8d-11eb-810e-d197721ea1f6.png)


Fix patch:
diff --git a/.github/actions/spelling/allow/apis.txt b/.github/actions/spelling/allow/apis.txt
index 682023fd96c..8084acd4f2c 100644
--- a/.github/actions/spelling/allow/apis.txt
+++ b/.github/actions/spelling/allow/apis.txt
@@ -30,6 +30,7 @@ DERR
 dlldata
 DONTADDTORECENT
 DWORDLONG
+DWMWA
 endfor
 enumset
 environstrings
@@ -154,6 +155,7 @@ serializer
 SETVERSION
 SHELLEXECUTEINFOW
 shobjidl
+SHOWDEFAULT
 SHOWHIDE
 SHOWMINIMIZED
 SHOWTIP
diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h
index 63d1c4e784d..8cbd0ff51b6 100644
--- a/src/cascadia/TerminalApp/AppLogic.h
+++ b/src/cascadia/TerminalApp/AppLogic.h
@@ -199,6 +199,7 @@ namespace winrt::TerminalApp::implementation
         FORWARDED_TYPED_EVENT(FullscreenChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, FullscreenChanged);
         FORWARDED_TYPED_EVENT(ChangeMaximizeRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, ChangeMaximizeRequested);
         FORWARDED_TYPED_EVENT(AlwaysOnTopChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, AlwaysOnTopChanged);
+        FORWARDED_TYPED_EVENT(Initialized, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, Initialized);
         FORWARDED_TYPED_EVENT(RaiseVisualBell, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, RaiseVisualBell);
         FORWARDED_TYPED_EVENT(SetTaskbarProgress, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, SetTaskbarProgress);
         FORWARDED_TYPED_EVENT(IdentifyWindowsRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IdentifyWindowsRequested);
diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl
index a5c0eb05a7b..7d659b02b09 100644
--- a/src/cascadia/TerminalApp/AppLogic.idl
+++ b/src/cascadia/TerminalApp/AppLogic.idl
@@ -122,6 +122,7 @@ namespace TerminalApp
         event Windows.Foundation.TypedEventHandler<Object, Object> FullscreenChanged;
         event Windows.Foundation.TypedEventHandler<Object, Object> ChangeMaximizeRequested;
         event Windows.Foundation.TypedEventHandler<Object, Object> AlwaysOnTopChanged;
+        event Windows.Foundation.TypedEventHandler<Object, Object> Initialized;
         event Windows.Foundation.TypedEventHandler<Object, Object> RaiseVisualBell;
         event Windows.Foundation.TypedEventHandler<Object, Object> SetTaskbarProgress;
         event Windows.Foundation.TypedEventHandler<Object, Object> IdentifyWindowsRequested;
diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp
index 2d0078c3747..9d6e8369b45 100644
--- a/src/cascadia/TerminalApp/TerminalPage.cpp
+++ b/src/cascadia/TerminalApp/TerminalPage.cpp
@@ -659,7 +659,7 @@ namespace winrt::TerminalApp::implementation
     // - <none>
     // Return Value:
     // - <none>
-    void TerminalPage::_CompleteInitialization()
+    winrt::fire_and_forget TerminalPage::_CompleteInitialization()
     {
         _startupState = StartupState::Initialized;
 
@@ -679,10 +679,55 @@ namespace winrt::TerminalApp::implementation
         if (_tabs.Size() == 0 && !(_shouldStartInboundListener || _isEmbeddingInboundListener))
         {
             _LastTabClosedHandlers(*this, nullptr);
+            co_return;
         }
         else
         {
-            _InitializedHandlers(*this, nullptr);
+            // GH#11561: When we start up, our window is initially just a frame
+            // with a transparent content area. We're gonna do all this startup
+            // init on the UI thread, so the UI won't actually paint till it's
+            // all done. This results in a few frames where the frame is
+            // visible, before the page paints for the first time, before any
+            // tabs appears, etc.
+            //
+            // To mitigate this, we're gonna wait for the UI thread to finish
+            // everything it's gotta do for the initial init, and _then_ fire
+            // our Initialized event. By waiting for everything else to finish
+            // (CoreDispatcherPriority::Low), we let all the tabs and panes
+            // actually get created. In the window layer, we're gonna cloak the
+            // window till this event is fired, so we don't actually see this
+            // frame until we're actually all ready to go.
+            //
+            // This will result in the window seemingly not loading as fast, but
+            // it will actually take exactly the same amount of time before it's
+            // usable.
+            //
+            // We also experimented with drawing a solid BG color before the
+            // initialization is finished. However, there are still a few frames
+            // after the frame is displayed before the XAML content first draws,
+            // so that didn't actually resolve any issues.
+
+            auto weak{ get_weak() };
+
+            // Switch to the BG thread -
+            co_await winrt::resume_background();
+
+            if (auto self{ weak.get() })
+            {
+                // Then enqueue the rest of this function for after the UI thread settles.
+                co_await wil::resume_foreground(self->Dispatcher(), CoreDispatcherPriority::Low);
+            }
+            else
+            {
+                // We don't exist anymore? Well, we probably don't need to fire
+                // off an Initialized event then...
+                co_return;
+            }
+
+            if (auto self{ weak.get() })
+            {
+                self->_InitializedHandlers(*self, nullptr);
+            }
         }
     }
 
diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h
index 55021a1e896..f3172daf411 100644
--- a/src/cascadia/TerminalApp/TerminalPage.h
+++ b/src/cascadia/TerminalApp/TerminalPage.h
@@ -147,7 +147,7 @@ namespace winrt::TerminalApp::implementation
         TYPED_EVENT(AlwaysOnTopChanged, IInspectable, IInspectable);
         TYPED_EVENT(RaiseVisualBell, IInspectable, IInspectable);
         TYPED_EVENT(SetTaskbarProgress, IInspectable, IInspectable);
-        TYPED_EVENT(Initialized, IInspectable, winrt::Windows::UI::Xaml::RoutedEventArgs);
+        TYPED_EVENT(Initialized, IInspectable, IInspectable);
         TYPED_EVENT(IdentifyWindowsRequested, IInspectable, IInspectable);
         TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs);
         TYPED_EVENT(IsQuakeWindowChanged, IInspectable, IInspectable);
@@ -390,7 +390,7 @@ namespace winrt::TerminalApp::implementation
 
         void _StartInboundListener();
 
-        void _CompleteInitialization();
+        winrt::fire_and_forget _CompleteInitialization();
 
         void _FocusActiveControl(IInspectable sender, IInspectable eventArgs);
 
diff --git a/src/cascadia/TerminalApp/TerminalPage.idl b/src/cascadia/TerminalApp/TerminalPage.idl
index 90d317c1d98..90d182b8d0f 100644
--- a/src/cascadia/TerminalApp/TerminalPage.idl
+++ b/src/cascadia/TerminalApp/TerminalPage.idl
@@ -51,7 +51,7 @@ namespace TerminalApp
         event Windows.Foundation.TypedEventHandler<Object, Object> FocusModeChanged;
         event Windows.Foundation.TypedEventHandler<Object, Object> FullscreenChanged;
         event Windows.Foundation.TypedEventHandler<Object, Object> AlwaysOnTopChanged;
-        event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.RoutedEventArgs> Initialized;
+        event Windows.Foundation.TypedEventHandler<Object, Object> Initialized;
         event Windows.Foundation.TypedEventHandler<Object, Object> SetTaskbarProgress;
         event Windows.Foundation.TypedEventHandler<Object, Object> IdentifyWindowsRequested;
         event Windows.Foundation.TypedEventHandler<Object, RenameWindowRequestedArgs> RenameWindowRequested;
diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp
index 8174f898011..c5847b91a23 100644
--- a/src/cascadia/WindowsTerminal/AppHost.cpp
+++ b/src/cascadia/WindowsTerminal/AppHost.cpp
@@ -73,8 +73,7 @@ AppHost::AppHost() noexcept :
     auto pfn = std::bind(&AppHost::_HandleCreateWindow,
                          this,
                          std::placeholders::_1,
-                         std::placeholders::_2,
-                         std::placeholders::_3);
+                         std::placeholders::_2);
     _window->SetCreateCallback(pfn);
 
     _window->SetSnapDimensionCallback(std::bind(&winrt::TerminalApp::AppLogic::CalcSnappedDimension,
@@ -379,6 +378,7 @@ void AppHost::Initialize()
     _revokers.FullscreenChanged = _logic.FullscreenChanged(winrt::auto_revoke, { this, &AppHost::_FullscreenChanged });
     _revokers.FocusModeChanged = _logic.FocusModeChanged(winrt::auto_revoke, { this, &AppHost::_FocusModeChanged });
     _revokers.AlwaysOnTopChanged = _logic.AlwaysOnTopChanged(winrt::auto_revoke, { this, &AppHost::_AlwaysOnTopChanged });
+    _revokers.Initialized = _logic.Initialized(winrt::auto_revoke, { this, &AppHost::_AppInitializedHandler });
     _revokers.RaiseVisualBell = _logic.RaiseVisualBell(winrt::auto_revoke, { this, &AppHost::_RaiseVisualBell });
     _revokers.SystemMenuChangeRequested = _logic.SystemMenuChangeRequested(winrt::auto_revoke, { this, &AppHost::_SystemMenuChangeRequested });
     _revokers.ChangeMaximizeRequested = _logic.ChangeMaximizeRequested(winrt::auto_revoke, { this, &AppHost::_ChangeMaximizeRequested });
@@ -520,12 +520,31 @@ LaunchPosition AppHost::_GetWindowLaunchPosition()
     return pos;
 }
 
+// Method Description:
+// - Callback for when the window is first being created (during WM_CREATE).
+//   Stash the proposed size for later. We'll need that once we're totally
+//   initialized, so that we can show the window in the right position *when we
+//   want to show it*. If we did the _initialResizeAndRepositionWindow work now,
+//   it would have no effect, because the window is not yet visible.
+// Arguments:
+// - hwnd: The HWND of the window we're about to create.
+// - proposedRect: The location and size of the window that we're about to
+//   create. We'll use this rect to determine which monitor the window is about
+//   to appear on.
+void AppHost::_HandleCreateWindow(const HWND /* hwnd */, RECT proposedRect)
+{
+    // GH#11561: Hide the window until we're totally done being initialized.
+    // More commentary in TerminalPage::_CompleteInitialization
+    _proposedRect = proposedRect;
+}
+
 // Method Description:
 // - Resize the window we're about to create to the appropriate dimensions, as
-//   specified in the settings. This will be called during the handling of
-//   WM_CREATE. We'll load the settings for the app, then get the proposed size
-//   of the terminal from the app. Using that proposed size, we'll resize the
-//   window we're creating, so that it'll match the values in the settings.
+//   specified in the settings. This is called once the app has finished it's
+//   initial setup, once we have created all the tabs, panes, etc. We'll load
+//   the settings for the app, then get the proposed size of the terminal from
+//   the app. Using that proposed size, we'll resize the window we're creating,
+//   so that it'll match the values in the settings.
 // Arguments:
 // - hwnd: The HWND of the window we're about to create.
 // - proposedRect: The location and size of the window that we're about to
@@ -534,7 +553,7 @@ LaunchPosition AppHost::_GetWindowLaunchPosition()
 // - launchMode: A LaunchMode enum reference that indicates the launch mode
 // Return Value:
 // - None
-void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, LaunchMode& launchMode)
+void AppHost::_initialResizeAndRepositionWindow(const HWND hwnd, RECT proposedRect, LaunchMode& launchMode)
 {
     launchMode = _logic.GetLaunchMode();
 
@@ -1556,3 +1575,22 @@ void AppHost::_CloseRequested(const winrt::Windows::Foundation::IInspectable& /*
     const auto pos = _GetWindowLaunchPosition();
     _logic.CloseWindow(pos);
 }
+
+void AppHost::_AppInitializedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
+                                     const winrt::Windows::Foundation::IInspectable& /*arg*/)
+{
+    // GH#11561: We're totally done being initialized. Resize the window to
+    // match the initial settings, and then call ShowWindow to finally make us
+    // visible.
+
+    LaunchMode launchMode{};
+    _initialResizeAndRepositionWindow(_window->GetHandle(), _proposedRect, launchMode);
+
+    auto nCmdShow = SW_SHOWDEFAULT;
+    if (WI_IsFlagSet(launchMode, LaunchMode::MaximizedMode))
+    {
+        nCmdShow = SW_MAXIMIZE;
+    }
+
+    ShowWindow(_window->GetHandle(), nCmdShow);
+}
diff --git a/src/cascadia/WindowsTerminal/AppHost.h b/src/cascadia/WindowsTerminal/AppHost.h
index fd95d7a406b..737c62c6cd9 100644
--- a/src/cascadia/WindowsTerminal/AppHost.h
+++ b/src/cascadia/WindowsTerminal/AppHost.h
@@ -31,6 +31,7 @@ class AppHost
 
     bool _shouldCreateWindow{ false };
     bool _useNonClientArea{ false };
+    RECT _proposedRect{};
 
     std::optional<til::throttled_func_trailing<>> _getWindowLayoutThrottler;
     winrt::Windows::Foundation::IAsyncAction _SaveWindowLayouts();
@@ -39,7 +40,7 @@ class AppHost
     void _HandleCommandlineArgs();
     winrt::Microsoft::Terminal::Settings::Model::LaunchPosition _GetWindowLaunchPosition();
 
-    void _HandleCreateWindow(const HWND hwnd, RECT proposedRect, winrt::Microsoft::Terminal::Settings::Model::LaunchMode& launchMode);
+    void _HandleCreateWindow(const HWND hwnd, RECT proposedRect);
     void _UpdateTitleBarContent(const winrt::Windows::Foundation::IInspectable& sender,
                                 const winrt::Windows::UI::Xaml::UIElement& arg);
     void _UpdateTheme(const winrt::Windows::Foundation::IInspectable&,
@@ -52,6 +53,9 @@ class AppHost
                                   const winrt::Windows::Foundation::IInspectable& arg);
     void _AlwaysOnTopChanged(const winrt::Windows::Foundation::IInspectable& sender,
                              const winrt::Windows::Foundation::IInspectable& arg);
+    void _AppInitializedHandler(const winrt::Windows::Foundation::IInspectable& sender,
+                                const winrt::Windows::Foundation::IInspectable& arg);
+
     void _RaiseVisualBell(const winrt::Windows::Foundation::IInspectable& sender,
                           const winrt::Windows::Foundation::IInspectable& arg);
     void _WindowMouseWheeled(const til::point coord, const int32_t delta);
@@ -121,6 +125,9 @@ class AppHost
                                         const winrt::Windows::Foundation::IInspectable& args);
     void _HideNotificationIconRequested(const winrt::Windows::Foundation::IInspectable& sender,
                                         const winrt::Windows::Foundation::IInspectable& args);
+
+    void _initialResizeAndRepositionWindow(const HWND hwnd, RECT proposedRect, winrt::Microsoft::Terminal::Settings::Model::LaunchMode& launchMode);
+
     std::unique_ptr<NotificationIcon> _notificationIcon;
     winrt::event_token _ReAddNotificationIconToken;
     winrt::event_token _NotificationIconPressedToken;
@@ -147,6 +154,7 @@ class AppHost
         winrt::TerminalApp::AppLogic::FullscreenChanged_revoker FullscreenChanged;
         winrt::TerminalApp::AppLogic::FocusModeChanged_revoker FocusModeChanged;
         winrt::TerminalApp::AppLogic::AlwaysOnTopChanged_revoker AlwaysOnTopChanged;
+        winrt::TerminalApp::AppLogic::Initialized_revoker Initialized;
         winrt::TerminalApp::AppLogic::RaiseVisualBell_revoker RaiseVisualBell;
         winrt::TerminalApp::AppLogic::SystemMenuChangeRequested_revoker SystemMenuChangeRequested;
         winrt::TerminalApp::AppLogic::ChangeMaximizeRequested_revoker ChangeMaximizeRequested;
diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp
index a1a79a30d7c..a995ba437c7 100644
--- a/src/cascadia/WindowsTerminal/IslandWindow.cpp
+++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp
@@ -112,7 +112,7 @@ void IslandWindow::Close()
 //        window.
 // Return Value:
 // - <none>
-void IslandWindow::SetCreateCallback(std::function<void(const HWND, const RECT, LaunchMode& launchMode)> pfn) noexcept
+void IslandWindow::SetCreateCallback(std::function<void(const HWND, const RECT)> pfn) noexcept
 {
     _pfnCreateCallback = pfn;
 }
@@ -154,19 +154,13 @@ void IslandWindow::_HandleCreateWindow(const WPARAM, const LPARAM lParam) noexce
     rc.right = rc.left + pcs->cx;
     rc.bottom = rc.top + pcs->cy;
 
-    auto launchMode = LaunchMode::DefaultMode;
     if (_pfnCreateCallback)
     {
-        _pfnCreateCallback(_window.get(), rc, launchMode);
+        _pfnCreateCallback(_window.get(), rc);
     }
 
-    auto nCmdShow = SW_SHOW;
-    if (WI_IsFlagSet(launchMode, LaunchMode::MaximizedMode))
-    {
-        nCmdShow = SW_MAXIMIZE;
-    }
-
-    ShowWindow(_window.get(), nCmdShow);
+    // GH#11561: DO NOT call ShowWindow here. The AppHost will call ShowWindow
+    // once the app has completed its initialization.
 
     UpdateWindow(_window.get());
 
diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h
index dcd805dc52f..35c1b4dc90c 100644
--- a/src/cascadia/WindowsTerminal/IslandWindow.h
+++ b/src/cascadia/WindowsTerminal/IslandWindow.h
@@ -37,7 +37,7 @@ class IslandWindow :
 
     virtual void Initialize();
 
-    void SetCreateCallback(std::function<void(const HWND, const RECT, winrt::Microsoft::Terminal::Settings::Model::LaunchMode& launchMode)> pfn) noexcept;
+    void SetCreateCallback(std::function<void(const HWND, const RECT)> pfn) noexcept;
     void SetSnapDimensionCallback(std::function<float(bool widthOrHeight, float dimension)> pfn) noexcept;
 
     void FocusModeChanged(const bool focusMode);
@@ -94,7 +94,7 @@ class IslandWindow :
     winrt::Windows::UI::Xaml::Controls::Grid _rootGrid;
     wil::com_ptr<ITaskbarList3> _taskbar;
 
-    std::function<void(const HWND, const RECT, winrt::Microsoft::Terminal::Settings::Model::LaunchMode& launchMode)> _pfnCreateCallback;
+    std::function<void(const HWND, const RECT)> _pfnCreateCallback;
     std::function<float(bool, float)> _pfnSnapDimensionCallback;
 
     void _HandleCreateWindow(const WPARAM wParam, const LPARAM lParam) noexcept;


Test patch: