These were in the staging user32-Mouse_Message_Hwnd series, I rewrote them to use the new test helpers. There were more tests with DC regions but I don't think they really belong to the input tests. The fixes are also not completely correct (they don't pass some tests now) so probably would need some investigation.
From: Rémi Bernon rbernon@codeweavers.com
Wine sends spurious mouse move messages in some cases, let's ignore them as it makes tests unreliable otherwise. --- dlls/user32/tests/input.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index b7dc5aac3b1..9eafde917af 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -302,6 +302,9 @@ static void ok_seq_( const char *file, int line, const struct user_call *expecte current_sequence_len = 0; }
+static BOOL append_message_hwnd; +static BOOL (*p_accept_message)( UINT msg ); + static void append_ll_hook_kbd( UINT msg, const KBDLLHOOKSTRUCT *info ) { struct user_call call = @@ -312,9 +315,12 @@ static void append_ll_hook_kbd( UINT msg, const KBDLLHOOKSTRUCT *info ) .flags = info->flags, .extra = info->dwExtraInfo } }; - ULONG index = InterlockedIncrement( ¤t_sequence_len ) - 1; - ok( index < ARRAY_SIZE(current_sequence), "got %lu calls\n", index ); - current_sequence[index] = call; + if (!p_accept_message || p_accept_message( msg )) + { + ULONG index = InterlockedIncrement( ¤t_sequence_len ) - 1; + ok( index < ARRAY_SIZE(current_sequence), "got %lu calls\n", index ); + current_sequence[index] = call; + } }
static void append_ll_hook_ms( UINT msg, const MSLLHOOKSTRUCT *info ) @@ -327,13 +333,14 @@ static void append_ll_hook_ms( UINT msg, const MSLLHOOKSTRUCT *info ) .time = info->time, .extra = info->dwExtraInfo } }; - ULONG index = InterlockedIncrement( ¤t_sequence_len ) - 1; - ok( index < ARRAY_SIZE(current_sequence), "got %lu calls\n", index ); - current_sequence[index] = call; + if (!p_accept_message || p_accept_message( msg )) + { + ULONG index = InterlockedIncrement( ¤t_sequence_len ) - 1; + ok( index < ARRAY_SIZE(current_sequence), "got %lu calls\n", index ); + current_sequence[index] = call; + } }
-static BOOL append_message_hwnd; -static BOOL (*p_accept_message)( UINT msg ); static void append_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { if (!p_accept_message || p_accept_message( msg )) @@ -3536,13 +3543,6 @@ static void test_SendInput_mouse_messages(void) WIN_MSG(WM_LBUTTONDOWN, (HWND)-1/*hwnd*/, 0x1, MAKELONG(50, 50), .todo = TRUE), {0}, }; - struct user_call button_down_hwnd_todo_attached[] = - { - MS_HOOK(WM_LBUTTONDOWN, 50, 50), - WIN_MSG(WM_LBUTTONDOWN, (HWND)-1/*hwnd*/, 0x1, MAKELONG(50, 50), .todo = TRUE), - {.todo = TRUE /* spurious message on Wine */}, - {0}, - }; struct user_call button_up_hwnd[] = { MS_HOOK(WM_LBUTTONUP, 50, 50), @@ -3793,8 +3793,8 @@ static void test_SendInput_mouse_messages(void)
mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 ); wait_messages( 5, FALSE ); - button_down_hwnd_todo_attached[1].message.hwnd = hwnd; - ok_seq( button_down_hwnd_todo_attached ); + button_down_hwnd[1].message.hwnd = hwnd; + ok_seq( button_down_hwnd ); mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 ); wait_messages( 5, FALSE ); button_up_hwnd[1].message.hwnd = hwnd;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/tests/input.c | 114 +++++++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 9eafde917af..736172cb504 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -52,6 +52,7 @@ #include "winbase.h" #include "wingdi.h" #include "winuser.h" +#include "wingdi.h" #include "winnls.h" #include "winreg.h" #include "ddk/hidsdi.h" @@ -3462,6 +3463,28 @@ static LRESULT CALLBACK mouse_move_wndproc(HWND hwnd, UINT msg, WPARAM wparam, L return DefWindowProcW(hwnd, msg, wparam, lparam); }
+static LRESULT CALLBACK mouse_layered_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + append_message( hwnd, msg, wparam, lparam ); + + if (msg == WM_PAINT) + { + HBRUSH brush = CreateSolidBrush( RGB(50, 100, 255) ); + PAINTSTRUCT paint; + RECT client_rect; + + HDC hdc = BeginPaint( hwnd, &paint ); + GetClientRect( hwnd, &client_rect ); + FillRect( hdc, &client_rect, brush ); + EndPaint( hwnd, &paint ); + + DeleteObject( brush ); + return 0; + } + + return DefWindowProcW( hwnd, msg, wparam, lparam ); +} + struct send_input_mouse_test { BOOL set_cursor_pos; @@ -3541,6 +3564,7 @@ static void test_SendInput_mouse_messages(void) { MS_HOOK(WM_LBUTTONDOWN, 50, 50), WIN_MSG(WM_LBUTTONDOWN, (HWND)-1/*hwnd*/, 0x1, MAKELONG(50, 50), .todo = TRUE), + {0/* placeholder for Wine spurious messages */}, {0}, }; struct user_call button_up_hwnd[] = @@ -3553,6 +3577,7 @@ static void test_SendInput_mouse_messages(void) { MS_HOOK(WM_LBUTTONUP, 50, 50), WIN_MSG(WM_LBUTTONUP, (HWND)-1/*hwnd*/, 0, MAKELONG(50, 50), .todo = TRUE), + {0/* placeholder for Wine spurious messages */}, {0}, }; struct user_call button_down_no_message[] = @@ -3571,10 +3596,28 @@ static void test_SendInput_mouse_messages(void) #undef MS_HOOK static const POINT expect_60x50 = {60, 50}, expect_50x50 = {50, 50};
+ static const struct layered_test + { + UINT color; + UINT alpha; + UINT flags; + BOOL expect_click; + } + layered_tests[] = + { + {.flags = LWA_ALPHA, .expect_click = FALSE}, + {.alpha = 1, .flags = LWA_ALPHA, .expect_click = TRUE}, + {.color = RGB(0, 255, 0), .flags = LWA_COLORKEY, .expect_click = TRUE}, + {.color = RGB(50, 100, 255), .flags = LWA_COLORKEY, .expect_click = TRUE}, + {.color = RGB(0, 255, 0), .flags = LWA_COLORKEY | LWA_ALPHA, .expect_click = FALSE}, + {.color = RGB(0, 255, 0), .alpha = 1, .flags = LWA_COLORKEY | LWA_ALPHA, .expect_click = TRUE}, + {.color = RGB(50, 100, 255), .alpha = 1, .flags = LWA_COLORKEY | LWA_ALPHA, .expect_click = TRUE}, + }; + struct create_transparent_window_params params = {0}; ULONG_PTR old_proc, old_other_proc; RECT clip_rect = {55, 55, 55, 55}; - UINT dblclk_time; + UINT dblclk_time, i; HWND hwnd, other; DWORD thread_id; HANDLE thread; @@ -3862,6 +3905,75 @@ static void test_SendInput_mouse_messages(void) SetCapture( 0 );
+ + /* click through layered window with alpha channel / color key */ + + for (i = 0; i < ARRAY_SIZE(layered_tests); i++) + { + const struct layered_test *test = layered_tests + i; + BOOL ret; + + winetest_push_context( "layered %u", i ); + + other = CreateWindowW( L"static", NULL, WS_VISIBLE | WS_POPUP, 0, 0, 100, 100, NULL, NULL, NULL, NULL ); + ok_ne( NULL, other, HWND, "%p" ); + old_other_proc = SetWindowLongPtrW( other, GWLP_WNDPROC, (LONG_PTR)mouse_layered_wndproc ); + ok_ne( 0, old_other_proc, LONG_PTR, "%#Ix" ); + wait_messages( 100, FALSE ); + + + SetWindowLongW( other, GWL_EXSTYLE, GetWindowLongW( other, GWL_EXSTYLE ) | WS_EX_LAYERED ); + ret = SetLayeredWindowAttributes( other, test->color, test->alpha, test->flags ); + if (broken(!ret)) /* broken on Win7 probably because of the separate desktop */ + { + win_skip("Skipping broken SetLayeredWindowAttributes tests\n"); + DestroyWindow( other ); + break; + } + + ok_ret( 1, RedrawWindow( other, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN ) ); + wait_messages( 5, FALSE ); + current_sequence_len = 0; + + mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 ); + wait_messages( 5, FALSE ); + button_down_hwnd_todo[1].message.hwnd = test->expect_click ? other : hwnd; + button_down_hwnd_todo[1].todo = !test->expect_click; + button_down_hwnd_todo[2].todo = !test->alpha && (test->flags & LWA_ALPHA); + ok_seq( button_down_hwnd_todo ); + mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 ); + wait_messages( 5, FALSE ); + button_up_hwnd_todo[1].message.hwnd = test->expect_click ? other : hwnd; + button_up_hwnd_todo[1].todo = !test->expect_click; + button_up_hwnd_todo[2].todo = !test->alpha && (test->flags & LWA_ALPHA); + ok_seq( button_up_hwnd_todo ); + + + /* removing the attribute isn't enough to get mouse input again? */ + + SetWindowLongW( other, GWL_EXSTYLE, GetWindowLongW( other, GWL_EXSTYLE ) & ~WS_EX_LAYERED ); + ok_ret( 1, RedrawWindow( other, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN ) ); + wait_messages( 5, FALSE ); + + mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 ); + wait_messages( 5, FALSE ); + button_down_hwnd_todo[1].message.hwnd = test->expect_click ? other : hwnd; + button_down_hwnd_todo[1].todo = !test->expect_click; + button_down_hwnd_todo[2].todo = !test->alpha && (test->flags & LWA_ALPHA); + ok_seq( button_down_hwnd_todo ); + mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 ); + wait_messages( 5, FALSE ); + button_up_hwnd_todo[1].message.hwnd = test->expect_click ? other : hwnd; + button_up_hwnd_todo[1].todo = !test->expect_click; + button_up_hwnd_todo[2].todo = !test->alpha && (test->flags & LWA_ALPHA); + ok_seq( button_up_hwnd_todo ); + + ok_ret( 1, DestroyWindow( other ) ); + + winetest_pop_context(); + } + + /* warm up test case by moving cursor and window a bit first */ ok_ret( 1, SetCursorPos( 60, 50 ) ); ok_ret( 1, SetWindowPos( hwnd, NULL, 10, 0, 0, 0, SWP_NOSIZE ) );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/tests/input.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 736172cb504..02200fb37aa 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -3622,6 +3622,8 @@ static void test_SendInput_mouse_messages(void) DWORD thread_id; HANDLE thread; HHOOK hook, hook_setpos, hook_getpos; + HRGN hregion; + RECT region; POINT pt;
params.start_event = CreateEventA( NULL, FALSE, FALSE, NULL ); @@ -3921,6 +3923,8 @@ static void test_SendInput_mouse_messages(void) ok_ne( 0, old_other_proc, LONG_PTR, "%#Ix" ); wait_messages( 100, FALSE );
+ ok_ret( ERROR, GetWindowRgnBox( other, ®ion ) ); +
SetWindowLongW( other, GWL_EXSTYLE, GetWindowLongW( other, GWL_EXSTYLE ) | WS_EX_LAYERED ); ret = SetLayeredWindowAttributes( other, test->color, test->alpha, test->flags ); @@ -3974,6 +3978,35 @@ static void test_SendInput_mouse_messages(void) }
+ /* click on top-level window with SetWindowRgn called */ + + other = CreateWindowW( L"static", NULL, WS_VISIBLE | WS_POPUP, 0, 0, 100, 100, NULL, NULL, NULL, NULL ); + ok_ne( NULL, hwnd, HWND, "%p" ); + wait_messages( 100, FALSE ); + current_sequence_len = 0; + + old_other_proc = SetWindowLongPtrW( other, GWLP_WNDPROC, (LONG_PTR)append_message_wndproc ); + ok_ne( 0, old_other_proc, LONG_PTR, "%#Ix" ); + + hregion = CreateRectRgn( 0, 0, 10, 10 ); + ok_ne( NULL, hregion, HRGN, "%p" ); + ok_ret( 1, SetWindowRgn( other, hregion, TRUE ) ); + DeleteObject( hregion ); + ok_ret( SIMPLEREGION, GetWindowRgnBox( other, ®ion ) ); + + mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 ); + wait_messages( 5, FALSE ); + button_down_hwnd[1].message.hwnd = hwnd; + ok_seq( button_down_hwnd ); + mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 ); + wait_messages( 5, FALSE ); + button_up_hwnd[1].message.hwnd = hwnd; + ok_seq( button_up_hwnd ); + + ok_ret( 1, DestroyWindow( other ) ); + wait_messages( 0, FALSE ); + + /* warm up test case by moving cursor and window a bit first */ ok_ret( 1, SetCursorPos( 60, 50 ) ); ok_ret( 1, SetWindowPos( hwnd, NULL, 10, 0, 0, 0, SWP_NOSIZE ) );
Test failures are the usual suspects, unrelated.
Thanks, this is greatly appreciated!