Pegasus Mail posts a WM_USER + 8991 message to its own window when it loses focus, then calls SetFocus on its window when processing this message. Several other applications have been seen calling SetWindowPos during WM_ACTIVATE message, which might also attempt to reactivate the window.
That processing happens shortly after we have changed the foreground window to the desktop window, when focus is lost, then SetFocus tries to change the foreground window again.
This SetFocus behavior is tested, and should work like this, but would only activate the window if the process is allowed to do so. Windows has various rules around this, and it seems to boil down to something like:
* Allow taking focus if the process never was foreground, ie: when process is starting and gets initial focus on its windows.
* Allow taking focus if the process was foreground but lost it recently because of a window being destroyed.
* Forbid taking focus back if the process had foreground and called SetForegroundWindow explicitly to give it to another process.
This doesn't implement all this rules, but rather keep rely on the host window management with some additional heuristics to avoid activating windows which lost foreground recently. This is mostly about keeping track of user input time, updating it on user input and on focus change.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58167
---
I think this should be enough to prevent spurious window reactivation, either from calls to SetWindowPos during WM_ACTIVATE messages like in https://gitlab.winehq.org/wine/wine/-/merge_requests/9398 or from calls to SetFocus from posted messages right after window deactivation as described above.
Fwiw we could have tests for that, and show that this MR is fixing them but fvwm doesn't implement window minimization properly, and doesn't change focus when window is minimized, so the tests would be meaningless.
-- v5: server: Forbid background process window reactivation. server: Set NULL foreground input when switching to desktop window. win32u: Introduce a NtUserSetForegroundWindowInternal call. user32/tests: Use a dedicated window instead of the desktop window. ddraw/tests: Use a dedicated window instead of the desktop window.