2022-07-28 15:38:12 -07:00
|
|
|
From bdef98a34241f02651374715cc03f90faef96bc0 Mon Sep 17 00:00:00 2001
|
2019-08-04 17:27:34 -07:00
|
|
|
From: =?UTF-8?q?Gabriel=20Iv=C4=83ncescu?= <gabrielopcode@gmail.com>
|
|
|
|
Date: Mon, 22 Jul 2019 15:29:25 +0300
|
2022-02-17 15:54:02 -08:00
|
|
|
Subject: [PATCH] user32/focus: Prevent a recursive loop with the activation
|
|
|
|
messages
|
2019-08-04 17:27:34 -07:00
|
|
|
MIME-Version: 1.0
|
|
|
|
Content-Type: text/plain; charset=UTF-8
|
|
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
|
|
|
|
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. Some applications
|
|
|
|
actually depend on this behavior, so it is needed.
|
|
|
|
|
|
|
|
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46274
|
|
|
|
Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
|
|
|
|
---
|
2022-03-11 16:27:46 -08:00
|
|
|
dlls/user32/tests/msg.c | 2 +-
|
2022-04-26 14:52:01 -07:00
|
|
|
dlls/win32u/input.c | 41 ++++++++++++++++++++++++------------
|
2022-03-11 16:27:46 -08:00
|
|
|
dlls/win32u/ntuser_private.h | 1 +
|
2022-04-26 14:52:01 -07:00
|
|
|
3 files changed, 30 insertions(+), 14 deletions(-)
|
2019-08-04 17:27:34 -07:00
|
|
|
|
2022-03-11 16:27:46 -08:00
|
|
|
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
|
2022-07-28 15:38:12 -07:00
|
|
|
index 63388e2250e..6ddac9cc7d3 100644
|
2022-03-11 16:27:46 -08:00
|
|
|
--- a/dlls/user32/tests/msg.c
|
|
|
|
+++ b/dlls/user32/tests/msg.c
|
2022-04-05 16:00:31 -07:00
|
|
|
@@ -5571,7 +5571,7 @@ static void test_messages(void)
|
2022-03-11 16:27:46 -08:00
|
|
|
|
|
|
|
ShowWindow(hwnd, SW_MINIMIZE);
|
|
|
|
flush_events();
|
|
|
|
- ok_sequence(WmShowMinOverlappedSeq, "ShowWindow(SW_SHOWMINIMIZED):overlapped", TRUE);
|
|
|
|
+ ok_sequence(WmShowMinOverlappedSeq, "ShowWindow(SW_SHOWMINIMIZED):overlapped", FALSE);
|
|
|
|
flush_sequence();
|
|
|
|
|
|
|
|
if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MINIMIZE)
|
|
|
|
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c
|
2022-07-28 15:38:12 -07:00
|
|
|
index a478a549fb2..ac0b51dfd73 100644
|
2022-03-11 16:27:46 -08:00
|
|
|
--- a/dlls/win32u/input.c
|
|
|
|
+++ b/dlls/win32u/input.c
|
2022-07-28 15:38:12 -07:00
|
|
|
@@ -1569,7 +1569,7 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
|
2019-08-04 17:27:34 -07:00
|
|
|
{
|
2022-03-11 16:27:46 -08:00
|
|
|
HWND previous = get_active_window();
|
2019-08-04 17:27:34 -07:00
|
|
|
BOOL ret;
|
|
|
|
- DWORD old_thread, new_thread;
|
|
|
|
+ DWORD winflags, old_thread, new_thread;
|
|
|
|
CBTACTIVATESTRUCT cbt;
|
|
|
|
|
|
|
|
if (previous == hwnd)
|
2022-07-28 15:38:12 -07:00
|
|
|
@@ -1578,16 +1578,24 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
|
2019-08-04 17:27:34 -07:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
- /* call CBT hook chain */
|
|
|
|
- cbt.fMouse = mouse;
|
|
|
|
- cbt.hWndActive = previous;
|
2022-03-11 16:27:46 -08:00
|
|
|
- if (call_hooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hwnd, (LPARAM)&cbt, TRUE )) return FALSE;
|
2019-08-04 17:27:34 -07:00
|
|
|
-
|
2022-03-11 16:27:46 -08:00
|
|
|
- if (is_window( previous ))
|
2019-08-04 17:27:34 -07:00
|
|
|
+ /* Prevent a recursive activation loop with the activation messages */
|
|
|
|
+ winflags = win_set_flags(hwnd, WIN_IS_IN_ACTIVATION, 0);
|
|
|
|
+ if (!(winflags & WIN_IS_IN_ACTIVATION))
|
|
|
|
{
|
2022-03-11 16:27:46 -08:00
|
|
|
- send_message( previous, WM_NCACTIVATE, FALSE, (LPARAM)hwnd );
|
|
|
|
- send_message( previous, WM_ACTIVATE,
|
|
|
|
- MAKEWPARAM( WA_INACTIVE, is_iconic(previous) ), (LPARAM)hwnd );
|
2019-08-04 17:27:34 -07:00
|
|
|
+ ret = FALSE;
|
|
|
|
+
|
|
|
|
+ /* call CBT hook chain */
|
|
|
|
+ cbt.fMouse = mouse;
|
|
|
|
+ cbt.hWndActive = previous;
|
2022-03-11 16:27:46 -08:00
|
|
|
+ if (call_hooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hwnd, (LPARAM)&cbt, TRUE ))
|
2019-08-04 17:27:34 -07:00
|
|
|
+ goto clear_flags;
|
|
|
|
+
|
2022-03-11 16:27:46 -08:00
|
|
|
+ if (is_window(previous))
|
2019-08-04 17:27:34 -07:00
|
|
|
+ {
|
2022-03-11 16:27:46 -08:00
|
|
|
+ send_message( previous, WM_NCACTIVATE, FALSE, (LPARAM)hwnd );
|
|
|
|
+ send_message( previous, WM_ACTIVATE,
|
|
|
|
+ MAKEWPARAM( WA_INACTIVE, is_iconic(previous) ), (LPARAM)hwnd );
|
2019-08-04 17:27:34 -07:00
|
|
|
+ }
|
|
|
|
}
|
|
|
|
|
|
|
|
SERVER_START_REQ( set_active_window )
|
2022-07-28 15:38:12 -07:00
|
|
|
@@ -1607,7 +1615,11 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
|
2022-04-05 16:00:31 -07:00
|
|
|
if (send_message( hwnd, WM_QUERYNEWPALETTE, 0, 0 ))
|
|
|
|
send_message_timeout( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hwnd, 0,
|
|
|
|
SMTO_ABORTIFHUNG, 2000, NULL, FALSE );
|
2022-03-11 16:27:46 -08:00
|
|
|
- if (!is_window(hwnd)) return FALSE;
|
|
|
|
+ if (!is_window(hwnd))
|
2019-08-04 17:27:34 -07:00
|
|
|
+ {
|
|
|
|
+ ret = FALSE;
|
|
|
|
+ goto clear_flags;
|
|
|
|
+ }
|
|
|
|
}
|
|
|
|
|
2022-03-11 16:27:46 -08:00
|
|
|
old_thread = previous ? get_window_thread( previous, NULL ) : 0;
|
2022-07-28 15:38:12 -07:00
|
|
|
@@ -1639,7 +1651,7 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
|
2019-08-04 17:27:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-11 16:27:46 -08:00
|
|
|
- if (is_window(hwnd))
|
|
|
|
+ if (!(winflags & WIN_IS_IN_ACTIVATION) && is_window(hwnd))
|
2019-08-04 17:27:34 -07:00
|
|
|
{
|
2022-03-11 16:27:46 -08:00
|
|
|
send_message( hwnd, WM_NCACTIVATE, hwnd == NtUserGetForegroundWindow(), (LPARAM)previous );
|
|
|
|
send_message( hwnd, WM_ACTIVATE,
|
2022-07-28 15:38:12 -07:00
|
|
|
@@ -1666,12 +1678,15 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
|
2022-04-26 14:52:01 -07:00
|
|
|
/* Do not change focus if the window is no more active */
|
|
|
|
if (hwnd == info.hwndActive)
|
|
|
|
{
|
|
|
|
+ /* this line exists to keep this patch from applying in the wrong place */
|
|
|
|
if (!info.hwndFocus || !hwnd || NtUserGetAncestor( info.hwndFocus, GA_ROOT ) != hwnd)
|
|
|
|
set_focus_window( hwnd );
|
2019-08-04 17:27:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- return TRUE;
|
|
|
|
+clear_flags:
|
|
|
|
+ win_set_flags(hwnd, 0, WIN_IS_IN_ACTIVATION);
|
|
|
|
+ return ret;
|
|
|
|
}
|
|
|
|
|
2022-03-11 16:27:46 -08:00
|
|
|
/**********************************************************************
|
|
|
|
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
|
2022-07-28 15:38:12 -07:00
|
|
|
index 3ecd7424f77..cc27526235d 100644
|
2022-03-11 16:27:46 -08:00
|
|
|
--- a/dlls/win32u/ntuser_private.h
|
|
|
|
+++ b/dlls/win32u/ntuser_private.h
|
2022-07-28 15:38:12 -07:00
|
|
|
@@ -105,6 +105,7 @@ typedef struct tagWND
|
2019-08-04 17:27:34 -07:00
|
|
|
#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_IN_ACTIVATION 0x0100 /* the window is in an activation process */
|
|
|
|
|
2022-07-28 15:38:12 -07:00
|
|
|
#define WND_OTHER_PROCESS ((WND *)1) /* returned by get_win_ptr on unknown window handles */
|
|
|
|
#define WND_DESKTOP ((WND *)2) /* returned by get_win_ptr on the desktop window */
|
2019-08-04 17:27:34 -07:00
|
|
|
--
|
2022-07-28 15:38:12 -07:00
|
|
|
2.35.1
|
2019-08-04 17:27:34 -07:00
|
|
|
|