mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-09-13 09:17:20 -07:00
Added user32-recursive-activation patchset
This commit is contained in:
parent
9917fb4559
commit
ad822b6405
@ -303,6 +303,7 @@ patch_enable_all ()
|
||||
enable_user32_ScrollWindowEx="$1"
|
||||
enable_user32_ShowWindow="$1"
|
||||
enable_user32_msgbox_Support_WM_COPY_mesg="$1"
|
||||
enable_user32_recursive_activation="$1"
|
||||
enable_uxtheme_CloseThemeClass="$1"
|
||||
enable_uxtheme_GTK_Theming="$1"
|
||||
enable_version_VerQueryValue="$1"
|
||||
@ -1039,6 +1040,9 @@ patch_enable ()
|
||||
user32-msgbox-Support-WM_COPY-mesg)
|
||||
enable_user32_msgbox_Support_WM_COPY_mesg="$2"
|
||||
;;
|
||||
user32-recursive-activation)
|
||||
enable_user32_recursive_activation="$2"
|
||||
;;
|
||||
uxtheme-CloseThemeClass)
|
||||
enable_uxtheme_CloseThemeClass="$2"
|
||||
;;
|
||||
@ -6427,6 +6431,23 @@ if test "$enable_user32_msgbox_Support_WM_COPY_mesg" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset user32-recursive-activation
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#46274] user32: Prevent a recursive loop with the activation messages.
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/user32/focus.c, dlls/user32/tests/msg.c, dlls/user32/win.h
|
||||
# |
|
||||
if test "$enable_user32_recursive_activation" -eq 1; then
|
||||
patch_apply user32-recursive-activation/0001-user32-focus-Prevent-a-recursive-loop-with-the-activ.patch
|
||||
patch_apply user32-recursive-activation/0002-user32-tests-Test-a-recursive-activation-loop-on-WM_.patch
|
||||
(
|
||||
printf '%s\n' '+ { "Gabriel Ivăncescu", "user32/focus: Prevent a recursive loop with the activation messages.", 1 },';
|
||||
printf '%s\n' '+ { "Gabriel Ivăncescu", "user32/tests: Test a recursive activation loop on WM_ACTIVATE.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset uxtheme-CloseThemeClass
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
|
@ -0,0 +1,142 @@
|
||||
From b41d5d29f777dccdd43f09270858f2ca032db00d Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Gabriel=20Iv=C4=83ncescu?= <gabrielopcode@gmail.com>
|
||||
Date: Mon, 22 Jul 2019 15:29:25 +0300
|
||||
Subject: [PATCH 1/2] user32/focus: Prevent a recursive loop with the
|
||||
activation messages
|
||||
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>
|
||||
---
|
||||
dlls/user32/focus.c | 44 +++++++++++++++++++++++++++--------------
|
||||
dlls/user32/tests/msg.c | 2 +-
|
||||
dlls/user32/win.h | 1 +
|
||||
3 files changed, 31 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/dlls/user32/focus.c b/dlls/user32/focus.c
|
||||
index f1c883167e..0d32d008a7 100644
|
||||
--- a/dlls/user32/focus.c
|
||||
+++ b/dlls/user32/focus.c
|
||||
@@ -78,7 +78,7 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
|
||||
{
|
||||
HWND previous = GetActiveWindow();
|
||||
BOOL ret;
|
||||
- DWORD old_thread, new_thread;
|
||||
+ DWORD winflags, old_thread, new_thread;
|
||||
CBTACTIVATESTRUCT cbt;
|
||||
|
||||
if (previous == hwnd)
|
||||
@@ -87,16 +87,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 (HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hwnd, (LPARAM)&cbt, TRUE )) return FALSE;
|
||||
-
|
||||
- if (IsWindow(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))
|
||||
{
|
||||
- SendMessageW( previous, WM_NCACTIVATE, FALSE, (LPARAM)hwnd );
|
||||
- SendMessageW( previous, WM_ACTIVATE,
|
||||
- MAKEWPARAM( WA_INACTIVE, IsIconic(previous) ), (LPARAM)hwnd );
|
||||
+ ret = FALSE;
|
||||
+
|
||||
+ /* call CBT hook chain */
|
||||
+ cbt.fMouse = mouse;
|
||||
+ cbt.hWndActive = previous;
|
||||
+ if (HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hwnd, (LPARAM)&cbt, TRUE ))
|
||||
+ goto clear_flags;
|
||||
+
|
||||
+ if (IsWindow(previous))
|
||||
+ {
|
||||
+ SendMessageW( previous, WM_NCACTIVATE, FALSE, (LPARAM)hwnd );
|
||||
+ SendMessageW( previous, WM_ACTIVATE,
|
||||
+ MAKEWPARAM( WA_INACTIVE, IsIconic(previous) ), (LPARAM)hwnd );
|
||||
+ }
|
||||
}
|
||||
|
||||
SERVER_START_REQ( set_active_window )
|
||||
@@ -106,9 +114,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 clear_flags;
|
||||
if (prev) *prev = previous;
|
||||
- if (previous == hwnd) return TRUE;
|
||||
+ if (previous == hwnd) goto clear_flags;
|
||||
|
||||
if (hwnd)
|
||||
{
|
||||
@@ -116,7 +124,11 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
|
||||
if (SendMessageW( hwnd, WM_QUERYNEWPALETTE, 0, 0 ))
|
||||
SendMessageTimeoutW( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hwnd, 0,
|
||||
SMTO_ABORTIFHUNG, 2000, NULL );
|
||||
- if (!IsWindow(hwnd)) return FALSE;
|
||||
+ if (!IsWindow(hwnd))
|
||||
+ {
|
||||
+ ret = FALSE;
|
||||
+ goto clear_flags;
|
||||
+ }
|
||||
}
|
||||
|
||||
old_thread = previous ? GetWindowThreadProcessId( previous, NULL ) : 0;
|
||||
@@ -148,7 +160,7 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
|
||||
}
|
||||
}
|
||||
|
||||
- if (IsWindow(hwnd))
|
||||
+ if (!(winflags & WIN_IS_IN_ACTIVATION) && IsWindow(hwnd))
|
||||
{
|
||||
SendMessageW( hwnd, WM_NCACTIVATE, (hwnd == GetForegroundWindow()), (LPARAM)previous );
|
||||
SendMessageW( hwnd, WM_ACTIVATE,
|
||||
@@ -173,7 +185,9 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
|
||||
}
|
||||
}
|
||||
|
||||
- return TRUE;
|
||||
+clear_flags:
|
||||
+ win_set_flags(hwnd, 0, WIN_IS_IN_ACTIVATION);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
|
||||
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
|
||||
index a5bc1c5518..64f7eeecf3 100644
|
||||
--- a/dlls/user32/tests/msg.c
|
||||
+++ b/dlls/user32/tests/msg.c
|
||||
@@ -5142,7 +5142,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)
|
||||
diff --git a/dlls/user32/win.h b/dlls/user32/win.h
|
||||
index 1f51fd6331..a64cc66be5 100644
|
||||
--- a/dlls/user32/win.h
|
||||
+++ b/dlls/user32/win.h
|
||||
@@ -79,6 +79,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 */
|
||||
|
||||
/* Window functions */
|
||||
extern HWND get_hwnd_message_parent(void) DECLSPEC_HIDDEN;
|
||||
--
|
||||
2.17.1
|
||||
|
@ -0,0 +1,140 @@
|
||||
From 064570eb530a73e822bf19ccb9bc31cd3654c504 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Gabriel=20Iv=C4=83ncescu?= <gabrielopcode@gmail.com>
|
||||
Date: Mon, 22 Jul 2019 15:29:26 +0300
|
||||
Subject: [PATCH 2/2] user32/tests: Test a recursive activation loop on
|
||||
WM_ACTIVATE
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Windows only sends the activation messages and hooks once, until the
|
||||
SetActiveWindow completes for that window.
|
||||
|
||||
Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
|
||||
---
|
||||
dlls/user32/tests/msg.c | 81 +++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 81 insertions(+)
|
||||
|
||||
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
|
||||
index 64f7eeecf3..191e7bfffb 100644
|
||||
--- a/dlls/user32/tests/msg.c
|
||||
+++ b/dlls/user32/tests/msg.c
|
||||
@@ -4772,6 +4772,39 @@ static void test_showwindow(void)
|
||||
flush_sequence();
|
||||
}
|
||||
|
||||
+static void test_recursive_activation(void)
|
||||
+{
|
||||
+ static const struct message seq[] =
|
||||
+ {
|
||||
+ { HCBT_ACTIVATE, hook },
|
||||
+ { WM_NCACTIVATE, sent|wparam, TRUE },
|
||||
+ { WM_ACTIVATE, sent|wparam, WA_ACTIVE },
|
||||
+ { HCBT_ACTIVATE, hook },
|
||||
+ { WM_NCACTIVATE, sent|wparam, FALSE },
|
||||
+ { WM_ACTIVATE, sent|wparam, WA_INACTIVE },
|
||||
+ { WM_SETFOCUS, sent|optional },
|
||||
+ { 0 }
|
||||
+ };
|
||||
+ HWND hwnd, recursive;
|
||||
+
|
||||
+ hwnd = CreateWindowExA(0, "SimpleWindowClass", NULL, WS_OVERLAPPED|WS_VISIBLE,
|
||||
+ 100, 100, 200, 200, 0, 0, 0, NULL);
|
||||
+ ok(hwnd != 0, "Failed to create simple window\n");
|
||||
+
|
||||
+ recursive = CreateWindowExA(0, "RecursiveActivationClass", NULL, WS_OVERLAPPED|WS_VISIBLE,
|
||||
+ 10, 10, 50, 50, hwnd, 0, 0, NULL);
|
||||
+ ok(recursive != 0, "Failed to create recursive activation window\n");
|
||||
+ SetActiveWindow(hwnd);
|
||||
+
|
||||
+ flush_sequence();
|
||||
+ SetActiveWindow(recursive);
|
||||
+ ok_sequence(seq, "Recursive Activation", FALSE);
|
||||
+
|
||||
+ DestroyWindow(recursive);
|
||||
+ DestroyWindow(hwnd);
|
||||
+ flush_sequence();
|
||||
+}
|
||||
+
|
||||
static void test_sys_menu(void)
|
||||
{
|
||||
HWND hwnd;
|
||||
@@ -9699,6 +9732,48 @@ static LRESULT WINAPI ShowWindowProcA(HWND hwnd, UINT message, WPARAM wParam, LP
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static LRESULT WINAPI recursive_activation_wndprocA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
+{
|
||||
+ static LONG defwndproc_counter = 0;
|
||||
+ struct recvd_message msg;
|
||||
+ LRESULT ret;
|
||||
+
|
||||
+ switch (message)
|
||||
+ {
|
||||
+ /* log only specific messages we are interested in */
|
||||
+ case WM_NCACTIVATE:
|
||||
+ case WM_ACTIVATE:
|
||||
+ case WM_SETFOCUS:
|
||||
+ case WM_KILLFOCUS:
|
||||
+ break;
|
||||
+ default:
|
||||
+ return DefWindowProcA(hwnd, message, wParam, lParam);
|
||||
+ }
|
||||
+
|
||||
+ msg.hwnd = hwnd;
|
||||
+ msg.message = message;
|
||||
+ msg.flags = sent|wparam|lparam;
|
||||
+ if (defwndproc_counter) msg.flags |= defwinproc;
|
||||
+ msg.wParam = wParam;
|
||||
+ msg.lParam = lParam;
|
||||
+ msg.descr = "recursive_activation";
|
||||
+ add_message(&msg);
|
||||
+
|
||||
+ /* recursively activate ourselves by first losing activation and changing it back */
|
||||
+ if (message == WM_ACTIVATE && LOWORD(wParam) != WA_INACTIVE)
|
||||
+ {
|
||||
+ SetActiveWindow((HWND)lParam);
|
||||
+ SetActiveWindow(hwnd);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ defwndproc_counter++;
|
||||
+ ret = DefWindowProcA(hwnd, message, wParam, lParam);
|
||||
+ defwndproc_counter--;
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static LRESULT WINAPI PaintLoopProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg)
|
||||
@@ -9796,6 +9871,10 @@ static BOOL RegisterWindowClasses(void)
|
||||
cls.lpszClassName = "ShowWindowClass";
|
||||
if(!RegisterClassA(&cls)) return FALSE;
|
||||
|
||||
+ cls.lpfnWndProc = recursive_activation_wndprocA;
|
||||
+ cls.lpszClassName = "RecursiveActivationClass";
|
||||
+ if(!RegisterClassA(&cls)) return FALSE;
|
||||
+
|
||||
cls.lpfnWndProc = PopupMsgCheckProcA;
|
||||
cls.lpszClassName = "TestPopupClass";
|
||||
if(!RegisterClassA(&cls)) return FALSE;
|
||||
@@ -9851,6 +9930,7 @@ static BOOL is_our_logged_class(HWND hwnd)
|
||||
{
|
||||
if (!lstrcmpiA(buf, "TestWindowClass") ||
|
||||
!lstrcmpiA(buf, "ShowWindowClass") ||
|
||||
+ !lstrcmpiA(buf, "RecursiveActivationClass") ||
|
||||
!lstrcmpiA(buf, "TestParentClass") ||
|
||||
!lstrcmpiA(buf, "TestPopupClass") ||
|
||||
!lstrcmpiA(buf, "SimpleWindowClass") ||
|
||||
@@ -17756,6 +17836,7 @@ START_TEST(msg)
|
||||
test_messages();
|
||||
test_setwindowpos();
|
||||
test_showwindow();
|
||||
+ test_recursive_activation();
|
||||
invisible_parent_tests();
|
||||
test_mdi_messages();
|
||||
test_button_messages();
|
||||
--
|
||||
2.17.1
|
||||
|
2
patches/user32-recursive-activation/definition
Normal file
2
patches/user32-recursive-activation/definition
Normal file
@ -0,0 +1,2 @@
|
||||
Fixes: [46274] user32: Prevent a recursive loop with the activation messages.
|
||||
|
Loading…
Reference in New Issue
Block a user