wish.nativewatch

The raw Windows message stream around a popup that closes itself.

Three fixes for “the note popover opens empty and vanishes” were reasoned from Linux and all three were wrong. A standalone probe on Windows then cleared the last suspect: a dying QToolTip does not take a Qt::Popup with it, in six variations including a genuine OS-level click.

What the application’s own log says is that the popover receives a bare Close while still visible and still active, with no mouse event, no FocusOut and no WindowDeactivate before it. There is no Qt-level cause, which means the cause arrives underneath Qt as a native message – WM_CANCELMODE, a lost WM_CAPTURECHANGED, a WM_ACTIVATE Qt is translating into a popup dismissal. This names it instead of narrowing the suspect list further.

Nothing here runs off Windows, and nothing runs unless the debug log is on and a popover is actually open: nativeEventFilter is called for every message the application receives, so the gate is the first thing it checks.

Module Attributes

WATCHED

Only the messages that can plausibly dismiss a popup, plus the two that say a window is going away.

watching

Set by whoever is being watched.

ENV

the stream is thousands of messages a second and means nothing to anyone not chasing a window that behaves oddly.

Functions

install(app)

Attach the filter to this application.

install_if_asked(app)

Attach the filter when WISH_NATIVE_LOG is set.

watch(on)

Start or stop recording.

wish.nativewatch.ENV = 'WISH_NATIVE_LOG'

the stream is thousands of messages a second and means nothing to anyone not chasing a window that behaves oddly. WISH_NATIVE_LOG=1 wish.exe --debug.

Type:

What switches it on, because it is off in every ordinary run

wish.nativewatch.WATCHED = {6: 'WM_ACTIVATE', 7: 'WM_SETFOCUS', 8: 'WM_KILLFOCUS', 16: 'WM_CLOSE', 28: 'WM_ACTIVATEAPP', 31: 'WM_CANCELMODE', 33: 'WM_MOUSEACTIVATE', 134: 'WM_NCACTIVATE', 533: 'WM_CAPTURECHANGED', 561: 'WM_ENTERSIZEMOVE', 673: 'WM_MOUSEHOVER', 675: 'WM_MOUSELEAVE'}

Only the messages that can plausibly dismiss a popup, plus the two that say a window is going away. Everything else is noise at thousands a second.

wish.nativewatch.install(app)[source]

Attach the filter to this application. True if it is now attached.

Windows only, and only worth doing with the debug log on – there is nowhere else for what it records to go.

Return type:

bool

wish.nativewatch.install_if_asked(app)[source]

Attach the filter when WISH_NATIVE_LOG is set. True if it is watching.

Off by default and reached only through the environment, because what it records is worth having about twice a year and is noise the rest of the time. It found the one bug it was written for – a QPushButton given no parent was briefly a top-level window of its own, stealing activation from the main window and taking the note popover down with it, visible in the raw stream as a WM_NCACTIVATE/WM_ACTIVATE round trip through an hwnd nothing else knew about. Nothing at the Qt level showed that at all.

Return type:

bool

wish.nativewatch.watch(on)[source]

Start or stop recording. Called around the thing under suspicion.

Parameters:

on (bool)

Return type:

None

wish.nativewatch.watching = False

Set by whoever is being watched. False costs one attribute read per message.