user32/tests: Add proper tests for SetActiveWindow(0).
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@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
fa28e05cf5
commit
ebe3cea01d
|
@ -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 */
|
/* 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,
|
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 )
|
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);
|
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)
|
static BOOL CALLBACK EnumChildProc( HWND hwndChild, LPARAM lParam)
|
||||||
{
|
{
|
||||||
(*(LPINT)lParam)++;
|
(*(LPINT)lParam)++;
|
||||||
|
@ -3437,31 +3443,142 @@ static void test_SetFocus(HWND hwnd)
|
||||||
DestroyWindow( child );
|
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)
|
static void test_SetActiveWindow(HWND hwnd)
|
||||||
{
|
{
|
||||||
HWND hwnd2, ret;
|
HWND hwnd2, ret;
|
||||||
|
|
||||||
flush_events( TRUE );
|
flush_events( TRUE );
|
||||||
ShowWindow(hwnd, SW_HIDE);
|
ShowWindow(hwnd, SW_HIDE);
|
||||||
SetFocus(0);
|
|
||||||
SetActiveWindow(0);
|
|
||||||
check_wnd_state(0, 0, 0, 0);
|
check_wnd_state(0, 0, 0, 0);
|
||||||
|
|
||||||
ShowWindow(hwnd, SW_SHOW);
|
ShowWindow(hwnd, SW_SHOW);
|
||||||
check_wnd_state(hwnd, hwnd, hwnd, 0);
|
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);
|
SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
|
||||||
check_wnd_state(hwnd, hwnd, hwnd, 0);
|
check_wnd_state(hwnd, hwnd, hwnd, 0);
|
||||||
|
|
||||||
|
@ -3510,17 +3627,7 @@ static void test_SetActiveWindow(HWND hwnd)
|
||||||
ret = SetActiveWindow(hwnd2);
|
ret = SetActiveWindow(hwnd2);
|
||||||
ok(ret == hwnd, "expected %p, got %p\n", hwnd, ret);
|
ok(ret == hwnd, "expected %p, got %p\n", hwnd, ret);
|
||||||
check_wnd_state(hwnd, hwnd, hwnd, 0);
|
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);
|
DestroyWindow(hwnd2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3561,22 +3668,11 @@ static void test_SetForegroundWindow(HWND hwnd)
|
||||||
|
|
||||||
flush_events( TRUE );
|
flush_events( TRUE );
|
||||||
ShowWindow(hwnd, SW_HIDE);
|
ShowWindow(hwnd, SW_HIDE);
|
||||||
SetFocus(0);
|
|
||||||
SetActiveWindow(0);
|
|
||||||
check_wnd_state(0, 0, 0, 0);
|
check_wnd_state(0, 0, 0, 0);
|
||||||
|
|
||||||
ShowWindow(hwnd, SW_SHOW);
|
ShowWindow(hwnd, SW_SHOW);
|
||||||
check_wnd_state(hwnd, hwnd, hwnd, 0);
|
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);
|
ret = SetForegroundWindow(hwnd);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
{
|
{
|
||||||
|
@ -9876,7 +9972,7 @@ static void test_window_from_point(const char *argv0)
|
||||||
startup.cb = sizeof(startup);
|
startup.cb = sizeof(startup);
|
||||||
ok(CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL,
|
ok(CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL,
|
||||||
&startup, &info), "CreateProcess failed.\n");
|
&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);
|
child = GetWindow(hwnd, GW_CHILD);
|
||||||
win = WindowFromPoint(pt);
|
win = WindowFromPoint(pt);
|
||||||
|
@ -12502,6 +12598,12 @@ START_TEST(win)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (argc == 4 && !strcmp( argv[2], "SetActiveWindow_0" ))
|
||||||
|
{
|
||||||
|
test_SetActiveWindow_0_proc( argv );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!RegisterWindowClasses()) assert(0);
|
if (!RegisterWindowClasses()) assert(0);
|
||||||
|
|
||||||
hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window",
|
hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window",
|
||||||
|
@ -12563,6 +12665,7 @@ START_TEST(win)
|
||||||
test_SetWindowPos(hwndMain, hwndMain2);
|
test_SetWindowPos(hwndMain, hwndMain2);
|
||||||
test_SetMenu(hwndMain);
|
test_SetMenu(hwndMain);
|
||||||
test_SetFocus(hwndMain);
|
test_SetFocus(hwndMain);
|
||||||
|
test_SetActiveWindow_0( argv );
|
||||||
test_SetActiveWindow(hwndMain);
|
test_SetActiveWindow(hwndMain);
|
||||||
test_NCRedraw();
|
test_NCRedraw();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue