When calling SetForegroundWindow for a window in another thread, an internal message is posted to the thread's message queue.
If this thread then calls SetForegroundWindow before processing its messages it will execute the corresponding set_active_window first, but then overwrite the active window later, when processing its internal messages.
This is not always the correct behavior and these tests help determine what should actually be done in various situations.
This aims to check the following sequences, with A being a separate thread that created three windows, and B being the main test thread with some windows initially in background:
* window A0, A1, or A2 is foreground, then: * B sets foreground to window A0 * A sets foreground to window A1
As well as these sequences where foreground is also temporarily switched to window B0:
* window A0, A1, or A2 is foreground, then: * B sets foreground to window B0 * B sets foreground to window A0 * B sets foreground to window B0 * A sets foreground to window A1
In addition, we also do tests with additional SetActiveWindow / SetFocus calls to check their influence.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
Another try at this. Back to message filtering, as it's a more generic solution than last time counter.
It still needs to be able to filter these internal messages so we have to change get_message request handler a bit. We don't provide any way to specifically remove messages though.
v2: * Remove cross-process test and the related debugger patch, the results are the same as cross-thread.
* Trace counted messages in the test so we can compare traces, add more test traces too.
* Send a WM_USER message too, to validate that we shouldn't process sent messages while filtering internal messages.
* Filter internal WM_WINE_SETACTIVEWINDOW messages using a thread local flag and a call to peek_message.
* Add a fix for the additional focus messages received when calling SetFocus, even if the window already has focus, fixing the last remaining todo in the test.
Supersedes: 191845-191849
dlls/user32/tests/win.c | 290 +++++++++++++++++++++++++++++++++------- 1 file changed, 238 insertions(+), 52 deletions(-)
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index 843da8900f1..bbc3fbfb1d9 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -3240,40 +3240,180 @@ static void test_SetActiveWindow(HWND hwnd) DestroyWindow(hwnd2); }
-struct create_window_thread_params +static int test_sfw_msg_count; + +static LRESULT WINAPI test_sfw_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { - HWND window; - HANDLE window_created; - HANDLE test_finished; + switch (msg) + { + case WM_NCACTIVATE: trace("%p WM_NCACTIVATE %d %p\n", hwnd, (DWORD)wparam, (HWND)lparam); test_sfw_msg_count++; break; + case WM_ACTIVATE: trace("%p WM_ACTIVATE %d %p\n", hwnd, (DWORD)wparam, (HWND)lparam); test_sfw_msg_count++; break; + case WM_SETFOCUS: trace("%p WM_SETFOCUS %p %d\n", hwnd, (HWND)wparam, (DWORD)lparam); test_sfw_msg_count++; break; + case WM_KILLFOCUS: trace("%p WM_KILLFOCUS %p %d\n", hwnd, (HWND)wparam, (DWORD)lparam); test_sfw_msg_count++; break; + case WM_USER: trace("%p WM_USER %d %d\n", hwnd, (DWORD)wparam, (DWORD)lparam); test_sfw_msg_count++; break; + } + + return DefWindowProcA( hwnd, msg, wparam, lparam ); +} + +struct test_sfw_test_desc +{ + int initial_window; + BOOL steal_foreground; + BOOL call_set_active_window; + BOOL call_set_focus; + + BOOL todo_msgcount_before_set_foreground; + int msgcount_before_set_foreground; + BOOL todo_msgcount_after_set_foreground; + int msgcount_after_set_foreground; + BOOL todo_msgcount_after_peek_message; + int msgcount_after_peek_message; + BOOL todo_expected_window; + int expected_window; +}; + +static struct test_sfw_test_desc test_sfw_tests[] = { + {1, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 0, FALSE, 7, FALSE, 0}, + {1, TRUE, FALSE, FALSE, FALSE, 0, TRUE, 1, TRUE, 7, TRUE, 0}, + {1, FALSE, TRUE, FALSE, FALSE, 0, FALSE, 0, FALSE, 7, FALSE, 0}, + {1, TRUE, TRUE, FALSE, FALSE, 0, TRUE, 1, TRUE, 7, TRUE, 0}, + {1, FALSE, FALSE, TRUE, FALSE, 0, FALSE, 0, FALSE, 7, FALSE, 0}, + {1, TRUE, FALSE, TRUE, FALSE, 0, TRUE, 1, TRUE, 7, TRUE, 0}, + + {2, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 6, TRUE, 1, TRUE, 1}, + {2, TRUE, FALSE, FALSE, FALSE, 0, FALSE, 6, TRUE, 1, TRUE, 1}, + {2, FALSE, TRUE, FALSE, FALSE, 6, FALSE, 0, TRUE, 1, TRUE, 1}, + {2, TRUE, TRUE, FALSE, FALSE, 6, TRUE, 1, TRUE, 7, TRUE, 0}, + {2, FALSE, FALSE, TRUE, TRUE, 8, FALSE, 0, TRUE, 1, TRUE, 1}, + {2, TRUE, FALSE, TRUE, TRUE, 8, TRUE, 1, TRUE, 7, TRUE, 0}, + + {0, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 6, FALSE, 1, FALSE, 1}, + {0, TRUE, FALSE, FALSE, FALSE, 0, FALSE, 6, TRUE, 1, TRUE, 1}, + {0, FALSE, TRUE, FALSE, FALSE, 6, FALSE, 0, FALSE, 1, FALSE, 1}, + {0, TRUE, TRUE, FALSE, FALSE, 6, TRUE, 1, FALSE, 7, FALSE, 0}, + {0, FALSE, FALSE, TRUE, TRUE, 8, FALSE, 0, FALSE, 1, FALSE, 1}, + {0, TRUE, FALSE, TRUE, TRUE, 8, TRUE, 1, FALSE, 7, FALSE, 0}, };
-static DWORD WINAPI create_window_thread(void *param) +static DWORD WINAPI test_sfw_thread( void *param ) { - struct create_window_thread_params *p = param; + HANDLE test_sfw_ready, test_sfw_start, test_sfw_done; + WNDPROC wndprocs[3]; + HWND windows[3]; DWORD res; BOOL ret; + MSG msg; + int i; + + test_sfw_ready = OpenEventA( EVENT_ALL_ACCESS, FALSE, "test_sfw_ready" ); + test_sfw_start = OpenEventA( EVENT_ALL_ACCESS, FALSE, "test_sfw_start" ); + test_sfw_done = OpenEventA( EVENT_ALL_ACCESS, FALSE, "test_sfw_done" );
- p->window = CreateWindowA("static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0); + windows[1] = CreateWindowA( "static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0 ); + windows[2] = CreateWindowA( "static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0 ); + windows[0] = CreateWindowA( "static", "test_sfw_window", WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0 ); + trace( "window[0]:%p windows[1]:%p windows[2]:%p\n", windows[0], windows[1], windows[2] );
- ret = SetEvent(p->window_created); + ret = SetEvent( test_sfw_ready ); ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
- res = WaitForSingleObject(p->test_finished, INFINITE); + /* wait for the initial state to be clean */ + + res = WaitForSingleObject( test_sfw_start, INFINITE ); ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError()); + ret = ResetEvent( test_sfw_start ); + ok( ret, "ResetEvent failed, last error %#x.\n", GetLastError() ); + + for (i = 0; i < ARRAY_SIZE(windows); ++i) + wndprocs[i] = (WNDPROC)SetWindowLongPtrA( windows[i], GWLP_WNDPROC, (LONG_PTR)test_sfw_wndproc ); + + flush_events( TRUE ); + + for (i = 0; i < ARRAY_SIZE(test_sfw_tests); ++i) + { + struct test_sfw_test_desc *test = test_sfw_tests + i; + HWND initial_window = windows[test->initial_window]; + HWND expected_window = windows[test->expected_window]; + trace( "running test %d\n", i ); + + SetForegroundWindow( initial_window ); + flush_events( TRUE ); + check_wnd_state( initial_window, initial_window, initial_window, 0 ); + + ret = SetEvent( test_sfw_ready ); + ok( ret, "SetEvent failed, last error %#x.\n", GetLastError() ); + + res = WaitForSingleObject( test_sfw_start, INFINITE ); + ok( res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError() ); + ret = ResetEvent( test_sfw_start ); + ok( ret, "ResetEvent failed, last error %#x.\n", GetLastError() ); + + test_sfw_msg_count = 0; + trace( "%d: before SetForegroundWindow\n", i ); + if (test->call_set_active_window) SetActiveWindow( windows[1] ); + if (test->call_set_focus) SetFocus( windows[1] ); + todo_wine_if( test->todo_msgcount_before_set_foreground ) + ok( test_sfw_msg_count == test->msgcount_before_set_foreground, + "%d: Unexpected number of messages received before SetForegroundWindow: %d\n", i, test_sfw_msg_count ); + + test_sfw_msg_count = 0; + trace( "%d: calling SetForegroundWindow\n", i ); + SetForegroundWindow( windows[1] ); + todo_wine_if( test->todo_msgcount_after_set_foreground ) + ok( test_sfw_msg_count == test->msgcount_after_set_foreground, + "%d: Unexpected number of messages received after SetForegroundWindow: %d\n", i, test_sfw_msg_count ); + + ok( GetForegroundWindow() == windows[1], "%d: GetForegroundWindow() returned %p\n", i, + GetForegroundWindow() ); + ok( GetActiveWindow() == windows[1], "%d: GetActiveWindow() returned %p\n", i, GetActiveWindow() ); + ok( GetFocus() == windows[1], "%d: GetFocus() returned %p\n", i, GetFocus() ); + + test_sfw_msg_count = 0; + trace( "%d: calling PeekMessageA\n", i ); + while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); + todo_wine_if( test->todo_msgcount_after_peek_message ) + ok( test_sfw_msg_count == test->msgcount_after_peek_message, + "%d: Unexpected number of messages received after PeekMessageA: %d\n", i, test_sfw_msg_count ); + + todo_wine_if( test->todo_expected_window ) + ok( GetForegroundWindow() == expected_window, "%d: GetForegroundWindow() returned %p\n", i, + GetForegroundWindow() ); + todo_wine_if( test->todo_expected_window ) + ok( GetActiveWindow() == expected_window, "%d: GetActiveWindow() returned %p\n", i, GetActiveWindow() ); + todo_wine_if( test->todo_expected_window ) + ok( GetFocus() == expected_window, "%d: GetFocus() returned %p\n", i, GetFocus() ); + trace( "%d: done\n", i ); + + res = WaitForSingleObject( test_sfw_done, INFINITE ); + ok( res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError() ); + ret = ResetEvent( test_sfw_done ); + ok( ret, "ResetEvent failed, last error %#x.\n", GetLastError() ); + } + + for (i = 0; i < ARRAY_SIZE(windows); ++i) + SetWindowLongPtrA( windows[i], GWLP_WNDPROC, (LONG_PTR)wndprocs[i] ); + + for (i = 0; i < ARRAY_SIZE(windows); ++i) DestroyWindow( windows[i] ); + + CloseHandle( test_sfw_ready ); + CloseHandle( test_sfw_start ); + CloseHandle( test_sfw_done );
- DestroyWindow(p->window); return 0; }
-static void test_SetForegroundWindow(HWND hwnd) +static void test_SetForegroundWindow( HWND hwnd ) { - struct create_window_thread_params thread_params; - HANDLE thread; + HANDLE thread = 0; + HANDLE test_sfw_ready, test_sfw_start, test_sfw_done; DWORD res, tid; - BOOL ret; + HWND test_sfw_window; HWND hwnd2; - MSG msg; LONG style; + BOOL ret; + MSG msg; + int i;
flush_events( TRUE ); ShowWindow(hwnd, SW_HIDE); @@ -3347,50 +3487,96 @@ static void test_SetForegroundWindow(HWND hwnd) DestroyWindow(hwnd2); check_wnd_state(hwnd, hwnd, hwnd, 0);
- hwnd2 = CreateWindowA("static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0); - check_wnd_state(hwnd2, hwnd2, hwnd2, 0); + hwnd2 = CreateWindowA( "static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0 ); + check_wnd_state( hwnd2, hwnd2, hwnd2, 0 );
- thread_params.window_created = CreateEventW(NULL, FALSE, FALSE, NULL); - ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError()); - thread_params.test_finished = CreateEventW(NULL, FALSE, FALSE, NULL); - ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError()); - thread = CreateThread(NULL, 0, create_window_thread, &thread_params, 0, &tid); - ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError()); - res = WaitForSingleObject(thread_params.window_created, INFINITE); - ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError()); - check_wnd_state(hwnd2, thread_params.window, hwnd2, 0); + test_sfw_ready = CreateEventA( NULL, FALSE, FALSE, "test_sfw_ready" ); + ok( !!test_sfw_ready, "CreateEvent failed, last error %#x.\n", GetLastError() ); + test_sfw_start = CreateEventA( NULL, FALSE, FALSE, "test_sfw_start" ); + ok( !!test_sfw_start, "CreateEvent failed, last error %#x.\n", GetLastError() ); + test_sfw_done = CreateEventA( NULL, FALSE, FALSE, "test_sfw_done" ); + ok( !!test_sfw_done, "CreateEvent failed, last error %#x.\n", GetLastError() );
- SetForegroundWindow(hwnd2); - check_wnd_state(hwnd2, hwnd2, hwnd2, 0); + thread = CreateThread( NULL, 0, test_sfw_thread, NULL, 0, &tid ); + ok( !!thread, "Failed to create thread, last error %#x.\n", GetLastError() );
- while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); - if (0) check_wnd_state(hwnd2, hwnd2, hwnd2, 0); + res = WaitForSingleObject( test_sfw_ready, INFINITE ); + ok( res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError() ); + ret = ResetEvent( test_sfw_ready ); + ok( ret, "ResetEvent failed, last error %#x.\n", GetLastError() ); + + test_sfw_window = FindWindowA( "static", "test_sfw_window" ); + ok( test_sfw_window != NULL, "FindWindowA failed to find test window, last error %#x\n", GetLastError() ); + check_wnd_state( hwnd2, test_sfw_window, hwnd2, 0 ); + + /* ensure initial state is consistent, with hwnd as active / foreground / focus window */ + + SetForegroundWindow( hwnd2 ); + check_wnd_state( hwnd2, hwnd2, hwnd2, 0 ); + + while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); + if (0) check_wnd_state( hwnd2, hwnd2, hwnd2, 0 );
/* FIXME: these tests are failing because of a race condition - * between internal focus state applied immediately and X11 focus - * message coming late */ - todo_wine ok(GetActiveWindow() == hwnd2, "Expected active window %p, got %p.\n", hwnd2, GetActiveWindow()); - todo_wine ok(GetFocus() == hwnd2, "Expected focus window %p, got %p.\n", hwnd2, GetFocus()); + * between internal process focus state applied immediately and + * X11 focus message coming late */ + todo_wine + ok( GetActiveWindow() == hwnd2, "Expected active window %p, got %p.\n", hwnd2, GetActiveWindow() ); + todo_wine + ok( GetFocus() == hwnd2, "Expected focus window %p, got %p.\n", hwnd2, GetFocus() );
- SetForegroundWindow(hwnd); - check_wnd_state(hwnd, hwnd, hwnd, 0); - style = GetWindowLongA(hwnd2, GWL_STYLE) | WS_CHILD; - ok(SetWindowLongA(hwnd2, GWL_STYLE, style), "SetWindowLong failed\n"); - ok(SetForegroundWindow(hwnd2), "SetForegroundWindow failed\n"); - check_wnd_state(hwnd2, hwnd2, hwnd2, 0); + SetForegroundWindow( hwnd ); + check_wnd_state( hwnd, hwnd, hwnd, 0 ); + style = GetWindowLongA( hwnd2, GWL_STYLE ) | WS_CHILD; + ok( SetWindowLongA( hwnd2, GWL_STYLE, style ), "SetWindowLong failed\n" ); + ok( SetForegroundWindow( hwnd2 ), "SetForegroundWindow failed\n" ); + check_wnd_state( hwnd2, hwnd2, hwnd2, 0 );
- SetForegroundWindow(hwnd); - check_wnd_state(hwnd, hwnd, hwnd, 0); - ok(SetWindowLongA(hwnd2, GWL_STYLE, style & (~WS_POPUP)), "SetWindowLong failed\n"); - ok(!SetForegroundWindow(hwnd2), "SetForegroundWindow failed\n"); - check_wnd_state(hwnd, hwnd, hwnd, 0); + SetForegroundWindow( hwnd ); + check_wnd_state( hwnd, hwnd, hwnd, 0 ); + ok( SetWindowLongA( hwnd2, GWL_STYLE, style & (~WS_POPUP) ), "SetWindowLong failed\n" ); + ok( !SetForegroundWindow( hwnd2 ), "SetForegroundWindow failed\n" ); + check_wnd_state( hwnd, hwnd, hwnd, 0 );
- SetEvent(thread_params.test_finished); - WaitForSingleObject(thread, INFINITE); - CloseHandle(thread_params.test_finished); - CloseHandle(thread_params.window_created); - CloseHandle(thread); - DestroyWindow(hwnd2); + res = SetEvent( test_sfw_start ); + ok( res, "SetEvent failed, last error %#x.\n", GetLastError() ); + + /* now run the tests */ + + for (i = 0; i < ARRAY_SIZE(test_sfw_tests); ++i) + { + struct test_sfw_test_desc *test = test_sfw_tests + i; + + while (MsgWaitForMultipleObjects( 1, &test_sfw_ready, FALSE, INFINITE, QS_SENDMESSAGE ) != WAIT_OBJECT_0) + { + while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE )) + DispatchMessageA( &msg ); + } + + ret = ResetEvent( test_sfw_ready ); + ok( ret, "ResetEvent failed, last error %#x.\n", GetLastError() ); + + if (test->steal_foreground) SetForegroundWindow( hwnd ); + SetForegroundWindow( test_sfw_window ); + if (test->steal_foreground) SetForegroundWindow( hwnd ); + SendNotifyMessageW( test_sfw_window, WM_USER, 0, 0 ); + + res = SetEvent( test_sfw_start ); + ok( res, "SetEvent failed, last error %#x.\n", GetLastError() ); + + ret = SetEvent( test_sfw_done ); + ok( res, "SetEvent failed, last error %#x.\n", GetLastError() ); + } + + WaitForSingleObject( thread, INFINITE ); + CloseHandle( thread ); + + CloseHandle( test_sfw_start ); + CloseHandle( test_sfw_done ); + CloseHandle( test_sfw_ready ); + + DestroyWindow( hwnd2 ); + flush_events( TRUE ); }
static WNDPROC old_button_proc; @@ -12040,7 +12226,7 @@ START_TEST(win) test_Expose(); test_layered_window();
- test_SetForegroundWindow(hwndMain); + test_SetForegroundWindow( hwndMain ); test_handles( hwndMain ); test_winregion(); test_map_points();
Instead of only checking that the window is foreground.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/message.c | 3 ++- dlls/user32/tests/win.c | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c index 4434f4b0c2a..02628e4b92b 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -1867,7 +1867,8 @@ static LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPAR if (is_desktop_window( hwnd )) return 0; return WIN_SetStyle(hwnd, wparam, lparam); case WM_WINE_SETACTIVEWINDOW: - if (!wparam && GetForegroundWindow() == hwnd) return 0; + if (!wparam && GetWindowThreadProcessId( GetForegroundWindow(), NULL ) == GetCurrentThreadId()) + return 0; return (LRESULT)SetActiveWindow( (HWND)wparam ); case WM_WINE_KEYBOARD_LL_HOOK: case WM_WINE_MOUSE_LL_HOOK: diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index bbc3fbfb1d9..a9400d4368a 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -3275,18 +3275,18 @@ struct test_sfw_test_desc
static struct test_sfw_test_desc test_sfw_tests[] = { {1, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 0, FALSE, 7, FALSE, 0}, - {1, TRUE, FALSE, FALSE, FALSE, 0, TRUE, 1, TRUE, 7, TRUE, 0}, + {1, TRUE, FALSE, FALSE, FALSE, 0, TRUE, 1, FALSE, 7, FALSE, 0}, {1, FALSE, TRUE, FALSE, FALSE, 0, FALSE, 0, FALSE, 7, FALSE, 0}, - {1, TRUE, TRUE, FALSE, FALSE, 0, TRUE, 1, TRUE, 7, TRUE, 0}, + {1, TRUE, TRUE, FALSE, FALSE, 0, TRUE, 1, FALSE, 7, FALSE, 0}, {1, FALSE, FALSE, TRUE, FALSE, 0, FALSE, 0, FALSE, 7, FALSE, 0}, - {1, TRUE, FALSE, TRUE, FALSE, 0, TRUE, 1, TRUE, 7, TRUE, 0}, + {1, TRUE, FALSE, TRUE, FALSE, 0, TRUE, 1, FALSE, 7, FALSE, 0},
{2, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 6, TRUE, 1, TRUE, 1}, {2, TRUE, FALSE, FALSE, FALSE, 0, FALSE, 6, TRUE, 1, TRUE, 1}, {2, FALSE, TRUE, FALSE, FALSE, 6, FALSE, 0, TRUE, 1, TRUE, 1}, - {2, TRUE, TRUE, FALSE, FALSE, 6, TRUE, 1, TRUE, 7, TRUE, 0}, + {2, TRUE, TRUE, FALSE, FALSE, 6, TRUE, 1, FALSE, 7, FALSE, 0}, {2, FALSE, FALSE, TRUE, TRUE, 8, FALSE, 0, TRUE, 1, TRUE, 1}, - {2, TRUE, FALSE, TRUE, TRUE, 8, TRUE, 1, TRUE, 7, TRUE, 0}, + {2, TRUE, FALSE, TRUE, TRUE, 8, TRUE, 1, FALSE, 7, FALSE, 0},
{0, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 6, FALSE, 1, FALSE, 1}, {0, TRUE, FALSE, FALSE, FALSE, 0, FALSE, 6, TRUE, 1, TRUE, 1},
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79679
Your paranoid android.
=== w1064v1809 (32 bit report) ===
user32: win.c:3164: Test failed: GetActiveWindow() = 0003004C win.c:3167: Test failed: GetFocus() = 00000000 win.c:3179: Test failed: GetFocus() = 00000000 win.c:3182: Test failed: GetFocus() = 00000000 win.c:3185: Test failed: GetFocus() = 00000000 win.c:3188: Test failed: GetActiveWindow() = 0003004C win.c:3192: Test failed: GetFocus() = 00000000 win.c:3195: Test failed: GetFocus() = 00000000 win.c:4075: Test failed: hwnd 00020174/00120286 message 0737 win.c:4080: Test failed: hwnd 00120286/00120286 message 0202 win.c:4085: Test failed: hwnd 00120286/00120286 message 0203 win.c:4089: Test failed: message 0202 available
=== w1064v1809 (64 bit report) ===
user32: win.c:3164: Test failed: GetActiveWindow() = 000000000003004E win.c:3167: Test failed: GetFocus() = 0000000000000000 win.c:3179: Test failed: GetFocus() = 0000000000000000 win.c:3182: Test failed: GetFocus() = 0000000000000000 win.c:3185: Test failed: GetFocus() = 0000000000000000 win.c:3188: Test failed: GetActiveWindow() = 000000000003004E win.c:3192: Test failed: GetFocus() = 0000000000000000 win.c:3195: Test failed: GetFocus() = 0000000000000000 win.c:4075: Test failed: hwnd 0000000000020174/00000000001302C8 message 0737 win.c:4080: Test failed: hwnd 00000000001302C8/00000000001302C8 message 0202 win.c:4085: Test failed: hwnd 00000000001302C8/00000000001302C8 message 0203 win.c:4089: Test failed: message 0202 available
=== w10pro64_2scr (64 bit report) ===
user32: win.c:4163: Test failed: hwnd 000000000003005A/000000000003005A message 0200 win.c:4165: Test failed: wparam 0 win.c:4176: Test failed: hwnd 000000000003005A/000000000003005A message 0203 win.c:4180: Test failed: message 0202 available
=== w10pro64_ar (64 bit report) ===
user32: win.c:3922: Test failed: message 0200 available
=== w10pro64_ja (64 bit report) ===
user32: win.c:9649: Test failed: didn't get start_event win.c:9664: Test failed: Timed out waiting for the child process win.c:9590: Test failed: transparent window didn't get WM_NCHITTEST message win.c:9591: Test failed: button under static window didn't get WM_LBUTTONUP
=== debiant (32 bit report) ===
user32: monitor: Timeout
=== debiant (32 bit Chinese:China report) ===
user32: monitor: Timeout
=== debiant (32 bit WoW report) ===
user32: monitor: Timeout
=== debiant (64 bit WoW report) ===
user32: monitor: Timeout
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/focus.c | 20 ++++++++++---------- dlls/user32/user_private.h | 6 ++++++ 2 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/dlls/user32/focus.c b/dlls/user32/focus.c index 4c18238a98b..d5add0ab197 100644 --- a/dlls/user32/focus.c +++ b/dlls/user32/focus.c @@ -71,10 +71,10 @@ static HWND set_focus_window( HWND hwnd ) /******************************************************************* * set_active_window */ -static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus ) +static BOOL set_active_window( HWND hwnd, HWND *prev, UINT flags ) { HWND previous = GetActiveWindow(); - BOOL ret; + BOOL ret, mouse = (flags & SET_ACTIVE_WINDOW_FLAGS_MOUSE); DWORD old_thread, new_thread; CBTACTIVATESTRUCT cbt;
@@ -156,7 +156,7 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus ) }
/* now change focus if necessary */ - if (focus) + if (flags & SET_ACTIVE_WINDOW_FLAGS_FOCUS) { GUITHREADINFO info;
@@ -177,7 +177,7 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus ) /******************************************************************* * set_foreground_window */ -static BOOL set_foreground_window( HWND hwnd, BOOL mouse ) +static BOOL set_foreground_window( HWND hwnd, UINT flags ) { BOOL ret, send_msg_old = FALSE, send_msg_new = FALSE; HWND previous = 0; @@ -199,12 +199,12 @@ static BOOL set_foreground_window( HWND hwnd, BOOL mouse ) if (send_msg_old) /* old window belongs to other thread */ SendNotifyMessageW( previous, WM_WINE_SETACTIVEWINDOW, 0, 0 ); else if (send_msg_new) /* old window belongs to us but new one to other thread */ - ret = set_active_window( 0, NULL, mouse, TRUE ); + ret = set_active_window( 0, NULL, flags|SET_ACTIVE_WINDOW_FLAGS_FOCUS );
if (send_msg_new) /* new window belongs to other thread */ SendNotifyMessageW( hwnd, WM_WINE_SETACTIVEWINDOW, (WPARAM)hwnd, 0 ); else /* new window belongs to us */ - ret = set_active_window( hwnd, NULL, mouse, TRUE ); + ret = set_active_window( hwnd, NULL, flags|SET_ACTIVE_WINDOW_FLAGS_FOCUS ); } return ret; } @@ -217,7 +217,7 @@ static BOOL set_foreground_window( HWND hwnd, BOOL mouse ) */ BOOL FOCUS_MouseActivate( HWND hwnd ) { - return set_foreground_window( hwnd, TRUE ); + return set_foreground_window( hwnd, SET_ACTIVE_WINDOW_FLAGS_MOUSE ); }
@@ -246,7 +246,7 @@ HWND WINAPI SetActiveWindow( HWND hwnd ) return GetActiveWindow(); /* Windows doesn't seem to return an error here */ }
- if (!set_active_window( hwnd, &prev, FALSE, TRUE )) return 0; + if (!set_active_window( hwnd, &prev, SET_ACTIVE_WINDOW_FLAGS_FOCUS )) return 0; return prev; }
@@ -293,7 +293,7 @@ HWND WINAPI SetFocus( HWND hwnd ) /* activate hwndTop if needed. */ if (hwndTop != GetActiveWindow()) { - if (!set_active_window( hwndTop, NULL, FALSE, FALSE )) return 0; + if (!set_active_window( hwndTop, NULL, 0 )) return 0; if (!IsWindow( hwnd )) return 0; /* Abort if window destroyed */
/* Do not change focus if the window is no longer active */ @@ -319,7 +319,7 @@ BOOL WINAPI SetForegroundWindow( HWND hwnd ) TRACE( "%p\n", hwnd );
hwnd = WIN_GetFullHandle( hwnd ); - return set_foreground_window( hwnd, FALSE ); + return set_foreground_window( hwnd, 0 ); }
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 7761a1ceb4f..193fde53307 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -60,6 +60,12 @@ enum wine_internal_message WM_WINE_LAST_DRIVER_MSG = 0x80001fff };
+enum set_active_window_flags +{ + SET_ACTIVE_WINDOW_FLAGS_MOUSE = 1, + SET_ACTIVE_WINDOW_FLAGS_FOCUS = 2, +}; + typedef struct tagUSER_DRIVER { /* keyboard functions */ HKL (CDECL *pActivateKeyboardLayout)(HKL, UINT);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79680
Your paranoid android.
=== debiant (32 bit report) ===
user32: monitor: Timeout
=== debiant (32 bit Chinese:China report) ===
user32: monitor: Timeout
=== debiant (32 bit WoW report) ===
user32: monitor: Timeout win.c:11720: Test failed: got normal pos (200,88)-(400,288) win.c:11723: Test failed: got window rect (200,88)-(400,288) win.c:11736: Test failed: got normal pos (200,88)-(400,288)
=== debiant (64 bit WoW report) ===
user32: monitor: Timeout
Instead of SetActiveWindow, and provide a flag to indicate its internal nature.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/focus.c | 6 +++--- dlls/user32/message.c | 2 +- dlls/user32/user_private.h | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/dlls/user32/focus.c b/dlls/user32/focus.c index d5add0ab197..dd4c282e63d 100644 --- a/dlls/user32/focus.c +++ b/dlls/user32/focus.c @@ -71,7 +71,7 @@ static HWND set_focus_window( HWND hwnd ) /******************************************************************* * set_active_window */ -static BOOL set_active_window( HWND hwnd, HWND *prev, UINT flags ) +BOOL set_active_window( HWND hwnd, HWND *prev, UINT flags ) { HWND previous = GetActiveWindow(); BOOL ret, mouse = (flags & SET_ACTIVE_WINDOW_FLAGS_MOUSE); @@ -197,12 +197,12 @@ static BOOL set_foreground_window( HWND hwnd, UINT flags ) if (ret && previous != hwnd) { if (send_msg_old) /* old window belongs to other thread */ - SendNotifyMessageW( previous, WM_WINE_SETACTIVEWINDOW, 0, 0 ); + SendNotifyMessageW( previous, WM_WINE_SETACTIVEWINDOW, 0, flags|SET_ACTIVE_WINDOW_FLAGS_FOCUS ); else if (send_msg_new) /* old window belongs to us but new one to other thread */ ret = set_active_window( 0, NULL, flags|SET_ACTIVE_WINDOW_FLAGS_FOCUS );
if (send_msg_new) /* new window belongs to other thread */ - SendNotifyMessageW( hwnd, WM_WINE_SETACTIVEWINDOW, (WPARAM)hwnd, 0 ); + SendNotifyMessageW( hwnd, WM_WINE_SETACTIVEWINDOW, (WPARAM)hwnd, flags|SET_ACTIVE_WINDOW_FLAGS_FOCUS ); else /* new window belongs to us */ ret = set_active_window( hwnd, NULL, flags|SET_ACTIVE_WINDOW_FLAGS_FOCUS ); } diff --git a/dlls/user32/message.c b/dlls/user32/message.c index 02628e4b92b..2a70b57b597 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -1869,7 +1869,7 @@ static LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPAR case WM_WINE_SETACTIVEWINDOW: if (!wparam && GetWindowThreadProcessId( GetForegroundWindow(), NULL ) == GetCurrentThreadId()) return 0; - return (LRESULT)SetActiveWindow( (HWND)wparam ); + return (LRESULT)set_active_window( (HWND)wparam, NULL, lparam|SET_ACTIVE_WINDOW_FLAGS_INTERNAL ); case WM_WINE_KEYBOARD_LL_HOOK: case WM_WINE_MOUSE_LL_HOOK: { diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 193fde53307..febb1bbb7bb 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -64,6 +64,7 @@ enum set_active_window_flags { SET_ACTIVE_WINDOW_FLAGS_MOUSE = 1, SET_ACTIVE_WINDOW_FLAGS_FOCUS = 2, + SET_ACTIVE_WINDOW_FLAGS_INTERNAL = 4, };
typedef struct tagUSER_DRIVER { @@ -251,6 +252,7 @@ extern struct rawinput_thread_data *rawinput_thread_data(void);
extern void CLIPBOARD_ReleaseOwner( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL FOCUS_MouseActivate( HWND hwnd ) DECLSPEC_HIDDEN; +extern BOOL set_active_window( HWND hwnd, HWND *prev, UINT flags ) DECLSPEC_HIDDEN; extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) DECLSPEC_HIDDEN; extern void free_dce( struct dce *dce, HWND hwnd ) DECLSPEC_HIDDEN; extern void invalidate_dce( struct tagWND *win, const RECT *rect ) DECLSPEC_HIDDEN;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79681
Your paranoid android.
=== debiant (32 bit report) ===
user32: monitor: Timeout
=== debiant (32 bit Chinese:China report) ===
user32: monitor: Timeout
=== debiant (32 bit WoW report) ===
user32: menu.c:2337: Test failed: test 25 monitor: Timeout win.c:11720: Test failed: got normal pos (200,88)-(400,288) win.c:11723: Test failed: got window rect (200,88)-(400,288) win.c:11736: Test failed: got normal pos (200,88)-(400,288)
=== debiant (64 bit WoW report) ===
user32: monitor: Timeout
We will need this to process only a specific internal message type without processing any of the other messages.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- server/queue.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/server/queue.c b/server/queue.c index 2c780a94e2c..85491675abb 100644 --- a/server/queue.c +++ b/server/queue.c @@ -2496,8 +2496,8 @@ DECL_HANDLER(post_quit_message) /* get a message from the current queue */ DECL_HANDLER(get_message) { + struct message *msg; struct timer *timer; - struct list *ptr; struct msg_queue *queue = get_current_queue(); user_handle_t get_win = get_user_full_handle( req->get_win ); unsigned int filter = req->flags >> 16; @@ -2515,9 +2515,12 @@ DECL_HANDLER(get_message) if (!filter) filter = QS_ALLINPUT;
/* first check for sent messages */ - if ((ptr = list_head( &queue->msg_list[SEND_MESSAGE] ))) + LIST_FOR_EACH_ENTRY( msg, &queue->msg_list[SEND_MESSAGE], struct message, entry ) { - struct message *msg = LIST_ENTRY( ptr, struct message, entry ); + /* skip filtered internal messages */ + if ((req->get_first & 0x80000000) && (req->get_last & 0x80000000) && + !check_msg_filter( msg->msg, req->get_first, req->get_last )) + continue; receive_message( queue, msg, reply ); return; }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79682
Your paranoid android.
=== debiant (32 bit report) ===
user32: monitor: Timeout win.c:10352: Test failed: Expected foreground window 000E013E, got 007F00FA win.c:10354: Test failed: GetActiveWindow() = 00000000 win.c:10354: Test failed: GetFocus() = 00000000 win.c:10355: Test failed: Received WM_ACTIVATEAPP(1), did not expect it. win.c:10356: Test failed: Received WM_ACTIVATEAPP(0), did not expect it. win.c:10364: Test failed: Expected foreground window 000E013E, got 00000000 win.c:10366: Test failed: GetActiveWindow() = 00000000 win.c:10366: Test failed: GetFocus() = 00000000 win.c:10374: Test failed: Received WM_ACTIVATEAPP(1), did not expect it.
=== debiant (32 bit Chinese:China report) ===
user32: clipboard.c:760: Test failed: 2: gle 5 clipboard.c:765: Test failed: 2.0: got 0000 instead of 000d clipboard.c:805: Test failed: 2: gle 1418 clipboard.c:815: Test failed: 2: count 4 clipboard.c:818: Test failed: 2: gle 1418 clipboard.c:833: Test failed: 2: gle 5 clipboard.c:838: Test failed: 2.0: got 0000 instead of 000d clipboard.c:868: Test failed: 2: gle 1418 monitor: Timeout
=== debiant (32 bit WoW report) ===
user32: monitor: Timeout
=== debiant (64 bit WoW report) ===
user32: monitor: Timeout
We need to use the internal peek_message here, as we really only should process these internal messages and shouldn't check the driver events.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/focus.c | 11 +++++++++ dlls/user32/message.c | 2 +- dlls/user32/tests/win.c | 46 +++++++++++++++++--------------------- dlls/user32/user_private.h | 2 ++ 4 files changed, 34 insertions(+), 27 deletions(-)
diff --git a/dlls/user32/focus.c b/dlls/user32/focus.c index dd4c282e63d..6a09d491995 100644 --- a/dlls/user32/focus.c +++ b/dlls/user32/focus.c @@ -73,10 +73,12 @@ static HWND set_focus_window( HWND hwnd ) */ BOOL set_active_window( HWND hwnd, HWND *prev, UINT flags ) { + struct user_thread_info *thread_data = get_user_thread_info(); HWND previous = GetActiveWindow(); BOOL ret, mouse = (flags & SET_ACTIVE_WINDOW_FLAGS_MOUSE); DWORD old_thread, new_thread; CBTACTIVATESTRUCT cbt; + MSG msg;
if (previous == hwnd) { @@ -84,6 +86,15 @@ BOOL set_active_window( HWND hwnd, HWND *prev, UINT flags ) return TRUE; }
+ if (thread_data->ignore_setactivewindow) return FALSE; + else if (!(flags & SET_ACTIVE_WINDOW_FLAGS_INTERNAL) && + GetWindowThreadProcessId( GetForegroundWindow(), NULL ) == GetCurrentThreadId()) + { + thread_data->ignore_setactivewindow = TRUE; + while (peek_message( &msg, 0, WM_WINE_SETACTIVEWINDOW, WM_WINE_SETACTIVEWINDOW, PM_REMOVE|PM_QS_SENDMESSAGE, 0 )); + thread_data->ignore_setactivewindow = FALSE; + } + /* call CBT hook chain */ cbt.fMouse = mouse; cbt.hWndActive = previous; diff --git a/dlls/user32/message.c b/dlls/user32/message.c index 2a70b57b597..89f8727670a 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -2643,7 +2643,7 @@ static inline void call_sendmsg_callback( SENDASYNCPROC callback, HWND hwnd, UIN * available; -1 on error. * All pending sent messages are processed before returning. */ -static int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags, UINT changed_mask ) +int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags, UINT changed_mask ) { LRESULT result; struct user_thread_info *thread_info = get_user_thread_info(); diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index a9400d4368a..feb1fb4a1bf 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -3267,33 +3267,31 @@ struct test_sfw_test_desc int msgcount_before_set_foreground; BOOL todo_msgcount_after_set_foreground; int msgcount_after_set_foreground; - BOOL todo_msgcount_after_peek_message; int msgcount_after_peek_message; - BOOL todo_expected_window; int expected_window; };
static struct test_sfw_test_desc test_sfw_tests[] = { - {1, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 0, FALSE, 7, FALSE, 0}, - {1, TRUE, FALSE, FALSE, FALSE, 0, TRUE, 1, FALSE, 7, FALSE, 0}, - {1, FALSE, TRUE, FALSE, FALSE, 0, FALSE, 0, FALSE, 7, FALSE, 0}, - {1, TRUE, TRUE, FALSE, FALSE, 0, TRUE, 1, FALSE, 7, FALSE, 0}, - {1, FALSE, FALSE, TRUE, FALSE, 0, FALSE, 0, FALSE, 7, FALSE, 0}, - {1, TRUE, FALSE, TRUE, FALSE, 0, TRUE, 1, FALSE, 7, FALSE, 0}, - - {2, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 6, TRUE, 1, TRUE, 1}, - {2, TRUE, FALSE, FALSE, FALSE, 0, FALSE, 6, TRUE, 1, TRUE, 1}, - {2, FALSE, TRUE, FALSE, FALSE, 6, FALSE, 0, TRUE, 1, TRUE, 1}, - {2, TRUE, TRUE, FALSE, FALSE, 6, TRUE, 1, FALSE, 7, FALSE, 0}, - {2, FALSE, FALSE, TRUE, TRUE, 8, FALSE, 0, TRUE, 1, TRUE, 1}, - {2, TRUE, FALSE, TRUE, TRUE, 8, TRUE, 1, FALSE, 7, FALSE, 0}, - - {0, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 6, FALSE, 1, FALSE, 1}, - {0, TRUE, FALSE, FALSE, FALSE, 0, FALSE, 6, TRUE, 1, TRUE, 1}, - {0, FALSE, TRUE, FALSE, FALSE, 6, FALSE, 0, FALSE, 1, FALSE, 1}, - {0, TRUE, TRUE, FALSE, FALSE, 6, TRUE, 1, FALSE, 7, FALSE, 0}, - {0, FALSE, FALSE, TRUE, TRUE, 8, FALSE, 0, FALSE, 1, FALSE, 1}, - {0, TRUE, FALSE, TRUE, TRUE, 8, TRUE, 1, FALSE, 7, FALSE, 0}, + {1, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 0, 7, 0}, + {1, TRUE, FALSE, FALSE, FALSE, 0, TRUE, 1, 7, 0}, + {1, FALSE, TRUE, FALSE, FALSE, 0, FALSE, 0, 7, 0}, + {1, TRUE, TRUE, FALSE, FALSE, 0, TRUE, 1, 7, 0}, + {1, FALSE, FALSE, TRUE, FALSE, 0, FALSE, 0, 7, 0}, + {1, TRUE, FALSE, TRUE, FALSE, 0, TRUE, 1, 7, 0}, + + {2, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 6, 1, 1}, + {2, TRUE, FALSE, FALSE, FALSE, 0, FALSE, 6, 1, 1}, + {2, FALSE, TRUE, FALSE, FALSE, 6, FALSE, 0, 1, 1}, + {2, TRUE, TRUE, FALSE, FALSE, 6, TRUE, 1, 7, 0}, + {2, FALSE, FALSE, TRUE, TRUE, 8, FALSE, 0, 1, 1}, + {2, TRUE, FALSE, TRUE, TRUE, 8, TRUE, 1, 7, 0}, + + {0, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 6, 1, 1}, + {0, TRUE, FALSE, FALSE, FALSE, 0, FALSE, 6, 1, 1}, + {0, FALSE, TRUE, FALSE, FALSE, 6, FALSE, 0, 1, 1}, + {0, TRUE, TRUE, FALSE, FALSE, 6, TRUE, 1, 7, 0}, + {0, FALSE, FALSE, TRUE, TRUE, 8, FALSE, 0, 1, 1}, + {0, TRUE, FALSE, TRUE, TRUE, 8, TRUE, 1, 7, 0}, };
static DWORD WINAPI test_sfw_thread( void *param ) @@ -3372,16 +3370,12 @@ static DWORD WINAPI test_sfw_thread( void *param ) test_sfw_msg_count = 0; trace( "%d: calling PeekMessageA\n", i ); while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); - todo_wine_if( test->todo_msgcount_after_peek_message ) ok( test_sfw_msg_count == test->msgcount_after_peek_message, "%d: Unexpected number of messages received after PeekMessageA: %d\n", i, test_sfw_msg_count );
- todo_wine_if( test->todo_expected_window ) ok( GetForegroundWindow() == expected_window, "%d: GetForegroundWindow() returned %p\n", i, GetForegroundWindow() ); - todo_wine_if( test->todo_expected_window ) ok( GetActiveWindow() == expected_window, "%d: GetActiveWindow() returned %p\n", i, GetActiveWindow() ); - todo_wine_if( test->todo_expected_window ) ok( GetFocus() == expected_window, "%d: GetFocus() returned %p\n", i, GetFocus() ); trace( "%d: done\n", i );
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index febb1bbb7bb..0c0968a16c2 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -209,6 +209,7 @@ struct user_thread_info HWND top_window; /* Desktop window */ HWND msg_window; /* HWND_MESSAGE parent window */ struct rawinput_thread_data *rawinput; /* RawInput thread local data / buffer */ + BOOL ignore_setactivewindow; /* Ingore WM_WINE_SETACTIVEWINDOW messages */ };
C_ASSERT( sizeof(struct user_thread_info) <= sizeof(((TEB *)0)->Win32ClientInfo) ); @@ -252,6 +253,7 @@ extern struct rawinput_thread_data *rawinput_thread_data(void);
extern void CLIPBOARD_ReleaseOwner( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL FOCUS_MouseActivate( HWND hwnd ) DECLSPEC_HIDDEN; +extern int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags, UINT changed_mask ) DECLSPEC_HIDDEN; extern BOOL set_active_window( HWND hwnd, HWND *prev, UINT flags ) DECLSPEC_HIDDEN; extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) DECLSPEC_HIDDEN; extern void free_dce( struct dce *dce, HWND hwnd ) DECLSPEC_HIDDEN;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79683
Your paranoid android.
=== w1064v1809 (32 bit report) ===
user32: win.c:3164: Test failed: GetActiveWindow() = 00030296 win.c:3167: Test failed: GetFocus() = 00000000 win.c:3179: Test failed: GetFocus() = 00000000 win.c:3182: Test failed: GetFocus() = 00000000 win.c:3185: Test failed: GetFocus() = 00000000 win.c:3188: Test failed: GetActiveWindow() = 00030296 win.c:3192: Test failed: GetFocus() = 00000000 win.c:3195: Test failed: GetFocus() = 00000000 win.c:4069: Test failed: hwnd 00020174/00120066 message 0737 win.c:4074: Test failed: hwnd 00120066/00120066 message 0202 win.c:4079: Test failed: hwnd 00120066/00120066 message 0203 win.c:4083: Test failed: message 0202 available
=== w10pro64_2scr (32 bit report) ===
user32: win.c:9658: Test failed: Timed out waiting for the child process
=== w1064v1809 (64 bit report) ===
user32: win.c:3164: Test failed: GetActiveWindow() = 0000000000030060 win.c:3167: Test failed: GetFocus() = 0000000000000000 win.c:3179: Test failed: GetFocus() = 0000000000000000 win.c:3182: Test failed: GetFocus() = 0000000000000000 win.c:3185: Test failed: GetFocus() = 0000000000000000 win.c:3188: Test failed: GetActiveWindow() = 0000000000030060 win.c:3192: Test failed: GetFocus() = 0000000000000000 win.c:3195: Test failed: GetFocus() = 0000000000000000 win.c:4069: Test failed: hwnd 00000000000200E4/00000000005E0048 message 0737 win.c:4074: Test failed: hwnd 00000000005E0048/00000000005E0048 message 0202 win.c:4079: Test failed: hwnd 00000000005E0048/00000000005E0048 message 0203 win.c:4083: Test failed: message 0202 available
=== debiant (32 bit report) ===
user32: monitor: Timeout
=== debiant (32 bit Chinese:China report) ===
user32: monitor: Timeout
=== debiant (32 bit WoW report) ===
user32: monitor: Timeout win.c:11714: Test failed: got normal pos (200,88)-(400,288) win.c:11717: Test failed: got window rect (200,88)-(400,288) win.c:11730: Test failed: got normal pos (200,88)-(400,288)
=== debiant (64 bit WoW report) ===
user32: menu.c:2337: Test failed: test 27 monitor: Timeout
When window is already active but has lost foreground, as shown by concurrent SetForegroundWindow tests.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/focus.c | 4 ++++ dlls/user32/tests/win.c | 42 ++++++++++++++++++++--------------------- 2 files changed, 24 insertions(+), 22 deletions(-)
diff --git a/dlls/user32/focus.c b/dlls/user32/focus.c index 6a09d491995..91b4b40af4e 100644 --- a/dlls/user32/focus.c +++ b/dlls/user32/focus.c @@ -212,6 +212,10 @@ static BOOL set_foreground_window( HWND hwnd, UINT flags ) else if (send_msg_new) /* old window belongs to us but new one to other thread */ ret = set_active_window( 0, NULL, flags|SET_ACTIVE_WINDOW_FLAGS_FOCUS );
+ /* already active, set_active_window will do no nothing */ + if (!send_msg_new && hwnd == GetActiveWindow()) + SendMessageW( hwnd, WM_NCACTIVATE, TRUE, (LPARAM)hwnd ); + if (send_msg_new) /* new window belongs to other thread */ SendNotifyMessageW( hwnd, WM_WINE_SETACTIVEWINDOW, (WPARAM)hwnd, flags|SET_ACTIVE_WINDOW_FLAGS_FOCUS ); else /* new window belongs to us */ diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index feb1fb4a1bf..4453363291a 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -3265,33 +3265,32 @@ struct test_sfw_test_desc
BOOL todo_msgcount_before_set_foreground; int msgcount_before_set_foreground; - BOOL todo_msgcount_after_set_foreground; int msgcount_after_set_foreground; int msgcount_after_peek_message; int expected_window; };
static struct test_sfw_test_desc test_sfw_tests[] = { - {1, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 0, 7, 0}, - {1, TRUE, FALSE, FALSE, FALSE, 0, TRUE, 1, 7, 0}, - {1, FALSE, TRUE, FALSE, FALSE, 0, FALSE, 0, 7, 0}, - {1, TRUE, TRUE, FALSE, FALSE, 0, TRUE, 1, 7, 0}, - {1, FALSE, FALSE, TRUE, FALSE, 0, FALSE, 0, 7, 0}, - {1, TRUE, FALSE, TRUE, FALSE, 0, TRUE, 1, 7, 0}, - - {2, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 6, 1, 1}, - {2, TRUE, FALSE, FALSE, FALSE, 0, FALSE, 6, 1, 1}, - {2, FALSE, TRUE, FALSE, FALSE, 6, FALSE, 0, 1, 1}, - {2, TRUE, TRUE, FALSE, FALSE, 6, TRUE, 1, 7, 0}, - {2, FALSE, FALSE, TRUE, TRUE, 8, FALSE, 0, 1, 1}, - {2, TRUE, FALSE, TRUE, TRUE, 8, TRUE, 1, 7, 0}, - - {0, FALSE, FALSE, FALSE, FALSE, 0, FALSE, 6, 1, 1}, - {0, TRUE, FALSE, FALSE, FALSE, 0, FALSE, 6, 1, 1}, - {0, FALSE, TRUE, FALSE, FALSE, 6, FALSE, 0, 1, 1}, - {0, TRUE, TRUE, FALSE, FALSE, 6, TRUE, 1, 7, 0}, - {0, FALSE, FALSE, TRUE, TRUE, 8, FALSE, 0, 1, 1}, - {0, TRUE, FALSE, TRUE, TRUE, 8, TRUE, 1, 7, 0}, + {1, FALSE, FALSE, FALSE, FALSE, 0, 0, 7, 0}, + {1, TRUE, FALSE, FALSE, FALSE, 0, 1, 7, 0}, + {1, FALSE, TRUE, FALSE, FALSE, 0, 0, 7, 0}, + {1, TRUE, TRUE, FALSE, FALSE, 0, 1, 7, 0}, + {1, FALSE, FALSE, TRUE, FALSE, 0, 0, 7, 0}, + {1, TRUE, FALSE, TRUE, FALSE, 0, 1, 7, 0}, + + {2, FALSE, FALSE, FALSE, FALSE, 0, 6, 1, 1}, + {2, TRUE, FALSE, FALSE, FALSE, 0, 6, 1, 1}, + {2, FALSE, TRUE, FALSE, FALSE, 6, 0, 1, 1}, + {2, TRUE, TRUE, FALSE, FALSE, 6, 1, 7, 0}, + {2, FALSE, FALSE, TRUE, TRUE, 8, 0, 1, 1}, + {2, TRUE, FALSE, TRUE, TRUE, 8, 1, 7, 0}, + + {0, FALSE, FALSE, FALSE, FALSE, 0, 6, 1, 1}, + {0, TRUE, FALSE, FALSE, FALSE, 0, 6, 1, 1}, + {0, FALSE, TRUE, FALSE, FALSE, 6, 0, 1, 1}, + {0, TRUE, TRUE, FALSE, FALSE, 6, 1, 7, 0}, + {0, FALSE, FALSE, TRUE, TRUE, 8, 0, 1, 1}, + {0, TRUE, FALSE, TRUE, TRUE, 8, 1, 7, 0}, };
static DWORD WINAPI test_sfw_thread( void *param ) @@ -3358,7 +3357,6 @@ static DWORD WINAPI test_sfw_thread( void *param ) test_sfw_msg_count = 0; trace( "%d: calling SetForegroundWindow\n", i ); SetForegroundWindow( windows[1] ); - todo_wine_if( test->todo_msgcount_after_set_foreground ) ok( test_sfw_msg_count == test->msgcount_after_set_foreground, "%d: Unexpected number of messages received after SetForegroundWindow: %d\n", i, test_sfw_msg_count );
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79684
Your paranoid android.
=== w1064v1809 (32 bit report) ===
user32: win.c:3164: Test failed: GetActiveWindow() = 0003004A win.c:3167: Test failed: GetFocus() = 00000000 win.c:3179: Test failed: GetFocus() = 00000000 win.c:3182: Test failed: GetFocus() = 00000000 win.c:3185: Test failed: GetFocus() = 00000000 win.c:3188: Test failed: GetActiveWindow() = 0003004A win.c:3192: Test failed: GetFocus() = 00000000 win.c:3195: Test failed: GetFocus() = 00000000 win.c:4067: Test failed: hwnd 00040292/00020136 message 0737 win.c:4072: Test failed: hwnd 00020136/00020136 message 0202 win.c:4077: Test failed: hwnd 00020136/00020136 message 0203 win.c:4081: Test failed: message 0202 available
=== w1064v1809 (64 bit report) ===
user32: win.c:3164: Test failed: GetActiveWindow() = 0000000000040292 win.c:3167: Test failed: GetFocus() = 0000000000000000 win.c:3179: Test failed: GetFocus() = 0000000000000000 win.c:3182: Test failed: GetFocus() = 0000000000000000 win.c:3185: Test failed: GetFocus() = 0000000000000000 win.c:3188: Test failed: GetActiveWindow() = 0000000000040292 win.c:3192: Test failed: GetFocus() = 0000000000000000 win.c:3195: Test failed: GetFocus() = 0000000000000000 win.c:4067: Test failed: hwnd 0000000000040066/00000000000D02C6 message 0737 win.c:4072: Test failed: hwnd 00000000000D02C6/00000000000D02C6 message 0202 win.c:4077: Test failed: hwnd 00000000000D02C6/00000000000D02C6 message 0203 win.c:4081: Test failed: message 0202 available
=== w10pro64_2scr (64 bit report) ===
user32: win.c:3932: Test failed: message 0200 available
=== w10pro64_ja (64 bit report) ===
user32: win.c:10152: Test failed: pos = 00fa00fa win.c:10156: Test failed: pos = 00fa00fa win.c:10160: Test failed: pos = 00fa00fa
=== debiant (32 bit report) ===
user32: monitor: Timeout
=== debiant (32 bit Chinese:China report) ===
user32: monitor: Timeout
=== debiant (32 bit WoW report) ===
user32: monitor: Timeout
=== debiant (64 bit WoW report) ===
user32: monitor: Timeout msg.c:15898: Test failed: OpenClipboard failed, err=5 msg.c:15898: Test failed: EmptyClipboard failed, err=1418 msg.c:15898: Test failed: CloseClipboard failed, err=1418
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/focus.c | 1 - dlls/user32/tests/win.c | 42 ++++++++++++++++++++--------------------- 2 files changed, 20 insertions(+), 23 deletions(-)
diff --git a/dlls/user32/focus.c b/dlls/user32/focus.c index 91b4b40af4e..43b86ae99ad 100644 --- a/dlls/user32/focus.c +++ b/dlls/user32/focus.c @@ -52,7 +52,6 @@ static HWND set_focus_window( HWND hwnd ) } SERVER_END_REQ; if (!ret) return 0; - if (previous == hwnd) return previous;
if (previous) { diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index 4453363291a..264358a02c8 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -3263,7 +3263,6 @@ struct test_sfw_test_desc BOOL call_set_active_window; BOOL call_set_focus;
- BOOL todo_msgcount_before_set_foreground; int msgcount_before_set_foreground; int msgcount_after_set_foreground; int msgcount_after_peek_message; @@ -3271,26 +3270,26 @@ struct test_sfw_test_desc };
static struct test_sfw_test_desc test_sfw_tests[] = { - {1, FALSE, FALSE, FALSE, FALSE, 0, 0, 7, 0}, - {1, TRUE, FALSE, FALSE, FALSE, 0, 1, 7, 0}, - {1, FALSE, TRUE, FALSE, FALSE, 0, 0, 7, 0}, - {1, TRUE, TRUE, FALSE, FALSE, 0, 1, 7, 0}, - {1, FALSE, FALSE, TRUE, FALSE, 0, 0, 7, 0}, - {1, TRUE, FALSE, TRUE, FALSE, 0, 1, 7, 0}, - - {2, FALSE, FALSE, FALSE, FALSE, 0, 6, 1, 1}, - {2, TRUE, FALSE, FALSE, FALSE, 0, 6, 1, 1}, - {2, FALSE, TRUE, FALSE, FALSE, 6, 0, 1, 1}, - {2, TRUE, TRUE, FALSE, FALSE, 6, 1, 7, 0}, - {2, FALSE, FALSE, TRUE, TRUE, 8, 0, 1, 1}, - {2, TRUE, FALSE, TRUE, TRUE, 8, 1, 7, 0}, - - {0, FALSE, FALSE, FALSE, FALSE, 0, 6, 1, 1}, - {0, TRUE, FALSE, FALSE, FALSE, 0, 6, 1, 1}, - {0, FALSE, TRUE, FALSE, FALSE, 6, 0, 1, 1}, - {0, TRUE, TRUE, FALSE, FALSE, 6, 1, 7, 0}, - {0, FALSE, FALSE, TRUE, TRUE, 8, 0, 1, 1}, - {0, TRUE, FALSE, TRUE, TRUE, 8, 1, 7, 0}, + {1, FALSE, FALSE, FALSE, 0, 0, 7, 0}, + {1, TRUE, FALSE, FALSE, 0, 1, 7, 0}, + {1, FALSE, TRUE, FALSE, 0, 0, 7, 0}, + {1, TRUE, TRUE, FALSE, 0, 1, 7, 0}, + {1, FALSE, FALSE, TRUE, 0, 0, 7, 0}, + {1, TRUE, FALSE, TRUE, 0, 1, 7, 0}, + + {2, FALSE, FALSE, FALSE, 0, 6, 1, 1}, + {2, TRUE, FALSE, FALSE, 0, 6, 1, 1}, + {2, FALSE, TRUE, FALSE, 6, 0, 1, 1}, + {2, TRUE, TRUE, FALSE, 6, 1, 7, 0}, + {2, FALSE, FALSE, TRUE, 8, 0, 1, 1}, + {2, TRUE, FALSE, TRUE, 8, 1, 7, 0}, + + {0, FALSE, FALSE, FALSE, 0, 6, 1, 1}, + {0, TRUE, FALSE, FALSE, 0, 6, 1, 1}, + {0, FALSE, TRUE, FALSE, 6, 0, 1, 1}, + {0, TRUE, TRUE, FALSE, 6, 1, 7, 0}, + {0, FALSE, FALSE, TRUE, 8, 0, 1, 1}, + {0, TRUE, FALSE, TRUE, 8, 1, 7, 0}, };
static DWORD WINAPI test_sfw_thread( void *param ) @@ -3350,7 +3349,6 @@ static DWORD WINAPI test_sfw_thread( void *param ) trace( "%d: before SetForegroundWindow\n", i ); if (test->call_set_active_window) SetActiveWindow( windows[1] ); if (test->call_set_focus) SetFocus( windows[1] ); - todo_wine_if( test->todo_msgcount_before_set_foreground ) ok( test_sfw_msg_count == test->msgcount_before_set_foreground, "%d: Unexpected number of messages received before SetForegroundWindow: %d\n", i, test_sfw_msg_count );
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79685
Your paranoid android.
=== w1064v1809 (32 bit report) ===
user32: win.c:3164: Test failed: GetActiveWindow() = 00030296 win.c:3167: Test failed: GetFocus() = 00000000 win.c:3179: Test failed: GetFocus() = 00000000 win.c:3182: Test failed: GetFocus() = 00000000 win.c:3185: Test failed: GetFocus() = 00000000 win.c:3188: Test failed: GetActiveWindow() = 00030296 win.c:3192: Test failed: GetFocus() = 00000000 win.c:3195: Test failed: GetFocus() = 00000000 win.c:4065: Test failed: hwnd 00020174/001502C8 message 0737 win.c:4070: Test failed: hwnd 001502C8/001502C8 message 0202 win.c:4075: Test failed: hwnd 001502C8/001502C8 message 0203 win.c:4079: Test failed: message 0202 available
=== w10pro64_2scr (32 bit report) ===
user32: win.c:9639: Test failed: didn't get start_event win.c:9654: Test failed: Timed out waiting for the child process win.c:9580: Test failed: transparent window didn't get WM_NCHITTEST message win.c:9581: Test failed: button under static window didn't get WM_LBUTTONUP
=== w10pro64_zh_CN (32 bit report) ===
user32: win.c:4091: Test failed: hwnd 000301A4/000301A4 message 0200 win.c:4095: Test failed: hwnd 000301A4/000301A4 message 0201 win.c:4104: Test failed: hwnd 00150016/00150016 message 0202 win.c:4107: Test failed: hwnd 00150016/00150016 message 0201
=== w1064v1809 (64 bit report) ===
user32: win.c:3164: Test failed: GetActiveWindow() = 0000000000030060 win.c:3167: Test failed: GetFocus() = 0000000000000000 win.c:3179: Test failed: GetFocus() = 0000000000000000 win.c:3182: Test failed: GetFocus() = 0000000000000000 win.c:3185: Test failed: GetFocus() = 0000000000000000 win.c:3188: Test failed: GetActiveWindow() = 0000000000030060 win.c:3192: Test failed: GetFocus() = 0000000000000000 win.c:3195: Test failed: GetFocus() = 0000000000000000 win.c:4065: Test failed: hwnd 00000000000200E4/00000000000B02D6 message 0737 win.c:4070: Test failed: hwnd 00000000000B02D6/00000000000B02D6 message 0202 win.c:4075: Test failed: hwnd 00000000000B02D6/00000000000B02D6 message 0203 win.c:4079: Test failed: message 0202 available
=== debiant (32 bit report) ===
user32: monitor: Timeout msg.c:13991: Test failed: EndDialog: 13: the msg sequence is not complete: expected 0000 - actual 0008
=== debiant (32 bit Chinese:China report) ===
user32: monitor: Timeout msg.c:13991: Test failed: EndDialog: 13: the msg sequence is not complete: expected 0000 - actual 0008
=== debiant (32 bit WoW report) ===
user32: monitor: Timeout msg.c:13991: Test failed: EndDialog: 13: the msg sequence is not complete: expected 0000 - actual 0008
=== debiant (64 bit WoW report) ===
user32: monitor: Timeout msg.c:13991: Test failed: EndDialog: 13: the msg sequence is not complete: expected 0000 - actual 0008
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79678
Your paranoid android.
=== w1064v1809 (32 bit report) ===
user32: win.c:3164: Test failed: GetActiveWindow() = 00030296 win.c:3167: Test failed: GetFocus() = 00000000 win.c:3179: Test failed: GetFocus() = 00000000 win.c:3182: Test failed: GetFocus() = 00000000 win.c:3185: Test failed: GetFocus() = 00000000 win.c:3188: Test failed: GetActiveWindow() = 00030296 win.c:3192: Test failed: GetFocus() = 00000000 win.c:3195: Test failed: GetFocus() = 00000000 win.c:4075: Test failed: hwnd 00020174/001402CE message 0737 win.c:4080: Test failed: hwnd 001402CE/001402CE message 0202 win.c:4085: Test failed: hwnd 001402CE/001402CE message 0203 win.c:4089: Test failed: message 0202 available
=== w10pro64_2scr (32 bit report) ===
user32: win.c:9664: Test failed: Timed out waiting for the child process
=== w10pro64_ja (32 bit report) ===
user32: win.c:10160: Test failed: pos = 00fa00fa win.c:10164: Test failed: pos = 00fa00fa win.c:10168: Test failed: pos = 00fa00fa
=== w1064v1809 (64 bit report) ===
user32: win.c:3164: Test failed: GetActiveWindow() = 000000000003005A win.c:3167: Test failed: GetFocus() = 0000000000000000 win.c:3179: Test failed: GetFocus() = 0000000000000000 win.c:3182: Test failed: GetFocus() = 0000000000000000 win.c:3185: Test failed: GetFocus() = 0000000000000000 win.c:3188: Test failed: GetActiveWindow() = 000000000003005A win.c:3192: Test failed: GetFocus() = 0000000000000000 win.c:3195: Test failed: GetFocus() = 0000000000000000 win.c:4075: Test failed: hwnd 0000000000020174/0000000000150292 message 0737 win.c:4080: Test failed: hwnd 0000000000150292/0000000000150292 message 0202 win.c:4085: Test failed: hwnd 0000000000150292/0000000000150292 message 0203 win.c:4089: Test failed: message 0202 available
=== w10pro64_ja (64 bit report) ===
user32: win.c:9649: Test failed: didn't get start_event win.c:9664: Test failed: Timed out waiting for the child process win.c:9590: Test failed: transparent window didn't get WM_NCHITTEST message win.c:9591: Test failed: button under static window didn't get WM_LBUTTONUP