[PATCH v2 3/5] user32/tests: Add proper tests for SetActiveWindow(0).
Rémi Bernon
rbernon at codeweavers.com
Mon Jan 31 07:18:08 CST 2022
Shows that it switches focus to some other process window and back, and
only on some older Windows versions. Win10 simply returns 0 and does
nothing.
Stop calling it elsewhere, as it makes focus go to an unpredictable
window, which may very well not be ours.
Wine-Bug: https://bugs.winehq.org//show_bug.cgi?id=51391
Wine-Bug: https://bugs.winehq.org//show_bug.cgi?id=51130
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/user32/tests/win.c | 209 ++++++++++++++++++++++++++++++----------
1 file changed, 156 insertions(+), 53 deletions(-)
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c
index c9d9509eacc..e83e4bcb39e 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -106,22 +106,6 @@ static void flush_events( BOOL remove_messages )
}
}
-static BOOL wait_for_event(HANDLE event, int timeout)
-{
- DWORD end_time = GetTickCount() + timeout;
- MSG msg;
-
- do {
- if(MsgWaitForMultipleObjects(1, &event, FALSE, timeout, QS_ALLINPUT) == WAIT_OBJECT_0)
- return TRUE;
- while(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
- DispatchMessageA(&msg);
- timeout = end_time - GetTickCount();
- }while(timeout > 0);
-
- return FALSE;
-}
-
/* check the values returned by the various parent/owner functions on a given window */
static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_parent,
HWND gw_owner, HWND ga_root, HWND ga_root_owner )
@@ -188,6 +172,28 @@ static BOOL ignore_message( UINT message, HWND hwnd )
message == WM_DEVICECHANGE);
}
+static DWORD wait_for_events( DWORD count, HANDLE *events, DWORD timeout )
+{
+ DWORD ret, end = GetTickCount() + timeout;
+ MSG msg;
+
+ while ((ret = MsgWaitForMultipleObjects( count, events, FALSE, timeout, QS_ALLINPUT )) <= count)
+ {
+ while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ))
+ {
+ TranslateMessage( &msg );
+ DispatchMessageA( &msg );
+ }
+ if (ret < count) return ret;
+ if (timeout == INFINITE) continue;
+ if (end <= GetTickCount()) timeout = 0;
+ else timeout = end - GetTickCount();
+ }
+
+ ok( ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %#x\n", ret );
+ return ret;
+}
+
static BOOL CALLBACK EnumChildProc( HWND hwndChild, LPARAM lParam)
{
(*(LPINT)lParam)++;
@@ -3437,31 +3443,142 @@ todo_wine
DestroyWindow( child );
}
+static void test_SetActiveWindow_0_proc( char **argv )
+{
+ HANDLE start_event, stop_event;
+ HWND hwnd, other, tmp;
+ BOOL ret;
+
+ sscanf( argv[3], "%p", &other );
+ start_event = CreateEventW( NULL, FALSE, FALSE, L"test_SetActiveWindow_0_start" );
+ ok( start_event != 0, "CreateEventW failed, error %u\n", GetLastError() );
+ stop_event = CreateEventW( NULL, FALSE, FALSE, L"test_SetActiveWindow_0_stop" );
+ ok( stop_event != 0, "CreateEventW failed, error %u\n", GetLastError() );
+
+ hwnd = CreateWindowExA( 0, "static", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, NULL, NULL );
+ ok( !!hwnd, "CreateWindowExA failed, error %u\n", GetLastError() );
+ flush_events( TRUE );
+
+ ret = SetForegroundWindow( hwnd );
+ ok( ret, "SetForegroundWindow failed, error %u\n", GetLastError() );
+
+ tmp = GetForegroundWindow();
+ ok( tmp == hwnd, "GetForegroundWindow returned %p\n", tmp );
+ tmp = GetActiveWindow();
+ ok( tmp == hwnd, "GetActiveWindow returned %p\n", tmp );
+ tmp = GetFocus();
+ ok( tmp == hwnd, "GetFocus returned %p\n", tmp );
+
+ SetLastError( 0xdeadbeef );
+ tmp = SetActiveWindow( 0 );
+ if (!tmp) ok( GetLastError() == 0xdeadbeef, "got error %u\n", GetLastError() );
+ else /* < Win10 */
+ {
+ ok( tmp == hwnd, "SetActiveWindow returned %p\n", tmp );
+ todo_wine
+ ok( GetLastError() == 0, "got error %u\n", GetLastError() );
+
+ tmp = GetForegroundWindow();
+ ok( tmp == other || tmp == 0, "GetForegroundWindow returned %p\n", tmp );
+ tmp = GetActiveWindow();
+ ok( tmp == 0, "GetActiveWindow returned %p\n", tmp );
+ tmp = GetFocus();
+ ok( tmp == 0, "GetFocus returned %p\n", tmp );
+
+ SetEvent( start_event );
+ wait_for_events( 1, &stop_event, INFINITE );
+
+ tmp = GetForegroundWindow();
+ todo_wine
+ ok( tmp == other, "GetForegroundWindow returned %p\n", tmp );
+ tmp = GetActiveWindow();
+ ok( tmp == 0, "GetActiveWindow returned %p\n", tmp );
+ tmp = GetFocus();
+ ok( tmp == 0, "GetFocus returned %p\n", tmp );
+ }
+
+ tmp = SetActiveWindow( 0 );
+ ok( tmp == 0, "SetActiveWindow returned %p\n", tmp );
+ tmp = GetForegroundWindow();
+ todo_wine
+ ok( tmp == hwnd, "GetForegroundWindow returned %p\n", tmp );
+ tmp = GetActiveWindow();
+ todo_wine
+ ok( tmp == hwnd, "GetActiveWindow returned %p\n", tmp );
+ tmp = GetFocus();
+ todo_wine
+ ok( tmp == hwnd, "GetFocus returned %p\n", tmp );
+
+ CloseHandle( start_event );
+ CloseHandle( stop_event );
+ DestroyWindow( hwnd );
+}
+
+static void test_SetActiveWindow_0( char **argv )
+{
+ STARTUPINFOA startup = {.cb = sizeof(STARTUPINFOA)};
+ PROCESS_INFORMATION info;
+ char cmdline[MAX_PATH];
+ HANDLE events[3];
+ HWND hwnd, tmp;
+ BOOL ret;
+
+ hwnd = CreateWindowExA( 0, "static", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, NULL, NULL );
+ ok( !!hwnd, "CreateWindowExA failed, error %u\n", GetLastError() );
+ SetWindowPos( hwnd, HWND_TOPMOST, 150, 150, 300, 300, SWP_FRAMECHANGED | SWP_SHOWWINDOW );
+ flush_events( TRUE );
+
+ tmp = GetForegroundWindow();
+ ok( tmp == hwnd, "GetForegroundWindow returned %p\n", tmp );
+ tmp = GetActiveWindow();
+ ok( tmp == hwnd, "GetActiveWindow returned %p\n", tmp );
+ tmp = GetFocus();
+ ok( tmp == hwnd, "GetFocus returned %p\n", tmp );
+
+ events[1] = CreateEventW( NULL, FALSE, FALSE, L"test_SetActiveWindow_0_start" );
+ ok( events[1] != 0, "CreateEventW failed, error %u\n", GetLastError() );
+ events[2] = CreateEventW( NULL, FALSE, FALSE, L"test_SetActiveWindow_0_stop" );
+ ok( events[2] != 0, "CreateEventW failed, error %u\n", GetLastError() );
+
+ sprintf( cmdline, "%s %s SetActiveWindow_0 %p", argv[0], argv[1], hwnd );
+ ret = CreateProcessA( NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info );
+ ok( ret, "CreateProcessA failed, error %u\n", GetLastError() );
+
+ events[0] = info.hProcess;
+ if (wait_for_events( 2, events, INFINITE ) == 1)
+ {
+ tmp = GetForegroundWindow();
+ todo_wine
+ ok( tmp == hwnd, "GetForegroundWindow returned %p\n", tmp );
+ tmp = GetActiveWindow();
+ todo_wine
+ ok( tmp == hwnd, "GetActiveWindow returned %p\n", tmp );
+ tmp = GetFocus();
+ todo_wine
+ ok( tmp == hwnd, "GetFocus returned %p\n", tmp );
+ SetEvent( events[2] );
+ }
+
+ wait_child_process( info.hProcess );
+ CloseHandle( info.hProcess );
+ CloseHandle( info.hThread );
+ CloseHandle( events[1] );
+ CloseHandle( events[2] );
+
+ DestroyWindow( hwnd );
+}
+
static void test_SetActiveWindow(HWND hwnd)
{
HWND hwnd2, ret;
flush_events( TRUE );
ShowWindow(hwnd, SW_HIDE);
- SetFocus(0);
- SetActiveWindow(0);
check_wnd_state(0, 0, 0, 0);
ShowWindow(hwnd, SW_SHOW);
check_wnd_state(hwnd, hwnd, hwnd, 0);
- SetLastError(0xdeadbeef);
- ret = SetActiveWindow(0);
- ok(ret == hwnd || broken(!ret) /* Win10 1809 */, "expected %p, got %p\n", hwnd, ret);
- if (!ret) ok(GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError());
- if (!GetActiveWindow()) /* doesn't always work on vista */
- {
- check_wnd_state(0, 0, 0, 0);
- ret = SetActiveWindow(hwnd);
- ok(ret == 0, "SetActiveWindow returned %p instead of 0\n", ret);
- }
- check_wnd_state(hwnd, hwnd, hwnd, 0);
-
SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
check_wnd_state(hwnd, hwnd, hwnd, 0);
@@ -3510,17 +3627,7 @@ static void test_SetActiveWindow(HWND hwnd)
ret = SetActiveWindow(hwnd2);
ok(ret == hwnd, "expected %p, got %p\n", hwnd, ret);
check_wnd_state(hwnd, hwnd, hwnd, 0);
- SetLastError(0xdeadbeef);
- ret = SetActiveWindow(0);
- ok(ret == hwnd || broken(!ret) /* Win10 1809 */, "expected %p, got %p\n", hwnd, ret);
- if (!ret) ok(GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError());
- if (!GetActiveWindow())
- {
- ret = SetActiveWindow(hwnd2);
- ok(ret == NULL, "expected NULL, got %p\n", ret);
- todo_wine
- check_active_state(hwnd, hwnd, hwnd);
- }
+
DestroyWindow(hwnd2);
}
@@ -3561,22 +3668,11 @@ static void test_SetForegroundWindow(HWND hwnd)
flush_events( TRUE );
ShowWindow(hwnd, SW_HIDE);
- SetFocus(0);
- SetActiveWindow(0);
check_wnd_state(0, 0, 0, 0);
ShowWindow(hwnd, SW_SHOW);
check_wnd_state(hwnd, hwnd, hwnd, 0);
- SetLastError(0xdeadbeef);
- hwnd2 = SetActiveWindow(0);
- ok(hwnd2 == hwnd || broken(!hwnd2) /* Win10 1809 */, "expected %p, got %p\n", hwnd, hwnd2);
- if (!hwnd2) ok(GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError());
- if (GetActiveWindow() == hwnd) /* doesn't always work on vista */
- check_wnd_state(hwnd, hwnd, hwnd, 0);
- else
- check_wnd_state(0, 0, 0, 0);
-
ret = SetForegroundWindow(hwnd);
if (!ret)
{
@@ -9876,7 +9972,7 @@ static void test_window_from_point(const char *argv0)
startup.cb = sizeof(startup);
ok(CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL,
&startup, &info), "CreateProcess failed.\n");
- ok(wait_for_event(start_event, 1000), "didn't get start_event\n");
+ ok(wait_for_events(1, &start_event, 1000) == 0, "didn't get start_event\n");
child = GetWindow(hwnd, GW_CHILD);
win = WindowFromPoint(pt);
@@ -12502,6 +12598,12 @@ START_TEST(win)
return;
}
+ if (argc == 4 && !strcmp( argv[2], "SetActiveWindow_0" ))
+ {
+ test_SetActiveWindow_0_proc( argv );
+ return;
+ }
+
if (!RegisterWindowClasses()) assert(0);
hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window",
@@ -12563,6 +12665,7 @@ START_TEST(win)
test_SetWindowPos(hwndMain, hwndMain2);
test_SetMenu(hwndMain);
test_SetFocus(hwndMain);
+ test_SetActiveWindow_0( argv );
test_SetActiveWindow(hwndMain);
test_NCRedraw();
--
2.34.1
More information about the wine-devel
mailing list