user32/tests: Add mouse SendInput tests.
This commit is contained in:
parent
80cbd276e0
commit
65b09537b3
|
@ -1643,6 +1643,258 @@ static void test_key_names(void)
|
|||
ok( bufferW[0] == 0xcccc, "wrong string %s\n", wine_dbgstr_w(bufferW) );
|
||||
}
|
||||
|
||||
static void simulate_click(BOOL left, int x, int y)
|
||||
{
|
||||
INPUT input[2];
|
||||
UINT events_no;
|
||||
|
||||
SetCursorPos(x, y);
|
||||
memset(input, 0, sizeof(input));
|
||||
input[0].type = INPUT_MOUSE;
|
||||
U(input[0]).mi.dx = x;
|
||||
U(input[0]).mi.dy = y;
|
||||
U(input[0]).mi.dwFlags = left ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN;
|
||||
input[1].type = INPUT_MOUSE;
|
||||
U(input[1]).mi.dx = x;
|
||||
U(input[1]).mi.dy = y;
|
||||
U(input[1]).mi.dwFlags = left ? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP;
|
||||
events_no = SendInput(2, input, sizeof(input[0]));
|
||||
ok(events_no == 2, "SendInput returned %d\n", events_no);
|
||||
}
|
||||
|
||||
static BOOL wait_for_message( MSG *msg )
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ret = PeekMessageA(msg, 0, 0, 0, PM_REMOVE);
|
||||
if (ret)
|
||||
{
|
||||
if (msg->message == WM_PAINT) DispatchMessageA(msg);
|
||||
else break;
|
||||
}
|
||||
else if (MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT) == WAIT_TIMEOUT) break;
|
||||
}
|
||||
if (!ret) msg->message = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static WNDPROC def_static_proc;
|
||||
static DWORD hittest_no;
|
||||
static LRESULT WINAPI static_hook_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
|
||||
{
|
||||
if (msg == WM_NCHITTEST)
|
||||
{
|
||||
/* break infinite hittest loop */
|
||||
if(hittest_no > 50) return HTCLIENT;
|
||||
hittest_no++;
|
||||
}
|
||||
|
||||
return def_static_proc(hwnd, msg, wp, lp);
|
||||
}
|
||||
|
||||
struct thread_data
|
||||
{
|
||||
HANDLE start_event;
|
||||
HANDLE end_event;
|
||||
HWND win;
|
||||
};
|
||||
|
||||
static DWORD WINAPI create_static_win(void *arg)
|
||||
{
|
||||
struct thread_data *thread_data = arg;
|
||||
HWND win;
|
||||
|
||||
win = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP,
|
||||
100, 100, 100, 100, 0, NULL, NULL, NULL);
|
||||
ok(win != 0, "CreateWindow failed\n");
|
||||
def_static_proc = (void*)SetWindowLongPtrA(win,
|
||||
GWLP_WNDPROC, (LONG_PTR)static_hook_proc);
|
||||
thread_data->win = win;
|
||||
|
||||
SetEvent(thread_data->start_event);
|
||||
wait_for_event(thread_data->end_event, 5000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_Input_mouse(void)
|
||||
{
|
||||
BOOL got_button_down, got_button_up;
|
||||
HWND hwnd, button_win, static_win;
|
||||
struct thread_data thread_data;
|
||||
HANDLE thread;
|
||||
DWORD thread_id;
|
||||
POINT pt;
|
||||
MSG msg;
|
||||
|
||||
button_win = CreateWindowA("button", "button", WS_VISIBLE | WS_POPUP,
|
||||
100, 100, 100, 100, 0, NULL, NULL, NULL);
|
||||
ok(button_win != 0, "CreateWindow failed\n");
|
||||
|
||||
pt.x = pt.y = 150;
|
||||
hwnd = WindowFromPoint(pt);
|
||||
if (hwnd != button_win)
|
||||
{
|
||||
skip("there's another window covering test window\n");
|
||||
DestroyWindow(button_win);
|
||||
return;
|
||||
}
|
||||
|
||||
/* simple button click test */
|
||||
simulate_click(TRUE, 150, 150);
|
||||
got_button_down = got_button_up = FALSE;
|
||||
while (wait_for_message(&msg))
|
||||
{
|
||||
DispatchMessageA(&msg);
|
||||
|
||||
if (msg.message == WM_LBUTTONDOWN)
|
||||
{
|
||||
got_button_down = TRUE;
|
||||
}
|
||||
else if (msg.message == WM_LBUTTONUP)
|
||||
{
|
||||
got_button_up = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ok(got_button_down, "expected WM_LBUTTONDOWN message\n");
|
||||
ok(got_button_up, "expected WM_LBUTTONUP message\n");
|
||||
|
||||
/* click through HTTRANSPARENT child window */
|
||||
static_win = CreateWindowA("static", "static", WS_VISIBLE | WS_CHILD,
|
||||
0, 0, 100, 100, button_win, NULL, NULL, NULL);
|
||||
ok(static_win != 0, "CreateWindow failed\n");
|
||||
def_static_proc = (void*)SetWindowLongPtrA(static_win,
|
||||
GWLP_WNDPROC, (LONG_PTR)static_hook_proc);
|
||||
simulate_click(FALSE, 150, 150);
|
||||
hittest_no = 0;
|
||||
got_button_down = got_button_up = FALSE;
|
||||
while (wait_for_message(&msg))
|
||||
{
|
||||
DispatchMessageA(&msg);
|
||||
|
||||
if (msg.message == WM_RBUTTONDOWN)
|
||||
{
|
||||
ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
|
||||
got_button_down = TRUE;
|
||||
}
|
||||
else if (msg.message == WM_RBUTTONUP)
|
||||
{
|
||||
ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
|
||||
got_button_up = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ok(hittest_no && hittest_no<50, "expected WM_NCHITTEST message\n");
|
||||
todo_wine ok(got_button_down, "expected WM_RBUTTONDOWN message\n");
|
||||
todo_wine ok(got_button_up, "expected WM_RBUTTONUP message\n");
|
||||
DestroyWindow(static_win);
|
||||
|
||||
/* click through HTTRANSPARENT top-level window */
|
||||
static_win = CreateWindowA("static", "static", WS_VISIBLE | WS_POPUP,
|
||||
100, 100, 100, 100, 0, NULL, NULL, NULL);
|
||||
ok(static_win != 0, "CreateWindow failed\n");
|
||||
def_static_proc = (void*)SetWindowLongPtrA(static_win,
|
||||
GWLP_WNDPROC, (LONG_PTR)static_hook_proc);
|
||||
simulate_click(TRUE, 150, 150);
|
||||
hittest_no = 0;
|
||||
got_button_down = got_button_up = FALSE;
|
||||
while (wait_for_message(&msg))
|
||||
{
|
||||
DispatchMessageA(&msg);
|
||||
|
||||
if (msg.message == WM_LBUTTONDOWN)
|
||||
{
|
||||
ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
|
||||
got_button_down = TRUE;
|
||||
}
|
||||
else if (msg.message == WM_LBUTTONUP)
|
||||
{
|
||||
ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
|
||||
got_button_up = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ok(hittest_no && hittest_no<50, "expected WM_NCHITTEST message\n");
|
||||
todo_wine ok(got_button_down, "expected WM_LBUTTONDOWN message\n");
|
||||
todo_wine ok(got_button_up, "expected WM_LBUTTONUP message\n");
|
||||
DestroyWindow(static_win);
|
||||
|
||||
/* click on HTTRANSPARENT top-level window that belongs to other thread */
|
||||
thread_data.start_event = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||
ok(thread_data.start_event != NULL, "CreateEvent failed\n");
|
||||
thread_data.end_event = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||
ok(thread_data.end_event != NULL, "CreateEvent failed\n");
|
||||
thread = CreateThread(NULL, 0, create_static_win, &thread_data, 0, NULL);
|
||||
ok(thread != NULL, "CreateThread failed\n");
|
||||
hittest_no = 0;
|
||||
got_button_down = got_button_up = FALSE;
|
||||
WaitForSingleObject(thread_data.start_event, INFINITE);
|
||||
simulate_click(FALSE, 150, 150);
|
||||
while (wait_for_message(&msg))
|
||||
{
|
||||
DispatchMessageA(&msg);
|
||||
|
||||
if (msg.message == WM_RBUTTONDOWN)
|
||||
got_button_down = TRUE;
|
||||
else if (msg.message == WM_RBUTTONUP)
|
||||
got_button_up = TRUE;
|
||||
}
|
||||
SetEvent(thread_data.end_event);
|
||||
WaitForSingleObject(thread, INFINITE);
|
||||
ok(hittest_no && hittest_no<50, "expected WM_NCHITTEST message\n");
|
||||
ok(!got_button_down, "unexpected WM_RBUTTONDOWN message\n");
|
||||
ok(!got_button_up, "unexpected WM_RBUTTONUP message\n");
|
||||
|
||||
/* click on HTTRANSPARENT top-level window that belongs to ther thread,
|
||||
* threads input queues are attached */
|
||||
thread = CreateThread(NULL, 0, create_static_win, &thread_data, 0, &thread_id);
|
||||
ok(thread != NULL, "CreateThread failed\n");
|
||||
hittest_no = 0;
|
||||
got_button_down = got_button_up = FALSE;
|
||||
WaitForSingleObject(thread_data.start_event, INFINITE);
|
||||
ok(AttachThreadInput(thread_id, GetCurrentThreadId(), TRUE),
|
||||
"AttachThreadInput failed\n");
|
||||
while (wait_for_message(&msg)) DispatchMessageA(&msg);
|
||||
SetWindowPos(thread_data.win, button_win, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
|
||||
simulate_click(TRUE, 150, 150);
|
||||
while (wait_for_message(&msg))
|
||||
{
|
||||
DispatchMessageA(&msg);
|
||||
|
||||
if (msg.message == WM_LBUTTONDOWN)
|
||||
got_button_down = TRUE;
|
||||
else if (msg.message == WM_LBUTTONUP)
|
||||
got_button_up = TRUE;
|
||||
}
|
||||
SetEvent(thread_data.end_event);
|
||||
WaitForSingleObject(thread, INFINITE);
|
||||
todo_wine ok(hittest_no > 50, "expected loop with WM_NCHITTEST messages\n");
|
||||
ok(!got_button_down, "unexpected WM_LBUTTONDOWN message\n");
|
||||
ok(!got_button_up, "unexpected WM_LBUTTONUP message\n");
|
||||
|
||||
CloseHandle(thread_data.start_event);
|
||||
CloseHandle(thread_data.end_event);
|
||||
DestroyWindow(button_win);
|
||||
}
|
||||
|
||||
START_TEST(input)
|
||||
{
|
||||
init_function_pointers();
|
||||
|
@ -1652,6 +1904,7 @@ START_TEST(input)
|
|||
test_Input_blackbox();
|
||||
test_Input_whitebox();
|
||||
test_Input_unicode();
|
||||
test_Input_mouse();
|
||||
}
|
||||
else win_skip("SendInput is not available\n");
|
||||
|
||||
|
|
Loading…
Reference in New Issue