From 6e63704edac355cc8cae62092c0433c608221266 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Thu, 18 Dec 2025 19:04:18 -0600 Subject: [PATCH] Try: Pass foreground rights across the handoff and Monarchy stacks --- src/cascadia/WindowsTerminal/IslandWindow.cpp | 32 ++++++------------- src/cascadia/wt/shim.cpp | 24 +++++++++++++- src/host/srvinit.cpp | 5 +++ 3 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index e627bd4495..3a592d3a39 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -1457,32 +1457,18 @@ void IslandWindow::_globalActivateWindow(const uint32_t dropdownDuration, } else { - // Try first to send a message to the current foreground window. If it's not responding, it may - // be waiting on us to finish launching. Passing SMTO_NOTIMEOUTIFNOTHUNG means that we get the same - // behavior as before--that is, waiting for the message loop--but we've done an early return if - // it turns out that it was hung. - // SendMessageTimeoutW returns nonzero if it succeeds. - if (0 != SendMessageTimeoutW(oldForegroundWindow, WM_NULL, 0, 0, SMTO_NOTIMEOUTIFNOTHUNG | SMTO_BLOCK | SMTO_ABORTIFHUNG, 1000, nullptr)) - { - const auto windowThreadProcessId = GetWindowThreadProcessId(oldForegroundWindow, nullptr); - const auto currentThreadId = GetCurrentThreadId(); + LOG_IF_WIN32_BOOL_FALSE(BringWindowToTop(_window.get())); + ShowWindow(_window.get(), SW_SHOW); - LOG_IF_WIN32_BOOL_FALSE(AttachThreadInput(windowThreadProcessId, currentThreadId, true)); - // Just in case, add the thread detach as a scope_exit, to make _sure_ we do it. - auto detachThread = wil::scope_exit([windowThreadProcessId, currentThreadId]() { - LOG_IF_WIN32_BOOL_FALSE(AttachThreadInput(windowThreadProcessId, currentThreadId, false)); - }); - LOG_IF_WIN32_BOOL_FALSE(BringWindowToTop(_window.get())); - ShowWindow(_window.get(), SW_SHOW); + // Activate the window too. This will force us to the virtual desktop this + // window is on, if it's on another virtual desktop. + LOG_LAST_ERROR_IF_NULL(SetActiveWindow(_window.get())); - // Activate the window too. This will force us to the virtual desktop this - // window is on, if it's on another virtual desktop. - LOG_LAST_ERROR_IF_NULL(SetActiveWindow(_window.get())); - - // Throw us on the active monitor. - _moveToMonitor(oldForegroundWindow, toMonitor); - } + // Throw us on the active monitor. + _moveToMonitor(oldForegroundWindow, toMonitor); } + + SetForegroundWindow(_window.get()); } // Method Description: diff --git a/src/cascadia/wt/shim.cpp b/src/cascadia/wt/shim.cpp index 0b00fcaf96..23016c57fd 100644 --- a/src/cascadia/wt/shim.cpp +++ b/src/cascadia/wt/shim.cpp @@ -6,10 +6,19 @@ #include #include #include +#include + +TRACELOGGING_DECLARE_PROVIDER(g_hProvider1); +TRACELOGGING_DEFINE_PROVIDER( + g_hProvider1, + "Microsoft.Windows.Terminal.Shim", + // tl:{d295502a-ab39-5565-c342-6e6d7659a422} + (0xd295502a,0xab39,0x5565,0xc3,0x42,0x6e,0x6d,0x76,0x59,0xa4,0x22)); #pragma warning(suppress : 26461) // we can't change the signature of wWinMain int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR pCmdLine, int) { + TraceLoggingRegister(g_hProvider1); std::filesystem::path module{ wil::GetModuleFileNameW(nullptr) }; // Cache our name (wt, wtd) @@ -32,5 +41,18 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR pCmdLine, int) // Go! wil::unique_process_information pi; - return !CreateProcessW(module.c_str(), cmdline.data(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi); + if (!CreateProcessW(module.c_str(), cmdline.data(), nullptr, nullptr, FALSE, CREATE_SUSPENDED, nullptr, nullptr, &si, &pi)) + { + return 1; + } + + DWORD lastError = 0; + if (!AllowSetForegroundWindow(pi.dwProcessId)) + { + lastError = GetLastError(); + } + TraceLoggingWrite(g_hProvider1, "ShimAllowSetForeground", TraceLoggingWinError(lastError, "lastError")); + + ResumeThread(pi.hThread); + return 0; } diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index cdb49db1bd..883489fea4 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -544,6 +544,11 @@ try myStartupInfo.wShowWindow = settings.GetShowWindow(); + { + HRESULT hr = CoAllowSetForegroundWindow(handoff.Get(), nullptr); + TraceLoggingWrite(g_hConhostV2EventTraceProvider, "PtyHandoffAllowSetForegroundWindow", TraceLoggingHResult(hr)); + } + wil::unique_handle inPipeOurSide; wil::unique_handle outPipeOurSide; RETURN_IF_FAILED(handoff->EstablishPtyHandoff(inPipeOurSide.addressof(),