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& 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& value); winrt::com_array Commandline(); + WINRT_PROPERTY(uint32_t, ShowWindowCommand, SW_NORMAL); // SW_NORMAL is 1, 0 is SW_HIDE + private: winrt::com_array _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& 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, 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 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(args.Commandline(), args.CurrentDirectory())); + p->ExecuteCommandline(*winrt::make_self(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(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 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 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 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 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 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 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 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 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(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(); { - 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> _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() }; - 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() };