Keep NVDA responsive when a UIA or MSAA application stops responding (#20168)
Fixes #16749 (also the long-standing #1408).
Summary of the issue:
When an application stops responding, synchronous cross-process UIA/MSAA calls into it block NVDA's core. The UIA event handlers can flood the log with COMError tracebacks and NVDA goes partially unresponsive until the app is killed.
Description of user facing changes:
When an application stops responding, NVDA no longer freezes or floods its log; it stays responsive and stops processing events from the unresponsive application until it recovers.
Description of developer facing changes:
New winBindings.user32.IsHungAppWindow ctypes binding + winUser.isHungAppWindow wrapper.
New UIAHandler.utils._getCachedWindowHandleFromEvent / _shouldSkipEventForHungWindow helpers.
Description of development approach:
Beside the existing unconditional ghosted-window drop:
The UIA event handlers skip events whose sender's window belongs to a not-responding application, using only the cached native window handle (NVDA registers event handler groups with baseCacheRequest, so this read cannot itself block).
winEventToNVDAEvent drops MSAA winEvents for a not-responding application (logged via log.debugWarning).
isUsableWindow / Window.getPossibleAPIClasses treat a not-responding window as unusable so NVDA falls back instead of making blocking higher-API calls.
The hot textChange path uses the cached class name instead of a live cross-process fetch.
The hung-skip is unconditional, mirroring the adjacent ghosted-window handling — there is no legitimate reason to keep polling a window the system reports as not responding.