Skip to main content

rs_teststand_sys/window/
mod.rs

1//! Win32 windows and window messages.
2//!
3//! Not COM, and deliberately not called `ui`: TestStand™ has its own "UI
4//! messages", a queue on the engine that a host drains with
5//! `Engine.GetUIMessage`. That queue and this one are unrelated, and a host owes
6//! both duties separately. Naming this module after the other concept would put
7//! two different mechanisms under one word.
8//!
9//! What lives here is the window layer a COM apartment rests on. A
10//! single-threaded apartment receives cross-apartment calls as window messages,
11//! so a thread holding COM objects has to dispatch them
12//! ([`pump_thread_messages`]) or it cannot hear the calls it is waiting for.
13//! And when a sequence raises a modal dialog, the evidence is a visible window
14//! owned by this process ([`find_blocking_dialog`]), which a host can then put
15//! in front of the operator ([`surface_blocking_dialog`]) instead of dying on
16//! it.
17
18pub(crate) mod dialog;
19pub(crate) mod dismiss;
20pub(crate) mod pump;
21pub(crate) mod raise;
22
23pub use dialog::{DialogInfo, find_blocking_dialog};
24pub use dismiss::{Dismissed, dismiss_blocking_dialog};
25pub use pump::pump_thread_messages;
26pub use raise::Raised;
27
28/// Brings the first blocking dialog to the front and reports what it says.
29///
30/// The alternative to killing the process. A message-popup step is a question,
31/// not a fault, so the useful response is to make sure the question is visible
32/// above whatever else is on the desktop and let it be answered, by an
33/// operator, or by a front end driving the same station.
34///
35/// `None` means no dialog is up. See [`Raised`] for what "in front" is
36/// guaranteed to mean, since Z-order and focus are not equally strong.
37#[must_use]
38pub fn surface_blocking_dialog() -> Option<(DialogInfo, Raised)> {
39    let handle = dialog::first_visible_dialog()?;
40    // Raise first: reading the dialog's controls walks its child windows, and
41    // doing that before the reorder would leave it hidden for that much longer.
42    let raised = raise::bring_to_front(handle);
43    Some((dialog::describe(handle), raised))
44}