[PATCH 2/2] user32: Prevent a recursive loop with the activation messages.
Rémi Bernon
rbernon at codeweavers.com
Thu Mar 24 16:37:53 CDT 2022
When activating a window and sending activation messages to the window
procedure, Windows avoids a recursive loop by not sending more of these
messages or hooks while it's still activating the window.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46274
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/user32/tests/msg.c | 2 +-
dlls/win32u/input.c | 17 ++++++++++++-----
dlls/win32u/ntuser_private.h | 1 +
3 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index adb167bdad3..5c7464173c0 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -14827,7 +14827,7 @@ static void test_set_active_window_recursive(HWND hwnd, HWND hwnd2)
flush_sequence();
SetActiveWindow(hwnd);
- ok_sequence(RecursiveActivationSeq, "recursive activation", TRUE);
+ ok_sequence(RecursiveActivationSeq, "recursive activation", FALSE);
DestroyWindow(hwnd2);
DestroyWindow(hwnd);
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c
index 5cd2cdd0970..29c7e86036c 100644
--- a/dlls/win32u/input.c
+++ b/dlls/win32u/input.c
@@ -1227,6 +1227,9 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
return TRUE;
}
+ if (prev) *prev = previous;
+ if (win_set_flags( hwnd, WIN_IS_ACTIVATING, 0 ) & WIN_IS_ACTIVATING) return TRUE;
+
/* call CBT hook chain */
cbt.fMouse = mouse;
cbt.hWndActive = previous;
@@ -1246,9 +1249,9 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
previous = wine_server_ptr_handle( reply->previous );
}
SERVER_END_REQ;
- if (!ret) return FALSE;
+ if (!ret) goto done;
if (prev) *prev = previous;
- if (previous == hwnd) return TRUE;
+ if (previous == hwnd) goto done;
if (hwnd)
{
@@ -1256,7 +1259,7 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
if (send_message( hwnd, WM_QUERYNEWPALETTE, 0, 0 ) && user_callbacks)
user_callbacks->pSendMessageTimeoutW( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hwnd, 0,
SMTO_ABORTIFHUNG, 2000, NULL );
- if (!is_window(hwnd)) return FALSE;
+ if (!(ret = is_window( hwnd ))) goto done;
}
old_thread = previous ? get_window_thread( previous, NULL ) : 0;
@@ -1290,7 +1293,9 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
if (is_window(hwnd))
{
- send_message( hwnd, WM_NCACTIVATE, hwnd == NtUserGetForegroundWindow(), (LPARAM)previous );
+ send_message( hwnd, WM_NCACTIVATE,
+ (hwnd == NtUserGetForegroundWindow()) && !(win_get_flags(previous) & WIN_IS_ACTIVATING),
+ (LPARAM)previous );
send_message( hwnd, WM_ACTIVATE,
MAKEWPARAM( mouse ? WA_CLICKACTIVE : WA_ACTIVE, is_iconic(hwnd) ),
(LPARAM)previous );
@@ -1313,7 +1318,9 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
}
}
- return TRUE;
+done:
+ win_set_flags( hwnd, 0, WIN_IS_ACTIVATING );
+ return ret;
}
/**********************************************************************
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index 7c03474286d..5452c722ffa 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -119,6 +119,7 @@ typedef struct tagWND
#define WIN_NEEDS_SHOW_OWNEDPOPUP 0x0020 /* WM_SHOWWINDOW:SC_SHOW must be sent in the next ShowOwnedPopup call */
#define WIN_CHILDREN_MOVED 0x0040 /* children may have moved, ignore stored positions */
#define WIN_HAS_IME_WIN 0x0080 /* the window has been registered with imm32 */
+#define WIN_IS_ACTIVATING 0x0100 /* the window is being activated */
#define WND_OTHER_PROCESS ((WND *)1) /* returned by WIN_GetPtr on unknown window handles */
#define WND_DESKTOP ((WND *)2) /* returned by WIN_GetPtr on the desktop window */
--
2.35.1
More information about the wine-devel
mailing list