diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index 3ae9d781e..0b88ca86b 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -2035,6 +2035,7 @@ IME CLDR doy Hinnant +IDT LONGDATE MRT Uninstalls diff --git a/src/cascadia/WindowsTerminal/TerminalProtocolComServer.cpp b/src/cascadia/WindowsTerminal/TerminalProtocolComServer.cpp index 85867618c..6ce098a21 100644 --- a/src/cascadia/WindowsTerminal/TerminalProtocolComServer.cpp +++ b/src/cascadia/WindowsTerminal/TerminalProtocolComServer.cpp @@ -19,8 +19,12 @@ namespace ProtocolParsing = Microsoft::Terminal::Protocol::Parsing; namespace Protocol = winrt::Microsoft::Terminal::Protocol; -// Static state — set once before registration, never mutated. +// Static state +// s_emperor: set once before registration, never mutated. +// s_emperorHwnd, s_liveObjectCount: mutable at runtime (see s_setEmperorHwnd, constructor/destructor). WindowEmperor* TerminalProtocolComServer::s_emperor = nullptr; +std::atomic TerminalProtocolComServer::s_emperorHwnd{ nullptr }; +std::atomic TerminalProtocolComServer::s_liveObjectCount{ 0 }; static DWORD g_comRegistration = 0; static std::shared_mutex g_mtx; @@ -36,6 +40,27 @@ void TerminalProtocolComServer::s_setEmperor(WindowEmperor* emperor) noexcept s_emperor = emperor; } +void TerminalProtocolComServer::s_setEmperorHwnd(HWND hwnd) noexcept +{ + s_emperorHwnd.store(hwnd, std::memory_order_release); +} + +int32_t TerminalProtocolComServer::s_GetLiveObjectCount() noexcept +{ + return s_liveObjectCount.load(std::memory_order_relaxed); +} + +// Post a message to the emperor's UI thread to re-evaluate idle state. +// Called from the COM MTA thread — PostMessage is thread-safe. +void TerminalProtocolComServer::s_notifyEmperorIdleCheck() +{ + const auto hwnd = TerminalProtocolComServer::s_emperorHwnd.load(std::memory_order_acquire); + if (hwnd) + { + PostMessage(hwnd, WindowEmperor::WM_COM_IDLE_CHECK, 0, 0); + } +} + HRESULT TerminalProtocolComServer::s_StartListening() try { @@ -96,9 +121,17 @@ HRESULT TerminalProtocolComServer::s_StopListening() return S_OK; } +TerminalProtocolComServer::TerminalProtocolComServer() +{ + s_liveObjectCount.fetch_add(1, std::memory_order_relaxed); + s_notifyEmperorIdleCheck(); +} + TerminalProtocolComServer::~TerminalProtocolComServer() { _removeInstance(); + s_liveObjectCount.fetch_sub(1, std::memory_order_relaxed); + s_notifyEmperorIdleCheck(); } void TerminalProtocolComServer::_addInstance() diff --git a/src/cascadia/WindowsTerminal/TerminalProtocolComServer.h b/src/cascadia/WindowsTerminal/TerminalProtocolComServer.h index 3ec29cdeb..e336a43ab 100644 --- a/src/cascadia/WindowsTerminal/TerminalProtocolComServer.h +++ b/src/cascadia/WindowsTerminal/TerminalProtocolComServer.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include @@ -51,6 +52,7 @@ struct Factory : winrt::implements, IClassFactory, winrt::no_module_l struct __declspec(uuid(__CLSID_TerminalProtocolServer)) TerminalProtocolComServer : winrt::implements { + TerminalProtocolComServer(); ~TerminalProtocolComServer(); // ── IProtocolServer ── @@ -98,10 +100,16 @@ TerminalProtocolComServer : winrt::implements