[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