[PATCH 7/8] user32: Discard internal messages in set_active_window.

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


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 at 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 09194bb08a7..cab557eb3a3 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 7d6ccd9f30b..184853c243b 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -2909,6 +2909,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 9f082d16330..389731ff69d 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -3282,15 +3282,15 @@ static struct test_sfw_test_desc test_sfw_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 19dfbbe48c0..3348c58ca67 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -248,6 +248,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;
-- 
2.28.0




More information about the wine-devel mailing list