TestAssemblySetup set the unhandled-exception mode and a ThreadException
handler from a module initializer. WinForms stores both per thread
(ThreadContext/NativeWindow thread statics), so they applied only to the
runner thread that loaded the assembly, never to the STA threads the
tests run on. There, an exception escaping a window message or a
BeginInvoke/SynchronizationContext callback still opened a modal
ThreadExceptionDialog in an interactive session, or was silently ignored
otherwise; the handler would also have logged and swallowed it.
Replace the fifteen copied RunSta helpers with StaTestThread.Run, which
selects UnhandledExceptionMode.ThrowException on each STA thread before
it creates a window, so the exception propagates to the test body and
fails the test. Each class keeps its own timeout and message; all
threads are now background threads. Remove TestAssemblySetup.
StaTestThreadTests covers a throwing BeginInvoke callback through
StaTestThread (fails with the original exception) and, as a control,
the default mode on a plain STA thread (the exception goes to the
thread's handler and never reaches the test body). Cross-compiled on
Linux; Windows execution is the windows-desktop CI job.
The docked side panel could only be closed with Escape, which was
unreliable: MainForm consumes Escape before ActionLeadIn's KeyDown
handler, so with a part selected ActionManager called the action's
empty CancelAction and nothing happened; with nothing selected the
panel closed but was stored as the previous action, so the next
Escape reopened it.
- EditNestForm side panel gets a header with the panel title and an
always-visible close button that ends the action.
- ActionLeadIn.CancelAction now steps back (unlock contour, then
deselect part), replacing the dead KeyDown handler.
- Actions can opt out of Escape-resume (ResumeOnEscape); the lead-in
action does, so a closed panel stays closed.