2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: Test for TrackMouseEvent
5 * PROGRAMMERS: Giannis Adamopoulos
13 #include <undocuser.h>
15 HWND hWnd1
, hWnd2
, hWnd3
;
16 HHOOK hMouseHookLL
, hMouseHook
;
17 int ignore_timer
= 0, ignore_mouse
= 0, ignore_mousell
= 0;
19 static int get_iwnd(HWND hWnd
)
21 if(hWnd
== hWnd1
) return 1;
22 else if(hWnd
== hWnd2
) return 2;
23 else if(hWnd
== hWnd3
) return 3;
27 LRESULT CALLBACK
TmeTestProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
29 int iwnd
= get_iwnd(hWnd
);
31 if(message
== WM_PAINT
)
34 BeginPaint(hWnd
, &ps
);
35 Rectangle(ps
.hdc
, ps
.rcPaint
.left
, ps
.rcPaint
.top
, ps
.rcPaint
.right
, ps
.rcPaint
.bottom
);
39 if(message
> WM_USER
|| !iwnd
|| IsDWmMsg(message
) || IseKeyMsg(message
))
40 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
44 case WM_IME_SETCONTEXT
:
50 ok(0, "Got unexpected WM_SYSTIMER in the winproc. wParam=%d\n", wParam
);
53 RECOND_MESSAGE(iwnd
, message
, SENT
, 0,0);
55 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
58 static LRESULT CALLBACK
MouseLLHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
61 RECOND_MESSAGE(0, WH_MOUSE_LL
, HOOK
, wParam
, 0);
62 ret
= CallNextHookEx(hMouseHookLL
, nCode
, wParam
, lParam
);
68 static LRESULT CALLBACK
MouseHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
70 MOUSEHOOKSTRUCT
*hs
= (MOUSEHOOKSTRUCT
*) lParam
;
72 RECOND_MESSAGE(get_iwnd(hs
->hwnd
), WH_MOUSE
, HOOK
, wParam
, hs
->wHitTestCode
);
73 ret
= CallNextHookEx(hMouseHook
, nCode
, wParam
, lParam
);
79 static void FlushMessages()
83 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
))
85 int iwnd
= get_iwnd(msg
.hwnd
);
88 if(msg
.message
== WM_SYSTIMER
)
90 RECOND_MESSAGE(iwnd
, msg
.message
, POST
,msg
.wParam
,0);
94 else if(!(msg
.message
> WM_USER
|| !iwnd
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
95 RECOND_MESSAGE(iwnd
, msg
.message
, POST
,0,0);
97 DispatchMessageA( &msg
);
101 #define FLUSH_MESSAGES(expected, notexpected) \
102 { EXPECT_QUEUE_STATUS(expected, notexpected);\
106 static void create_test_windows()
108 hMouseHookLL
= SetWindowsHookExW(WH_MOUSE_LL
, MouseLLHookProc
, GetModuleHandleW( NULL
), 0);
109 hMouseHook
= SetWindowsHookExW(WH_MOUSE
, MouseHookProc
, GetModuleHandleW( NULL
), GetCurrentThreadId());
110 ok(hMouseHook
!=NULL
,"failed to set hook\n");
111 ok(hMouseHookLL
!=NULL
,"failed to set hook\n");
113 RegisterSimpleClass(TmeTestProc
, L
"testClass");
115 hWnd1
= CreateWindowW(L
"testClass", L
"test", WS_OVERLAPPEDWINDOW
,
116 100, 100, 500, 500, NULL
, NULL
, 0, NULL
);
117 hWnd2
= CreateWindowW(L
"testClass", L
"test", WS_CHILD
,
118 50, 50, 200, 200, hWnd1
, NULL
, 0, NULL
);
119 hWnd3
= CreateWindowW(L
"testClass", L
"test", WS_CHILD
,
120 150, 150, 200, 200, hWnd1
, NULL
, 0, NULL
);
122 ShowWindow(hWnd1
, SW_SHOW
);
124 ShowWindow(hWnd2
, SW_SHOW
);
126 ShowWindow(hWnd3
, SW_SHOWNORMAL
);
128 //SetWindowPos (hWnd3, HWND_TOP, 0,0,0,0, SWP_NOMOVE|SWP_NOREDRAW);
131 static void destroy_test_window()
133 DestroyWindow(hWnd1
);
134 UnregisterClassW(L
"testClass", 0);
135 UnhookWindowsHookEx(hMouseHookLL
);
136 UnhookWindowsHookEx(hMouseHook
);
139 static void TmeStartTracking(HWND hwnd
, DWORD Flags
)
142 tme
.cbSize
= sizeof(tme
);
144 tme
.hwndTrack
= hwnd
;
146 if(!TrackMouseEvent(&tme
))
152 DWORD
TmeQuery(HWND hwnd
)
155 tme
.cbSize
= sizeof(tme
);
156 tme
.dwFlags
= TME_QUERY
|TME_HOVER
|TME_LEAVE
;
157 tme
.hwndTrack
= hwnd
;
158 TrackMouseEvent(&tme
);
162 #define EXPECT_TME_FLAGS(hWnd, expected) \
163 { DWORD flags = TmeQuery(hWnd); \
164 ok(flags == (expected),"wrong tme flags. expected %li, and got %li\n", (DWORD)(expected), flags); \
167 #define MOVE_CURSOR(x,y) mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE , \
168 x*(65535/GetSystemMetrics(SM_CXVIRTUALSCREEN)), \
169 y*(65535/GetSystemMetrics(SM_CYVIRTUALSCREEN)) , 0,0);
171 /* the mouse moves over hwnd2 */
172 MSG_ENTRY mousemove2_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
174 {2, WH_MOUSE
,HOOK
, WM_MOUSEMOVE
, HTCLIENT
},
177 {2, WM_MOUSEMOVE
, POST
},
180 /* the mouse hovers hwnd2 */
181 MSG_ENTRY mousehover2_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
183 {2, WH_MOUSE
,HOOK
, WM_MOUSEMOVE
, HTCLIENT
},
186 {2, WM_MOUSEMOVE
, POST
},
187 {2, WM_SYSTIMER
, POST
, ID_TME_TIMER
},
188 {2, WM_MOUSEHOVER
, POST
},
191 /* the mouse leaves hwnd2 and moves to hwnd1 */
192 MSG_ENTRY mouseleave2to1_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
194 {1, WH_MOUSE
,HOOK
, WM_MOUSEMOVE
, HTCLIENT
},
196 {1, WM_MOUSEMOVE
, POST
},
197 {2, WM_MOUSELEAVE
, POST
},
200 /* the mouse leaves hwnd2 and moves to hwnd3 */
201 MSG_ENTRY mouseleave2to3_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
203 {3, WH_MOUSE
,HOOK
, WM_MOUSEMOVE
, HTCLIENT
},
206 {3, WM_MOUSEMOVE
, POST
},
207 {2, WM_MOUSELEAVE
, POST
},
210 /* the mouse hovers hwnd3 */
211 MSG_ENTRY mousehover3_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
213 {3, WH_MOUSE
,HOOK
, WM_MOUSEMOVE
, HTCLIENT
},
216 {3, WM_MOUSEMOVE
, POST
},
217 {3, WM_SYSTIMER
, POST
, ID_TME_TIMER
},
218 {3, WM_MOUSEHOVER
, POST
},
221 /* the mouse hovers hwnd3 without moving */
222 MSG_ENTRY mousehover3_nomove_chain
[]={{3, WM_SYSTIMER
, POST
, ID_TME_TIMER
},
223 {3, WM_MOUSEHOVER
, POST
},
226 /* the mouse hovers hwnd3 and the timer is not dispatched */
227 MSG_ENTRY mousehover3_droptimer_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
229 {3, WH_MOUSE
,HOOK
, WM_MOUSEMOVE
, HTCLIENT
},
232 {3, WM_MOUSEMOVE
, POST
},
233 {3, WM_SYSTIMER
, POST
, ID_TME_TIMER
},
236 /* the mouse hovers hwnd3 and mouse message is dropped by WH_MOUSE */
237 MSG_ENTRY mousehover3_dropmouse_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
239 {3, WH_MOUSE
,HOOK
, WM_MOUSEMOVE
, HTCLIENT
},
240 {3, WM_SYSTIMER
, POST
, ID_TME_TIMER
},
241 {3, WM_MOUSEHOVER
, POST
},
244 /* the mouse hovers hwnd3 and mouse message is dropped by WH_MOUSE_LL */
245 MSG_ENTRY mousehover3_dropmousell_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
246 {3, WM_SYSTIMER
, POST
, ID_TME_TIMER
},
247 {3, WM_MOUSEHOVER
, POST
},
250 /* the mouse leaves hwnd3 and moves to hwnd2 and mouse message is dropped by WH_MOUSE */
251 MSG_ENTRY mouseleave3to2_dropmouse_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
253 {2, WH_MOUSE
,HOOK
, WM_MOUSEMOVE
, HTCLIENT
},
256 /* the mouse leaves hwnd3 and moves to hwnd2 and mouse message is dropped by WH_MOUSE_LL */
257 MSG_ENTRY mouseleave3to2_dropmousell_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
260 /* after WH_MOUSE drops WM_MOUSEMOVE, WM_MOUSELEAVE is still in the queue */
261 MSG_ENTRY mouseleave3_remainging_chain
[]={{3, WM_MOUSELEAVE
, POST
},
264 void Test_TrackMouseEvent()
267 create_test_windows();
271 /* the mouse moves over hwnd2 */
272 MOVE_CURSOR(220,220);
274 COMPARE_CACHE(mousemove2_chain
);
275 EXPECT_TME_FLAGS(hWnd2
, 0);
277 /* Begin tracking mouse events for hWnd2 */
278 TmeStartTracking(hWnd2
, TME_HOVER
|TME_LEAVE
);
279 EXPECT_TME_FLAGS(hWnd2
, TME_HOVER
|TME_LEAVE
);
281 COMPARE_CACHE(empty_chain
);
283 /* the mouse hovers hwnd2 */
284 MOVE_CURSOR(221, 221);
286 EXPECT_TME_FLAGS(hWnd2
, TME_HOVER
|TME_LEAVE
);
287 FLUSH_MESSAGES(QS_TIMER
|QS_MOUSEMOVE
, 0);
288 EXPECT_TME_FLAGS(hWnd2
, TME_LEAVE
);
289 COMPARE_CACHE(mousehover2_chain
);
291 /* the mouse leaves hwnd2 and moves to hwnd1 */
292 MOVE_CURSOR(150, 150);
293 EXPECT_TME_FLAGS(hWnd2
, TME_LEAVE
);
294 FLUSH_MESSAGES(QS_MOUSEMOVE
,QS_TIMER
);
295 EXPECT_TME_FLAGS(hWnd2
, 0);
296 COMPARE_CACHE(mouseleave2to1_chain
);
299 COMPARE_CACHE(empty_chain
);
301 /* the mouse moves over hwnd2 */
302 MOVE_CURSOR(220,220);
303 FLUSH_MESSAGES(QS_MOUSEMOVE
, QS_TIMER
);
304 COMPARE_CACHE(mousemove2_chain
);
305 EXPECT_TME_FLAGS(hWnd2
, 0);
308 COMPARE_CACHE(empty_chain
);
310 /* Begin tracking mouse events for hWnd2 */
311 TmeStartTracking(hWnd2
, TME_HOVER
|TME_LEAVE
);
312 TmeStartTracking(hWnd2
, TME_HOVER
|TME_LEAVE
);
313 TmeStartTracking(hWnd2
, TME_HOVER
|TME_LEAVE
);
314 TmeStartTracking(hWnd2
, TME_HOVER
|TME_LEAVE
);
315 FLUSH_MESSAGES(0, QS_TIMER
|QS_MOUSEMOVE
);
316 COMPARE_CACHE(empty_chain
);
317 EXPECT_TME_FLAGS(hWnd2
, TME_HOVER
|TME_LEAVE
);
319 /* the mouse moves from hwnd2 to the intersection of hwnd2 and hwnd3 */
320 MOVE_CURSOR(300,300);
321 FLUSH_MESSAGES(QS_MOUSEMOVE
, QS_TIMER
);
322 EXPECT_TME_FLAGS(hWnd2
, TME_HOVER
|TME_LEAVE
);
323 COMPARE_CACHE(mousemove2_chain
);
326 COMPARE_CACHE(empty_chain
);
328 /* the mouse moves from hwnd2 to hwnd3 */
329 MOVE_CURSOR(400,400);
330 FLUSH_MESSAGES(QS_MOUSEMOVE
, QS_TIMER
);
331 EXPECT_TME_FLAGS(hWnd2
, 0);
332 COMPARE_CACHE(mouseleave2to3_chain
);
335 COMPARE_CACHE(empty_chain
);
337 /* Begin tracking mouse events for hWnd3 */
338 TmeStartTracking(hWnd3
, TME_HOVER
|TME_LEAVE
);
339 FLUSH_MESSAGES(0, QS_TIMER
|QS_MOUSEMOVE
);
340 COMPARE_CACHE(empty_chain
);
341 EXPECT_TME_FLAGS(hWnd2
, TME_HOVER
|TME_LEAVE
);
343 /* the mouse hovers hwnd3 */
344 MOVE_CURSOR(401,401);
346 EXPECT_TME_FLAGS(hWnd3
, TME_HOVER
|TME_LEAVE
);
347 FLUSH_MESSAGES(QS_TIMER
|QS_MOUSEMOVE
, 0);
348 EXPECT_TME_FLAGS(hWnd3
, TME_LEAVE
);
349 COMPARE_CACHE(mousehover3_chain
);
352 COMPARE_CACHE(empty_chain
);
354 /* Begin tracking mouse events for hWnd3 */
355 TmeStartTracking(hWnd3
, TME_HOVER
);
356 FLUSH_MESSAGES(0, QS_TIMER
|QS_MOUSEMOVE
);
357 COMPARE_CACHE(empty_chain
);
358 EXPECT_TME_FLAGS(hWnd3
, TME_HOVER
|TME_LEAVE
);
360 /* make sure that the timer will fire before the mouse moves */
363 COMPARE_CACHE(mousehover3_nomove_chain
);
364 EXPECT_TME_FLAGS(hWnd3
, TME_LEAVE
);
368 COMPARE_CACHE(empty_chain
);
370 /* the mouse hovers hwnd3 and the timer is not dispatched*/
371 TmeStartTracking(hWnd3
, TME_HOVER
);
373 MOVE_CURSOR(400,400);
375 EXPECT_TME_FLAGS(hWnd3
, TME_HOVER
|TME_LEAVE
);
376 FLUSH_MESSAGES(QS_TIMER
|QS_MOUSEMOVE
, 0); /* the loop drops WM_SYSTIMER */
377 EXPECT_TME_FLAGS(hWnd3
, TME_HOVER
|TME_LEAVE
); /* TME_HOVER is still active */
378 COMPARE_CACHE(mousehover3_droptimer_chain
); /* we get no WM_MOUSEHOVER */
379 ignore_timer
= FALSE
;
381 /* the mouse hovers hwnd3 and mouse message is dropped by WH_MOUSE_LL */
382 ignore_mousell
= TRUE
;
383 MOVE_CURSOR(402,402);
385 EXPECT_TME_FLAGS(hWnd3
, TME_HOVER
|TME_LEAVE
);
386 FLUSH_MESSAGES(QS_TIMER
, QS_MOUSEMOVE
); /* WH_MOUSE_LL drops WM_MOUSEMOVE */
387 EXPECT_TME_FLAGS(hWnd3
, TME_LEAVE
);
388 COMPARE_CACHE(mousehover3_dropmousell_chain
); /* we get WM_MOUSEHOVER normaly */
389 ignore_mousell
= FALSE
;
392 COMPARE_CACHE(empty_chain
);
394 /* the mouse hovers hwnd3 and mouse message is dropped by WH_MOUSE */
396 TmeStartTracking(hWnd3
, TME_HOVER
);
397 MOVE_CURSOR(401,401);
399 EXPECT_TME_FLAGS(hWnd3
, TME_HOVER
|TME_LEAVE
);
400 FLUSH_MESSAGES(QS_TIMER
|QS_MOUSEMOVE
, 0); /* WH_MOUSE drops WM_MOUSEMOVE */
401 EXPECT_TME_FLAGS(hWnd3
, TME_LEAVE
);
402 COMPARE_CACHE(mousehover3_dropmouse_chain
); /* we get WM_MOUSEHOVER normaly */
403 ignore_mouse
= FALSE
;
406 COMPARE_CACHE(empty_chain
);
408 /* the mouse leaves hwnd3 and moves to hwnd2 and mouse message is dropped by WH_MOUSE_LL */
409 ignore_mousell
= TRUE
;
410 TmeStartTracking(hWnd3
, TME_LEAVE
);
411 MOVE_CURSOR(220,220);
412 FLUSH_MESSAGES(0, QS_MOUSEMOVE
|QS_TIMER
); /* WH_MOUSE drops WM_MOUSEMOVE */
413 EXPECT_TME_FLAGS(hWnd3
, TME_LEAVE
); /* all flags are removed */
414 COMPARE_CACHE(mouseleave3to2_dropmousell_chain
); /* we get no WM_MOUSELEAVE */
415 ignore_mousell
= FALSE
;
418 COMPARE_CACHE(empty_chain
);
420 /* the mouse leaves hwnd3 and moves to hwnd2 and mouse message is dropped by WH_MOUSE */
422 MOVE_CURSOR(220,220);
423 FLUSH_MESSAGES(QS_MOUSEMOVE
, QS_TIMER
); /* WH_MOUSE drops WM_MOUSEMOVE */
424 EXPECT_TME_FLAGS(hWnd3
, 0); /* all flags are removed */
425 COMPARE_CACHE(mouseleave3to2_dropmouse_chain
); /* we get no WM_MOUSELEAVE */
426 ignore_mouse
= FALSE
;
428 /* after WH_MOUSE drops WM_MOUSEMOVE, WM_MOUSELEAVE is still in the queue */
429 FLUSH_MESSAGES(QS_POSTMESSAGE
, QS_TIMER
|QS_MOUSEMOVE
);
430 COMPARE_CACHE(mouseleave3_remainging_chain
);
433 COMPARE_CACHE(empty_chain
);
435 destroy_test_window();
438 START_TEST(TrackMouseEvent
)
440 Test_TrackMouseEvent();