This discards the pending WM_WINE_SETACTIVEWINDOW messages when current thread becomes -or is already- foreground, and before setting the active window.
Although it's still not enough, it should help solving several focus inversions when WM messages arrive late, or when multiple windows are created without the application checking its messages.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/focus.c | 3 +++ dlls/user32/message.c | 12 ++++++++++++ dlls/user32/tests/win.c | 10 +++++----- dlls/user32/user_private.h | 1 + 4 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/dlls/user32/focus.c b/dlls/user32/focus.c index 09194bb08a78..cab557eb3a35 100644 --- a/dlls/user32/focus.c +++ b/dlls/user32/focus.c @@ -87,6 +87,9 @@ BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus, BOOL inte return TRUE; }
+ if (hwnd && !internal && GetWindowThreadProcessId( GetForegroundWindow(), NULL ) == GetCurrentThreadId()) + discard_internal_messages( WM_WINE_SETACTIVEWINDOW ); + /* call CBT hook chain */ cbt.fMouse = mouse; cbt.hWndActive = previous; diff --git a/dlls/user32/message.c b/dlls/user32/message.c index 118522ea4722..c731f8f8ba23 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -3008,6 +3008,18 @@ static inline void process_sent_messages(void) }
+/*********************************************************************** + * discard_internal_messages + * + * Remove all matching internal messages. + */ +void discard_internal_messages(UINT msg) +{ + MSG message; + peek_message( &message, 0, msg, msg, PM_REMOVE | PM_QS_SENDMESSAGE, 0, TRUE ); +} + + /*********************************************************************** * get_server_queue_handle * diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index 90c49a8f5c2b..3aef70d95a92 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -3290,15 +3290,15 @@ static struct set_foreground_test_desc set_foreground_tests[] = { {1, FALSE, FALSE, TRUE, FALSE, 0, FALSE, 0, FALSE, 6, FALSE, 0}, {1, TRUE, FALSE, TRUE, FALSE, 0, TRUE, 1, FALSE, 6, FALSE, 0},
- {2, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 6, TRUE, 0, TRUE, 1}, - {2, TRUE, FALSE, FALSE, FALSE, 0, FALSE, 6, TRUE, 0, TRUE, 1}, - {2, FALSE, TRUE, FALSE, FALSE, 6, FALSE, 0, TRUE, 0, TRUE, 1}, + {2, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 6, FALSE, 0, FALSE, 1}, + {2, TRUE, FALSE, FALSE, FALSE, 0, FALSE, 6, FALSE, 0, FALSE, 1}, + {2, FALSE, TRUE, FALSE, FALSE, 6, FALSE, 0, FALSE, 0, FALSE, 1}, {2, TRUE, TRUE, FALSE, FALSE, 6, TRUE, 1, FALSE, 6, FALSE, 0}, - {2, FALSE, FALSE, TRUE, TRUE, 8, FALSE, 0, TRUE, 0, TRUE, 1}, + {2, FALSE, FALSE, TRUE, TRUE, 8, FALSE, 0, FALSE, 0, FALSE, 1}, {2, TRUE, FALSE, TRUE, TRUE, 8, TRUE, 1, FALSE, 6, FALSE, 0},
{0, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 6, FALSE, 0, FALSE, 1}, - {0, TRUE, FALSE, FALSE, FALSE, 0, FALSE, 6, TRUE, 0, TRUE, 1}, + {0, TRUE, FALSE, FALSE, FALSE, 0, FALSE, 6, FALSE, 0, FALSE, 1}, {0, FALSE, TRUE, FALSE, FALSE, 6, FALSE, 0, FALSE, 0, FALSE, 1}, {0, TRUE, TRUE, FALSE, FALSE, 6, TRUE, 1, FALSE, 6, FALSE, 0}, {0, FALSE, FALSE, TRUE, TRUE, 8, FALSE, 0, FALSE, 0, FALSE, 1}, diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 2f46908fa0a1..6b614dc4c99c 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -233,6 +233,7 @@ extern void CLIPBOARD_ReleaseOwner( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL FOCUS_MouseActivate( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus, BOOL internal ) DECLSPEC_HIDDEN; extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) DECLSPEC_HIDDEN; +extern void discard_internal_messages( UINT msg ); extern void free_dce( struct dce *dce, HWND hwnd ) DECLSPEC_HIDDEN; extern void invalidate_dce( struct tagWND *win, const RECT *rect ) DECLSPEC_HIDDEN; extern HDC get_display_dc(void) DECLSPEC_HIDDEN;