Commit 4e93a376 authored by Gabriel Ivăncescu's avatar Gabriel Ivăncescu Committed by Vitaly Lipatov

user32/focus: Prevent a recursive loop with the activation messages

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=46274Signed-off-by: 's avatarGabriel Ivăncescu <gabrielopcode@gmail.com>
parent e268b36c
......@@ -5571,7 +5571,7 @@ static void test_messages(void)
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)
......
......@@ -1569,7 +1569,7 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
{
HWND previous = get_active_window();
BOOL ret;
DWORD old_thread, new_thread;
DWORD winflags, old_thread, new_thread;
CBTACTIVATESTRUCT cbt;
if (previous == hwnd)
......@@ -1578,16 +1578,24 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
return TRUE;
}
/* call CBT hook chain */
cbt.fMouse = mouse;
cbt.hWndActive = previous;
if (call_hooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hwnd, (LPARAM)&cbt, TRUE )) return FALSE;
if (is_window( previous ))
/* 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))
{
send_message( previous, WM_NCACTIVATE, FALSE, (LPARAM)hwnd );
send_message( previous, WM_ACTIVATE,
MAKEWPARAM( WA_INACTIVE, is_iconic(previous) ), (LPARAM)hwnd );
ret = FALSE;
/* call CBT hook chain */
cbt.fMouse = mouse;
cbt.hWndActive = previous;
if (call_hooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hwnd, (LPARAM)&cbt, TRUE ))
goto clear_flags;
if (is_window(previous))
{
send_message( previous, WM_NCACTIVATE, FALSE, (LPARAM)hwnd );
send_message( previous, WM_ACTIVATE,
MAKEWPARAM( WA_INACTIVE, is_iconic(previous) ), (LPARAM)hwnd );
}
}
SERVER_START_REQ( set_active_window )
......@@ -1607,7 +1615,11 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
if (send_message( hwnd, WM_QUERYNEWPALETTE, 0, 0 ))
send_message_timeout( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hwnd, 0,
SMTO_ABORTIFHUNG, 2000, NULL, FALSE );
if (!is_window(hwnd)) return FALSE;
if (!is_window(hwnd))
{
ret = FALSE;
goto clear_flags;
}
}
old_thread = previous ? get_window_thread( previous, NULL ) : 0;
......@@ -1639,7 +1651,7 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
}
}
if (is_window(hwnd))
if (!(winflags & WIN_IS_IN_ACTIVATION) && is_window(hwnd))
{
send_message( hwnd, WM_NCACTIVATE, hwnd == NtUserGetForegroundWindow(), (LPARAM)previous );
send_message( hwnd, WM_ACTIVATE,
......@@ -1666,12 +1678,15 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
/* 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 );
}
}
return TRUE;
clear_flags:
win_set_flags(hwnd, 0, WIN_IS_IN_ACTIVATION);
return ret;
}
/**********************************************************************
......
......@@ -105,6 +105,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_IN_ACTIVATION 0x0100 /* the window is in an activation process */
#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 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment