Repository: microsoft/terminal (language: cpp)

Issue:
"Open Terminal here" doesn't show a window on 1.18
Probably regressed in #13838, though following up with Leonard on which build he's on specifically. 

On my `dev/lhecker/14957-fix-resize-glitch` current dev build, I can't repro it
"Open Terminal here" doesn't show a window on 1.18
Probably regressed in #13838, though following up with Leonard on which build he's on specifically. 

On my `dev/lhecker/14957-fix-resize-glitch` current dev build, I can't repro it


Discussion / hints:

Fix patch:
diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt
index 1dfaa076cd5..c8cc9565e6a 100644
--- a/.github/actions/spelling/expect/expect.txt
+++ b/.github/actions/spelling/expect/expect.txt
@@ -804,6 +804,7 @@ HIBYTE
 hicon
 HIDEWINDOW
 hinst
+Hirots
 HISTORYBUFS
 HISTORYNODUP
 HISTORYSIZE
diff --git a/src/cascadia/Remoting/CommandlineArgs.h b/src/cascadia/Remoting/CommandlineArgs.h
index 5277e1c5f2b..4d40c898a62 100644
--- a/src/cascadia/Remoting/CommandlineArgs.h
+++ b/src/cascadia/Remoting/CommandlineArgs.h
@@ -14,9 +14,11 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
         }
 
         CommandlineArgs(const winrt::array_view<const winrt::hstring>& args,
-                        winrt::hstring currentDirectory) :
+                        winrt::hstring currentDirectory,
+                        const uint32_t showWindowCommand) :
             _args{ args.begin(), args.end() },
-            _cwd{ currentDirectory }
+            _cwd{ currentDirectory },
+            _ShowWindowCommand{ showWindowCommand }
         {
         }
 
@@ -25,6 +27,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
         void Commandline(const winrt::array_view<const winrt::hstring>& value);
         winrt::com_array<winrt::hstring> Commandline();
 
+        WINRT_PROPERTY(uint32_t, ShowWindowCommand, SW_NORMAL); // SW_NORMAL is 1, 0 is SW_HIDE
+
     private:
         winrt::com_array<winrt::hstring> _args;
         winrt::hstring _cwd;
diff --git a/src/cascadia/Remoting/Monarch.h b/src/cascadia/Remoting/Monarch.h
index ef311fad4e1..3b5cc7d9abe 100644
--- a/src/cascadia/Remoting/Monarch.h
+++ b/src/cascadia/Remoting/Monarch.h
@@ -46,7 +46,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
             _Id{ windowInfo.Id() ? windowInfo.Id().Value() : 0 }, // We'll use 0 as a sentinel, since no window will ever get to have that ID
             _WindowName{ windowInfo.WindowName() },
             _args{ command.Commandline() },
-            _CurrentDirectory{ command.CurrentDirectory() } {};
+            _CurrentDirectory{ command.CurrentDirectory() },
+            _ShowWindowCommand{ command.ShowWindowCommand() } {};
 
         WindowRequestedArgs(const winrt::hstring& window, const winrt::hstring& content, const Windows::Foundation::IReference<Windows::Foundation::Rect>& bounds) :
             _Id{ 0u },
@@ -63,6 +64,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
         WINRT_PROPERTY(winrt::hstring, WindowName);
         WINRT_PROPERTY(winrt::hstring, CurrentDirectory);
         WINRT_PROPERTY(winrt::hstring, Content);
+        WINRT_PROPERTY(uint32_t, ShowWindowCommand, SW_NORMAL);
         WINRT_PROPERTY(Windows::Foundation::IReference<Windows::Foundation::Rect>, InitialBounds);
 
     private:
diff --git a/src/cascadia/Remoting/Monarch.idl b/src/cascadia/Remoting/Monarch.idl
index bc60fbe2c71..cc2c45f5426 100644
--- a/src/cascadia/Remoting/Monarch.idl
+++ b/src/cascadia/Remoting/Monarch.idl
@@ -26,6 +26,7 @@ namespace Microsoft.Terminal.Remoting
 
         String[] Commandline { get; };
         String CurrentDirectory { get; };
+        UInt32 ShowWindowCommand { get; };
 
         String Content { get; };
         Windows.Foundation.IReference<Windows.Foundation.Rect> InitialBounds { get; };
diff --git a/src/cascadia/Remoting/Peasant.idl b/src/cascadia/Remoting/Peasant.idl
index 2b8780cae8d..89e2b52db2c 100644
--- a/src/cascadia/Remoting/Peasant.idl
+++ b/src/cascadia/Remoting/Peasant.idl
@@ -7,10 +7,11 @@ namespace Microsoft.Terminal.Remoting
     runtimeclass CommandlineArgs
     {
         CommandlineArgs();
-        CommandlineArgs(String[] args, String cwd);
+        CommandlineArgs(String[] args, String cwd, UInt32 showWindowCommand);
 
         String[] Commandline { get; set; };
         String CurrentDirectory();
+        UInt32 ShowWindowCommand { get; };
     };
 
     runtimeclass RenameRequestArgs
diff --git a/src/cascadia/Remoting/WindowManager.cpp b/src/cascadia/Remoting/WindowManager.cpp
index f53928398cf..b0aa010402a 100644
--- a/src/cascadia/Remoting/WindowManager.cpp
+++ b/src/cascadia/Remoting/WindowManager.cpp
@@ -350,7 +350,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
         // If the name wasn't specified, this will be an empty string.
         p->WindowName(args.WindowName());
 
-        p->ExecuteCommandline(*winrt::make_self<CommandlineArgs>(args.Commandline(), args.CurrentDirectory()));
+        p->ExecuteCommandline(*winrt::make_self<CommandlineArgs>(args.Commandline(), args.CurrentDirectory(), args.ShowWindowCommand()));
 
         _monarch.AddPeasant(*p);
 
diff --git a/src/cascadia/ShellExtension/OpenTerminalHere.cpp b/src/cascadia/ShellExtension/OpenTerminalHere.cpp
index 34360d9d7e1..f50c5883cbf 100644
--- a/src/cascadia/ShellExtension/OpenTerminalHere.cpp
+++ b/src/cascadia/ShellExtension/OpenTerminalHere.cpp
@@ -44,6 +44,10 @@ try
         STARTUPINFOEX siEx{ 0 };
         siEx.StartupInfo.cb = sizeof(STARTUPINFOEX);
 
+        // Explicitly create the terminal window visible.
+        siEx.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
+        siEx.StartupInfo.wShowWindow = SW_SHOWNORMAL;
+
         std::filesystem::path modulePath{ wil::GetModuleFileNameW<std::wstring>(wil::GetModuleInstanceHandle()) };
         std::wstring cmdline;
         if (runElevated)
diff --git a/src/cascadia/UnitTests_Remoting/RemotingTests.cpp b/src/cascadia/UnitTests_Remoting/RemotingTests.cpp
index 0599aa980af..0b8a07ddfe1 100644
--- a/src/cascadia/UnitTests_Remoting/RemotingTests.cpp
+++ b/src/cascadia/UnitTests_Remoting/RemotingTests.cpp
@@ -431,7 +431,7 @@ namespace RemotingUnitTests
         m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
 
         std::vector<winrt::hstring> args{};
-        Remoting::CommandlineArgs eventArgs{ { args }, { L"" } };
+        Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL };
 
         auto result = m0->ProposeCommandline(eventArgs);
         VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow());
@@ -468,7 +468,7 @@ namespace RemotingUnitTests
         });
 
         std::vector<winrt::hstring> args{ L"1", L"arg[1]" };
-        Remoting::CommandlineArgs eventArgs{ { args }, { L"" } };
+        Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL };
 
         auto result = m0->ProposeCommandline(eventArgs);
         VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow());
@@ -489,7 +489,7 @@ namespace RemotingUnitTests
 
         {
             std::vector<winrt::hstring> args{ L"-1" };
-            Remoting::CommandlineArgs eventArgs{ { args }, { L"" } };
+            Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL };
 
             auto result = m0->ProposeCommandline(eventArgs);
             VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow());
@@ -497,7 +497,7 @@ namespace RemotingUnitTests
         }
         {
             std::vector<winrt::hstring> args{ L"-2" };
-            Remoting::CommandlineArgs eventArgs{ { args }, { L"" } };
+            Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL };
 
             auto result = m0->ProposeCommandline(eventArgs);
             VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow());
@@ -534,7 +534,7 @@ namespace RemotingUnitTests
                                                          winrt::clock().now() };
             p1->ActivateWindow(activatedArgs);
 
-            Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" } };
+            Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" }, SW_NORMAL };
 
             auto result = m0->ProposeCommandline(eventArgs);
             VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow());
@@ -559,7 +559,7 @@ namespace RemotingUnitTests
             p2->ActivateWindow(activatedArgs);
 
             Log::Comment(L"Send a commandline to the current window, which should be p2");
-            Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" } };
+            Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" }, SW_NORMAL };
             auto result = m0->ProposeCommandline(eventArgs);
             VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow());
             VERIFY_ARE_EQUAL(false, (bool)result.Id());
@@ -572,7 +572,7 @@ namespace RemotingUnitTests
             p1->ActivateWindow(activatedArgs);
 
             Log::Comment(L"Send a commandline to the current window, which should be p1 again");
-            Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" } };
+            Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" }, SW_NORMAL };
             auto result = m0->ProposeCommandline(eventArgs);
             VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow());
             VERIFY_ARE_EQUAL(false, (bool)result.Id());
@@ -593,7 +593,7 @@ namespace RemotingUnitTests
 
         {
             std::vector<winrt::hstring> args{ L"2" };
-            Remoting::CommandlineArgs eventArgs{ { args }, { L"" } };
+            Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL };
 
             auto result = m0->ProposeCommandline(eventArgs);
             VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow());
@@ -602,7 +602,7 @@ namespace RemotingUnitTests
         }
         {
             std::vector<winrt::hstring> args{ L"10" };
-            Remoting::CommandlineArgs eventArgs{ { args }, { L"" } };
+            Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL };
 
             auto result = m0->ProposeCommandline(eventArgs);
             VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow());
@@ -648,7 +648,7 @@ namespace RemotingUnitTests
         {
             Log::Comment(L"Send a commandline to p2, who is still alive. We won't create a new window.");
 
-            Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" } };
+            Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" }, SW_NORMAL };
 
             auto result = m0->ProposeCommandline(eventArgs);
             VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow());
@@ -656,7 +656,7 @@ namespace RemotingUnitTests
         }
         {
             Log::Comment(L"Send a commandline to p1, who is dead. We will create a new window.");
-            Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" } };
+            Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" }, SW_NORMAL };
 
             auto result = m0->ProposeCommandline(eventArgs);
             VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow());
@@ -1359,7 +1359,7 @@ namespace RemotingUnitTests
         std::vector<winrt::hstring> p2Args{ L"two", L"this is for p2" };
 
         {
-            Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" } };
+            Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" }, SW_NORMAL };
             auto result = m0->ProposeCommandline(eventArgs);
             VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow());
             VERIFY_ARE_EQUAL(false, (bool)result.Id()); // Casting to (bool) checks if the reference has a value
@@ -1368,7 +1368,7 @@ namespace RemotingUnitTests
 
         {
             Log::Comment(L"Send a commandline to \"two\", which should be p2");
-            Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" } };
+            Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" }, SW_NORMAL };
             auto result = m0->ProposeCommandline(eventArgs);
             VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow());
             VERIFY_ARE_EQUAL(false, (bool)result.Id()); // Casting to (bool) checks if the reference has a value
@@ -1380,7 +1380,7 @@ namespace RemotingUnitTests
 
         {
             Log::Comment(L"Send a commandline to \"two\", who is now dead.");
-            Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" } };
+            Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" }, SW_NORMAL };
             auto result = m0->ProposeCommandline(eventArgs);
             VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow());
             VERIFY_ARE_EQUAL(false, (bool)result.Id()); // Casting to (bool) checks if the reference has a value
@@ -2392,7 +2392,7 @@ namespace RemotingUnitTests
         VERIFY_ARE_EQUAL(p1->GetID(), m0->_mruPeasants[1].PeasantID());
 
         std::vector<winrt::hstring> commandlineArgs{ L"0", L"arg[1]" };
-        Remoting::CommandlineArgs eventArgs{ { commandlineArgs }, { L"" } };
+        Remoting::CommandlineArgs eventArgs{ { commandlineArgs }, { L"" }, SW_NORMAL };
 
         Log::Comment(L"When we attempt to send a commandline to the MRU window,"
                      L" we should find peasant 1 (who's name is \"one\"), not 2"
@@ -2577,7 +2577,7 @@ namespace RemotingUnitTests
         auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
 
         {
-            Remoting::CommandlineArgs args{ { L"wt.exe" }, { L"-Embedding" } };
+            Remoting::CommandlineArgs args{ { L"wt.exe" }, { L"-Embedding" }, SW_NORMAL };
             const auto result = m0->ProposeCommandline(args);
             auto shouldCreateWindow = result.ShouldCreateWindow();
             VERIFY_IS_TRUE(shouldCreateWindow);
@@ -2585,7 +2585,7 @@ namespace RemotingUnitTests
 
         auto m1 = make_self<DeadMonarch>();
         {
-            Remoting::CommandlineArgs args{ { L"wt.exe" }, { L"-Embedding" } };
+            Remoting::CommandlineArgs args{ { L"wt.exe" }, { L"-Embedding" }, SW_NORMAL };
 
             try
             {
diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp
index 9866cb74e26..6074e3e238a 100644
--- a/src/cascadia/WindowsTerminal/AppHost.cpp
+++ b/src/cascadia/WindowsTerminal/AppHost.cpp
@@ -188,6 +188,8 @@ void AppHost::_HandleCommandlineArgs(const Remoting::WindowRequestedArgs& window
             }
         }
 
+        _launchShowWindowCommand = windowArgs.ShowWindowCommand();
+
         // This is a fix for GH#12190 and hopefully GH#12169.
         //
         // If the commandline we were provided is going to result in us only
@@ -1247,7 +1249,12 @@ winrt::fire_and_forget AppHost::_WindowInitializedHandler(const winrt::Windows::
     // match the initial settings, and then call ShowWindow to finally make us
     // visible.
 
-    auto nCmdShow = SW_SHOW;
+    // Use the visibility that we were originally requested with as a base. We
+    // can't just use SW_SHOWDEFAULT, because that is set on a per-process
+    // basis. That means that a second window needs to have its STARTUPINFO's
+    // wShowCmd passed into the original process.
+    auto nCmdShow = _launchShowWindowCommand;
+
     if (WI_IsFlagSet(_launchMode, LaunchMode::MaximizedMode))
     {
         nCmdShow = SW_MAXIMIZE;
diff --git a/src/cascadia/WindowsTerminal/AppHost.h b/src/cascadia/WindowsTerminal/AppHost.h
index 6fa0c5c2191..695a07fc895 100644
--- a/src/cascadia/WindowsTerminal/AppHost.h
+++ b/src/cascadia/WindowsTerminal/AppHost.h
@@ -43,6 +43,8 @@ class AppHost
 
     std::shared_ptr<ThrottledFuncTrailing<bool>> _showHideWindowThrottler;
 
+    uint32_t _launchShowWindowCommand{ SW_NORMAL };
+
     void _preInit();
 
     void _HandleCommandlineArgs(const winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs& args);
diff --git a/src/cascadia/WindowsTerminal/WindowEmperor.cpp b/src/cascadia/WindowsTerminal/WindowEmperor.cpp
index 1284bd80370..9e851dcf8fe 100644
--- a/src/cascadia/WindowsTerminal/WindowEmperor.cpp
+++ b/src/cascadia/WindowsTerminal/WindowEmperor.cpp
@@ -73,7 +73,15 @@ bool WindowEmperor::HandleCommandlineArgs()
     _buildArgsFromCommandline(args);
     auto cwd{ wil::GetCurrentDirectoryW<std::wstring>() };
 
-    Remoting::CommandlineArgs eventArgs{ { args }, { cwd } };
+    // Get the requested initial state of the window from our startup info. For
+    // something like `start /min`, this will set the wShowWindow member to
+    // SW_SHOWMINIMIZED. We'll need to make sure is bubbled all the way through,
+    // so we can open a new window with the same state.
+    STARTUPINFOW si;
+    GetStartupInfoW(&si);
+    const auto showWindow = si.wShowWindow;
+
+    Remoting::CommandlineArgs eventArgs{ { args }, { cwd }, showWindow };
 
     const auto isolatedMode{ _app.Logic().IsolatedMode() };
 


Test patch: