[PATCH 0/8] Fix SetForegroundWindow focus inversion.

Rémi Bernon rbernon at codeweavers.com
Fri Aug 14 07:56:30 CDT 2020


I'm resending these, with the tests also run in cross-process mode (in
addition to the same-process/cross-thread calls). The results are the
same in both cases, and it exposes an inversion in Wine which can then
cause various focus inconsistencies.


PATCH 1/8 is not strictly necessary to make the test run well on
testbot, and can possibly be dropped, but it helped me when running the
test in a VM, especially when multiple processes are involved (the new
process windows couldn't get foreground and were just flashing in the
taskbar instead).

The remaining todo_wine after the series are caused by the same kind of
behavior as is fixed by PATCH 8/8, where WM_KILLFOCUS/WM_SETFOCUS
messages aren't sent because the window already has focus. As foreground
was temporarily stolen by another thread they should still apparently
be sent. The logic was a little bit more complicated so I left it aside.


The remaining focus issues with Wine are mostly caused by:

* asynchronous SetForegroundWindow consequences, with user actions
  interleaved, causing events coming late to steal foreground that was
  already lost,

* threads not checking their messages for a while, causing a delay
  between host focus changes, and wineserver focus state updates.

My plan, to fix those, would be to:

* use timestamps to order SetForegroundWindow requests and their
  corresponding host events, and then ignore out-of-order events,

* track the host focus state globally, for instance from explorer,
  so that threads that do not check their messages for a while will
  not make wine focus state inconsistent.

This inversion makes the whole thing useless, as threads can steal
foreground from each other, as they process the internal
WM_WINE_SETACTIVEWINDOW messages in the wrong order, so it has to be
fixed first.

Cheers,

Rémi Bernon (8):
  user32/tests: Attach a debugger to help SetForegroundWindow suceed.
  user32/tests: Add concurrency tests for SetForegroundWindow.
  user32: Do not deactivate if thread is foreground.
  user32: Call set_active_window from internal handler.
  server: Allow filtering internal sent messages.
  user32: Add discard_internal parameter to peek_message.
  user32: Discard internal messages in set_active_window.
  user32: Send WM_NCACTIVATE on SetForegroundWindow call.

 dlls/user32/focus.c        |  17 +-
 dlls/user32/message.c      |  34 +++-
 dlls/user32/tests/win.c    | 388 +++++++++++++++++++++++++++++++------
 dlls/user32/user_private.h |   2 +
 server/queue.c             |   9 +-
 5 files changed, 374 insertions(+), 76 deletions(-)

-- 
2.28.0




More information about the wine-devel mailing list