diff --git a/dep/nuget/packages.config b/dep/nuget/packages.config
index a641da7c51..f28aa77888 100644
--- a/dep/nuget/packages.config
+++ b/dep/nuget/packages.config
@@ -5,7 +5,7 @@
-
+
diff --git a/src/cascadia/LocalTests_TerminalApp/TerminalApp.LocalTests.vcxproj b/src/cascadia/LocalTests_TerminalApp/TerminalApp.LocalTests.vcxproj
index 91134e3f08..8ab41a6eca 100644
--- a/src/cascadia/LocalTests_TerminalApp/TerminalApp.LocalTests.vcxproj
+++ b/src/cascadia/LocalTests_TerminalApp/TerminalApp.LocalTests.vcxproj
@@ -24,6 +24,7 @@
true
+ true
diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp
index 3b2691df93..adc3cf4150 100644
--- a/src/cascadia/TerminalApp/TabManagement.cpp
+++ b/src/cascadia/TerminalApp/TabManagement.cpp
@@ -1013,6 +1013,8 @@ namespace winrt::TerminalApp::implementation
auto profile = tab_impl->GetFocusedProfile();
_UpdateBackground(profile);
}
+
+ _adjustProcessPriorityThrottled->Run();
}
CATCH_LOG();
}
diff --git a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj
index 0896bc114a..3230bf625f 100644
--- a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj
+++ b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj
@@ -26,6 +26,7 @@
true
true
true
+ true
diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp
index 56d710d192..9d24ef8466 100644
--- a/src/cascadia/TerminalApp/TerminalPage.cpp
+++ b/src/cascadia/TerminalApp/TerminalPage.cpp
@@ -6,6 +6,7 @@
#include "TerminalPage.h"
#include
+#include
#include
#include
@@ -102,6 +103,13 @@ namespace winrt::TerminalApp::implementation
// before restoring previous tabs in that scenario.
}
}
+
+ _adjustProcessPriorityThrottled = std::make_shared>(
+ DispatcherQueue::GetForCurrentThread(),
+ std::chrono::milliseconds{ 100 },
+ [=]() {
+ _adjustProcessPriority();
+ });
_hostingHwnd = hwnd;
return S_OK;
}
@@ -1946,7 +1954,7 @@ namespace winrt::TerminalApp::implementation
return false;
}
- TermControl TerminalPage::_GetActiveControl()
+ TermControl TerminalPage::_GetActiveControl() const
{
if (const auto terminalTab{ _GetFocusedTabImpl() })
{
@@ -2410,6 +2418,8 @@ namespace winrt::TerminalApp::implementation
auto profile = tab->GetFocusedProfile();
_UpdateBackground(profile);
}
+
+ _adjustProcessPriorityThrottled->Run();
}
uint32_t TerminalPage::NumberOfTabs() const
@@ -4611,9 +4621,12 @@ namespace winrt::TerminalApp::implementation
if (const auto coreState{ sender.try_as() })
{
const auto newConnectionState = coreState.ConnectionState();
+ co_await wil::resume_foreground(Dispatcher());
+
+ _adjustProcessPriorityThrottled->Run();
+
if (newConnectionState == ConnectionState::Failed && !_IsMessageDismissed(InfoBarMessage::CloseOnExitInfo))
{
- co_await wil::resume_foreground(Dispatcher());
if (const auto infoBar = FindName(L"CloseOnExitInfoBar").try_as())
{
infoBar.IsOpen(true);
@@ -4878,6 +4891,94 @@ namespace winrt::TerminalApp::implementation
}
}
+ void TerminalPage::_adjustProcessPriority() const
+ {
+ // Windowing is single-threaded, so this will not cause a race condition.
+ static bool supported{ true };
+
+ if (!supported || !_hostingHwnd.has_value())
+ {
+ return;
+ }
+
+ std::array processes;
+ auto it = processes.begin();
+ const auto end = processes.end();
+
+ auto&& appendFromControl = [&](auto&& control) {
+ if (it == end)
+ {
+ return;
+ }
+ if (control)
+ {
+ if (const auto conn{ control.Connection() })
+ {
+ if (const auto pty{ conn.try_as() })
+ {
+ if (const uint64_t process{ pty.RootProcessHandle() }; process != 0)
+ {
+ *it++ = reinterpret_cast(process);
+ }
+ }
+ }
+ }
+ };
+
+ auto&& appendFromTab = [&](auto&& tabImpl) {
+ if (const auto pane{ tabImpl->GetRootPane() })
+ {
+ pane->WalkTree([&](auto&& child) {
+ if (const auto& control{ child->GetTerminalControl() })
+ {
+ appendFromControl(control);
+ }
+ });
+ }
+ };
+
+ if (!_activated)
+ {
+ // When a window is out of focus, we want to attach all of the processes
+ // under it to the window so they all go into the background at the same time.
+ for (auto&& tab : _tabs)
+ {
+ if (auto tabImpl{ _GetTerminalTabImpl(tab) })
+ {
+ appendFromTab(tabImpl);
+ }
+ }
+ }
+ else
+ {
+ // When a window is in focus, propagate our foreground boost (if we have one)
+ // to current all panes in the current tab.
+ if (auto tabImpl{ _GetFocusedTabImpl() })
+ {
+ appendFromTab(tabImpl);
+ }
+ }
+
+ const auto count{ gsl::narrow_cast(it - processes.begin()) };
+ const auto hr = TerminalTrySetWindowAssociatedProcesses(_hostingHwnd.value(), count, count ? processes.data() : nullptr);
+ if (S_FALSE == hr)
+ {
+ // Don't bother trying again or logging. The wrapper tells us it's unsupported.
+ supported = false;
+ return;
+ }
+
+ TraceLoggingWrite(
+ g_hTerminalAppProvider,
+ "CalledNewQoSAPI",
+ TraceLoggingValue(reinterpret_cast(_hostingHwnd.value()), "hwnd"),
+ TraceLoggingValue(count),
+ TraceLoggingHResult(hr));
+#ifdef _DEBUG
+ OutputDebugStringW(fmt::format(FMT_COMPILE(L"Submitted {} processes to TerminalTrySetWindowAssociatedProcesses; return=0x{:08x}\n"), count, hr).c_str());
+#endif
+ }
+
void TerminalPage::WindowActivated(const bool activated)
{
// Stash if we're activated. Use that when we reload
@@ -4885,6 +4986,8 @@ namespace winrt::TerminalApp::implementation
_activated = activated;
_updateThemeColors();
+ _adjustProcessPriorityThrottled->Run();
+
if (const auto& tab{ _GetFocusedTabImpl() })
{
if (tab->TabStatus().IsInputBroadcastActive())
diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h
index 9c54d66248..e0b8ded229 100644
--- a/src/cascadia/TerminalApp/TerminalPage.h
+++ b/src/cascadia/TerminalApp/TerminalPage.h
@@ -3,6 +3,8 @@
#pragma once
+#include
+
#include "TerminalPage.g.h"
#include "TerminalTab.h"
#include "AppKeyBindings.h"
@@ -359,8 +361,11 @@ namespace winrt::TerminalApp::implementation
bool _MovePane(const Microsoft::Terminal::Settings::Model::MovePaneArgs args);
bool _MoveTab(winrt::com_ptr tab, const Microsoft::Terminal::Settings::Model::MoveTabArgs args);
+ std::shared_ptr> _adjustProcessPriorityThrottled;
+ void _adjustProcessPriority() const;
+
template
- bool _ApplyToActiveControls(F f)
+ bool _ApplyToActiveControls(F f) const
{
if (const auto tab{ _GetFocusedTabImpl() })
{
@@ -379,7 +384,7 @@ namespace winrt::TerminalApp::implementation
return false;
}
- winrt::Microsoft::Terminal::Control::TermControl _GetActiveControl();
+ winrt::Microsoft::Terminal::Control::TermControl _GetActiveControl() const;
std::optional _GetFocusedTabIndex() const noexcept;
std::optional _GetTabIndex(const TerminalApp::TabBase& tab) const noexcept;
TerminalApp::TabBase _GetFocusedTab() const noexcept;
diff --git a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj
index 6a20f0ac9b..4bc996863a 100644
--- a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj
+++ b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj
@@ -16,6 +16,7 @@
true
true
+ true
diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp
index f511ff8afa..ba14ee618c 100644
--- a/src/cascadia/TerminalConnection/ConptyConnection.cpp
+++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp
@@ -340,7 +340,13 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
auto ownedSignal = duplicateHandle(signal);
auto ownedReference = duplicateHandle(reference);
auto ownedServer = duplicateHandle(server);
- auto ownedClient = duplicateHandle(client);
+ wil::unique_hfile ownedClient;
+ LOG_IF_WIN32_BOOL_FALSE(DuplicateHandle(GetCurrentProcess(), client, GetCurrentProcess(), ownedClient.addressof(), PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_SET_INFORMATION | SYNCHRONIZE, FALSE, 0));
+ if (!ownedClient)
+ {
+ // If we couldn't reopen the handle with SET_INFORMATION, which may be required to do things like QoS management, fall back.
+ ownedClient = duplicateHandle(client);
+ }
THROW_IF_FAILED(ConptyPackPseudoConsole(ownedServer.get(), ownedReference.get(), ownedSignal.get(), &_hPC));
ownedServer.release();
@@ -533,6 +539,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
DWORD exitCode{ 0 };
GetExitCodeProcess(_piClient.hProcess, &exitCode);
+ _piClient.reset();
+
// Signal the closing or failure of the process.
// exitCode might be STILL_ACTIVE if a client has called FreeConsole() and
// thus caused the tab to close, even though the CLI app is still running.
@@ -649,6 +657,12 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
}
}
+ uint64_t ConptyConnection::RootProcessHandle() noexcept
+ {
+#pragma warning(disable : 26490) // Don't use reinterpret_cast (type.1).
+ return reinterpret_cast(_piClient.hProcess);
+ }
+
void ConptyConnection::Close() noexcept
try
{
diff --git a/src/cascadia/TerminalConnection/ConptyConnection.h b/src/cascadia/TerminalConnection/ConptyConnection.h
index cdcd99981f..f54c92e547 100644
--- a/src/cascadia/TerminalConnection/ConptyConnection.h
+++ b/src/cascadia/TerminalConnection/ConptyConnection.h
@@ -30,6 +30,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
void ShowHide(const bool show);
void ReparentWindow(const uint64_t newParent);
+ uint64_t RootProcessHandle() noexcept;
winrt::hstring Commandline() const;
winrt::hstring StartingTitle() const;
diff --git a/src/cascadia/TerminalConnection/ConptyConnection.idl b/src/cascadia/TerminalConnection/ConptyConnection.idl
index 5264238c79..f0f074b01d 100644
--- a/src/cascadia/TerminalConnection/ConptyConnection.idl
+++ b/src/cascadia/TerminalConnection/ConptyConnection.idl
@@ -21,6 +21,8 @@ namespace Microsoft.Terminal.TerminalConnection
void ReparentWindow(UInt64 newParent);
+ UInt64 RootProcessHandle();
+
static event NewConnectionHandler NewConnection;
static void StartInboundListener();
diff --git a/src/common.nugetversions.targets b/src/common.nugetversions.targets
index 837c575fd8..fc2ee146e7 100644
--- a/src/common.nugetversions.targets
+++ b/src/common.nugetversions.targets
@@ -47,7 +47,7 @@
-
+
@@ -85,7 +85,7 @@
-
+
diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp
index cd68c921e9..49551a25bd 100644
--- a/src/host/srvinit.cpp
+++ b/src/host/srvinit.cpp
@@ -463,7 +463,7 @@ try
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
- wil::unique_handle clientProcess{ OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | SYNCHRONIZE, TRUE, static_cast(connectMessage->Descriptor.Process)) };
+ wil::unique_handle clientProcess{ OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_SET_INFORMATION | SYNCHRONIZE, TRUE, static_cast(connectMessage->Descriptor.Process)) };
RETURN_LAST_ERROR_IF_NULL(clientProcess.get());
TraceLoggingWrite(g_hConhostV2EventTraceProvider,