2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: Test for TrackMouseEvent
5 * PROGRAMMERS: Giannis Adamopoulos
10 HWND hWnd1
, hWnd2
, hWnd3
;
11 HHOOK hMouseHookLL
, hMouseHook
;
12 int ignore_timer
= 0, ignore_mouse
= 0, ignore_mousell
= 0;
14 static int get_iwnd(HWND hWnd
)
16 if(hWnd
== hWnd1
) return 1;
17 else if(hWnd
== hWnd2
) return 2;
18 else if(hWnd
== hWnd3
) return 3;
22 LRESULT CALLBACK
TmeTestProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
24 int iwnd
= get_iwnd(hWnd
);
26 if(message
== WM_PAINT
)
29 BeginPaint(hWnd
, &ps
);
30 Rectangle(ps
.hdc
, ps
.rcPaint
.left
, ps
.rcPaint
.top
, ps
.rcPaint
.right
, ps
.rcPaint
.bottom
);
34 if(message
> WM_USER
|| !iwnd
|| IsDWmMsg(message
) || IseKeyMsg(message
))
35 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
39 case WM_IME_SETCONTEXT
:
45 ok(0, "Got unexpected WM_SYSTIMER in the winproc. wParam=%d\n", wParam
);
48 RECORD_MESSAGE(iwnd
, message
, SENT
, 0,0);
50 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
53 static LRESULT CALLBACK
MouseLLHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
56 RECORD_MESSAGE(0, WH_MOUSE_LL
, HOOK
, wParam
, 0);
57 ret
= CallNextHookEx(hMouseHookLL
, nCode
, wParam
, lParam
);
63 static LRESULT CALLBACK
MouseHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
65 MOUSEHOOKSTRUCT
*hs
= (MOUSEHOOKSTRUCT
*) lParam
;
67 RECORD_MESSAGE(get_iwnd(hs
->hwnd
), WH_MOUSE
, HOOK
, wParam
, hs
->wHitTestCode
);
68 ret
= CallNextHookEx(hMouseHook
, nCode
, wParam
, lParam
);
74 static void FlushMessages()
78 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
))
80 int iwnd
= get_iwnd(msg
.hwnd
);
83 if(msg
.message
== WM_SYSTIMER
)
85 RECORD_MESSAGE(iwnd
, msg
.message
, POST
,msg
.wParam
,0);
89 else if(!(msg
.message
> WM_USER
|| !iwnd
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
90 RECORD_MESSAGE(iwnd
, msg
.message
, POST
,0,0);
92 DispatchMessageA( &msg
);
96 #define FLUSH_MESSAGES(expected, notexpected) \
97 { EXPECT_QUEUE_STATUS(expected, notexpected);\
101 static void create_test_windows()
103 hMouseHookLL
= SetWindowsHookExW(WH_MOUSE_LL
, MouseLLHookProc
, GetModuleHandleW( NULL
), 0);
104 hMouseHook
= SetWindowsHookExW(WH_MOUSE
, MouseHookProc
, GetModuleHandleW( NULL
), GetCurrentThreadId());
105 ok(hMouseHook
!=NULL
,"failed to set hook\n");
106 ok(hMouseHookLL
!=NULL
,"failed to set hook\n");
108 RegisterSimpleClass(TmeTestProc
, L
"testClass");
110 hWnd1
= CreateWindowW(L
"testClass", L
"test", WS_OVERLAPPEDWINDOW
,
111 100, 100, 500, 500, NULL
, NULL
, 0, NULL
);
112 hWnd2
= CreateWindowW(L
"testClass", L
"test", WS_CHILD
,
113 50, 50, 200, 200, hWnd1
, NULL
, 0, NULL
);
114 hWnd3
= CreateWindowW(L
"testClass", L
"test", WS_CHILD
,
115 150, 150, 200, 200, hWnd1
, NULL
, 0, NULL
);
117 ShowWindow(hWnd1
, SW_SHOW
);
119 ShowWindow(hWnd2
, SW_SHOW
);
121 ShowWindow(hWnd3
, SW_SHOWNORMAL
);
123 //SetWindowPos (hWnd3, HWND_TOP, 0,0,0,0, SWP_NOMOVE|SWP_NOREDRAW);
126 static void destroy_test_window()
128 DestroyWindow(hWnd1
);
129 UnregisterClassW(L
"testClass", 0);
130 UnhookWindowsHookEx(hMouseHookLL
);
131 UnhookWindowsHookEx(hMouseHook
);
134 static void TmeStartTracking(HWND hwnd
, DWORD Flags
)
137 tme
.cbSize
= sizeof(tme
);
139 tme
.hwndTrack
= hwnd
;
141 if(!TrackMouseEvent(&tme
))
147 DWORD
TmeQuery(HWND hwnd
)
150 tme
.cbSize
= sizeof(tme
);
151 tme
.dwFlags
= TME_QUERY
|TME_HOVER
|TME_LEAVE
;
152 tme
.hwndTrack
= hwnd
;
153 TrackMouseEvent(&tme
);
157 #define EXPECT_TME_FLAGS(hWnd, expected) \
158 { DWORD flags = TmeQuery(hWnd); \
159 ok(flags == (expected),"wrong tme flags. expected %li, and got %li\n", (DWORD)(expected), flags); \
162 #define MOVE_CURSOR(x,y) mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE , \
163 x*(65535/GetSystemMetrics(SM_CXVIRTUALSCREEN)), \
164 y*(65535/GetSystemMetrics(SM_CYVIRTUALSCREEN)) , 0,0);
166 /* the mouse moves over hwnd2 */
167 MSG_ENTRY mousemove2_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
169 {2, WH_MOUSE
,HOOK
, WM_MOUSEMOVE
, HTCLIENT
},
172 {2, WM_MOUSEMOVE
, POST
},
175 /* the mouse hovers hwnd2 */
176 MSG_ENTRY mousehover2_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
178 {2, WH_MOUSE
,HOOK
, WM_MOUSEMOVE
, HTCLIENT
},
181 {2, WM_MOUSEMOVE
, POST
},
182 {2, WM_SYSTIMER
, POST
, ID_TME_TIMER
},
183 {2, WM_MOUSEHOVER
, POST
},
186 /* the mouse leaves hwnd2 and moves to hwnd1 */
187 MSG_ENTRY mouseleave2to1_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
189 {1, WH_MOUSE
,HOOK
, WM_MOUSEMOVE
, HTCLIENT
},
191 {1, WM_MOUSEMOVE
, POST
},
192 {2, WM_MOUSELEAVE
, POST
},
195 /* the mouse leaves hwnd2 and moves to hwnd3 */
196 MSG_ENTRY mouseleave2to3_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
198 {3, WH_MOUSE
,HOOK
, WM_MOUSEMOVE
, HTCLIENT
},
201 {3, WM_MOUSEMOVE
, POST
},
202 {2, WM_MOUSELEAVE
, POST
},
205 /* the mouse hovers hwnd3 */
206 MSG_ENTRY mousehover3_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
208 {3, WH_MOUSE
,HOOK
, WM_MOUSEMOVE
, HTCLIENT
},
211 {3, WM_MOUSEMOVE
, POST
},
212 {3, WM_SYSTIMER
, POST
, ID_TME_TIMER
},
213 {3, WM_MOUSEHOVER
, POST
},
216 /* the mouse hovers hwnd3 without moving */
217 MSG_ENTRY mousehover3_nomove_chain
[]={{3, WM_SYSTIMER
, POST
, ID_TME_TIMER
},
218 {3, WM_MOUSEHOVER
, POST
},
221 /* the mouse hovers hwnd3 and the timer is not dispatched */
222 MSG_ENTRY mousehover3_droptimer_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
224 {3, WH_MOUSE
,HOOK
, WM_MOUSEMOVE
, HTCLIENT
},
227 {3, WM_MOUSEMOVE
, POST
},
228 {3, WM_SYSTIMER
, POST
, ID_TME_TIMER
},
231 /* the mouse hovers hwnd3 and mouse message is dropped by WH_MOUSE */
232 MSG_ENTRY mousehover3_dropmouse_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
234 {3, WH_MOUSE
,HOOK
, WM_MOUSEMOVE
, HTCLIENT
},
235 {3, WM_SYSTIMER
, POST
, ID_TME_TIMER
},
236 {3, WM_MOUSEHOVER
, POST
},
239 /* the mouse hovers hwnd3 and mouse message is dropped by WH_MOUSE_LL */
240 MSG_ENTRY mousehover3_dropmousell_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
241 {3, WM_SYSTIMER
, POST
, ID_TME_TIMER
},
242 {3, WM_MOUSEHOVER
, POST
},
245 /* the mouse leaves hwnd3 and moves to hwnd2 and mouse message is dropped by WH_MOUSE */
246 MSG_ENTRY mouseleave3to2_dropmouse_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
248 {2, WH_MOUSE
,HOOK
, WM_MOUSEMOVE
, HTCLIENT
},
251 /* the mouse leaves hwnd3 and moves to hwnd2 and mouse message is dropped by WH_MOUSE_LL */
252 MSG_ENTRY mouseleave3to2_dropmousell_chain
[]={{0, WH_MOUSE_LL
, HOOK
, WM_MOUSEMOVE
},
255 /* after WH_MOUSE drops WM_MOUSEMOVE, WM_MOUSELEAVE is still in the queue */
256 MSG_ENTRY mouseleave3_remainging_chain
[]={{3, WM_MOUSELEAVE
, POST
},
259 void Test_TrackMouseEvent()
262 create_test_windows();
266 /* the mouse moves over hwnd2 */
267 MOVE_CURSOR(220,220);
269 COMPARE_CACHE(mousemove2_chain
);
270 EXPECT_TME_FLAGS(hWnd2
, 0);
272 /* Begin tracking mouse events for hWnd2 */
273 TmeStartTracking(hWnd2
, TME_HOVER
|TME_LEAVE
);
274 EXPECT_TME_FLAGS(hWnd2
, TME_HOVER
|TME_LEAVE
);
276 COMPARE_CACHE(empty_chain
);
278 /* the mouse hovers hwnd2 */
279 MOVE_CURSOR(221, 221);
281 EXPECT_TME_FLAGS(hWnd2
, TME_HOVER
|TME_LEAVE
);
282 FLUSH_MESSAGES(QS_TIMER
|QS_MOUSEMOVE
, 0);
283 EXPECT_TME_FLAGS(hWnd2
, TME_LEAVE
);
284 COMPARE_CACHE(mousehover2_chain
);
286 /* the mouse leaves hwnd2 and moves to hwnd1 */
287 MOVE_CURSOR(150, 150);
288 EXPECT_TME_FLAGS(hWnd2
, TME_LEAVE
);
289 FLUSH_MESSAGES(QS_MOUSEMOVE
,QS_TIMER
);
290 EXPECT_TME_FLAGS(hWnd2
, 0);
291 COMPARE_CACHE(mouseleave2to1_chain
);
294 COMPARE_CACHE(empty_chain
);
296 /* the mouse moves over hwnd2 */
297 MOVE_CURSOR(220,220);
298 FLUSH_MESSAGES(QS_MOUSEMOVE
, QS_TIMER
);
299 COMPARE_CACHE(mousemove2_chain
);
300 EXPECT_TME_FLAGS(hWnd2
, 0);
303 COMPARE_CACHE(empty_chain
);
305 /* Begin tracking mouse events for hWnd2 */
306 TmeStartTracking(hWnd2
, TME_HOVER
|TME_LEAVE
);
307 TmeStartTracking(hWnd2
, TME_HOVER
|TME_LEAVE
);
308 TmeStartTracking(hWnd2
, TME_HOVER
|TME_LEAVE
);
309 TmeStartTracking(hWnd2
, TME_HOVER
|TME_LEAVE
);
310 FLUSH_MESSAGES(0, QS_TIMER
|QS_MOUSEMOVE
);
311 COMPARE_CACHE(empty_chain
);
312 EXPECT_TME_FLAGS(hWnd2
, TME_HOVER
|TME_LEAVE
);
314 /* the mouse moves from hwnd2 to the intersection of hwnd2 and hwnd3 */
315 MOVE_CURSOR(300,300);
316 FLUSH_MESSAGES(QS_MOUSEMOVE
, QS_TIMER
);
317 EXPECT_TME_FLAGS(hWnd2
, TME_HOVER
|TME_LEAVE
);
318 COMPARE_CACHE(mousemove2_chain
);
321 COMPARE_CACHE(empty_chain
);
323 /* the mouse moves from hwnd2 to hwnd3 */
324 MOVE_CURSOR(400,400);
325 FLUSH_MESSAGES(QS_MOUSEMOVE
, QS_TIMER
);
326 EXPECT_TME_FLAGS(hWnd2
, 0);
327 COMPARE_CACHE(mouseleave2to3_chain
);
330 COMPARE_CACHE(empty_chain
);
332 /* Begin tracking mouse events for hWnd3 */
333 TmeStartTracking(hWnd3
, TME_HOVER
|TME_LEAVE
);
334 FLUSH_MESSAGES(0, QS_TIMER
|QS_MOUSEMOVE
);
335 COMPARE_CACHE(empty_chain
);
336 EXPECT_TME_FLAGS(hWnd2
, TME_HOVER
|TME_LEAVE
);
338 /* the mouse hovers hwnd3 */
339 MOVE_CURSOR(401,401);
341 EXPECT_TME_FLAGS(hWnd3
, TME_HOVER
|TME_LEAVE
);
342 FLUSH_MESSAGES(QS_TIMER
|QS_MOUSEMOVE
, 0);
343 EXPECT_TME_FLAGS(hWnd3
, TME_LEAVE
);
344 COMPARE_CACHE(mousehover3_chain
);
347 COMPARE_CACHE(empty_chain
);
349 /* Begin tracking mouse events for hWnd3 */
350 TmeStartTracking(hWnd3
, TME_HOVER
);
351 FLUSH_MESSAGES(0, QS_TIMER
|QS_MOUSEMOVE
);
352 COMPARE_CACHE(empty_chain
);
353 EXPECT_TME_FLAGS(hWnd3
, TME_HOVER
|TME_LEAVE
);
355 /* make sure that the timer will fire before the mouse moves */
358 COMPARE_CACHE(mousehover3_nomove_chain
);
359 EXPECT_TME_FLAGS(hWnd3
, TME_LEAVE
);
363 COMPARE_CACHE(empty_chain
);
365 /* the mouse hovers hwnd3 and the timer is not dispatched*/
366 TmeStartTracking(hWnd3
, TME_HOVER
);
368 MOVE_CURSOR(400,400);
370 EXPECT_TME_FLAGS(hWnd3
, TME_HOVER
|TME_LEAVE
);
371 FLUSH_MESSAGES(QS_TIMER
|QS_MOUSEMOVE
, 0); /* the loop drops WM_SYSTIMER */
372 EXPECT_TME_FLAGS(hWnd3
, TME_HOVER
|TME_LEAVE
); /* TME_HOVER is still active */
373 COMPARE_CACHE(mousehover3_droptimer_chain
); /* we get no WM_MOUSEHOVER */
374 ignore_timer
= FALSE
;
376 /* the mouse hovers hwnd3 and mouse message is dropped by WH_MOUSE_LL */
377 ignore_mousell
= TRUE
;
378 MOVE_CURSOR(402,402);
380 EXPECT_TME_FLAGS(hWnd3
, TME_HOVER
|TME_LEAVE
);
381 FLUSH_MESSAGES(QS_TIMER
, QS_MOUSEMOVE
); /* WH_MOUSE_LL drops WM_MOUSEMOVE */
382 EXPECT_TME_FLAGS(hWnd3
, TME_LEAVE
);
383 COMPARE_CACHE(mousehover3_dropmousell_chain
); /* we get WM_MOUSEHOVER normaly */
384 ignore_mousell
= FALSE
;
387 COMPARE_CACHE(empty_chain
);
389 /* the mouse hovers hwnd3 and mouse message is dropped by WH_MOUSE */
391 TmeStartTracking(hWnd3
, TME_HOVER
);
392 MOVE_CURSOR(401,401);
394 EXPECT_TME_FLAGS(hWnd3
, TME_HOVER
|TME_LEAVE
);
395 FLUSH_MESSAGES(QS_TIMER
|QS_MOUSEMOVE
, 0); /* WH_MOUSE drops WM_MOUSEMOVE */
396 EXPECT_TME_FLAGS(hWnd3
, TME_LEAVE
);
397 COMPARE_CACHE(mousehover3_dropmouse_chain
); /* we get WM_MOUSEHOVER normaly */
398 ignore_mouse
= FALSE
;
401 COMPARE_CACHE(empty_chain
);
403 /* the mouse leaves hwnd3 and moves to hwnd2 and mouse message is dropped by WH_MOUSE_LL */
404 ignore_mousell
= TRUE
;
405 TmeStartTracking(hWnd3
, TME_LEAVE
);
406 MOVE_CURSOR(220,220);
407 FLUSH_MESSAGES(0, QS_MOUSEMOVE
|QS_TIMER
); /* WH_MOUSE drops WM_MOUSEMOVE */
408 EXPECT_TME_FLAGS(hWnd3
, TME_LEAVE
); /* all flags are removed */
409 COMPARE_CACHE(mouseleave3to2_dropmousell_chain
); /* we get no WM_MOUSELEAVE */
410 ignore_mousell
= FALSE
;
413 COMPARE_CACHE(empty_chain
);
415 /* the mouse leaves hwnd3 and moves to hwnd2 and mouse message is dropped by WH_MOUSE */
417 MOVE_CURSOR(220,220);
418 FLUSH_MESSAGES(QS_MOUSEMOVE
, QS_TIMER
); /* WH_MOUSE drops WM_MOUSEMOVE */
419 EXPECT_TME_FLAGS(hWnd3
, 0); /* all flags are removed */
420 COMPARE_CACHE(mouseleave3to2_dropmouse_chain
); /* we get no WM_MOUSELEAVE */
421 ignore_mouse
= FALSE
;
423 /* after WH_MOUSE drops WM_MOUSEMOVE, WM_MOUSELEAVE is still in the queue */
424 FLUSH_MESSAGES(QS_POSTMESSAGE
, QS_TIMER
|QS_MOUSEMOVE
);
425 COMPARE_CACHE(mouseleave3_remainging_chain
);
428 COMPARE_CACHE(empty_chain
);
430 destroy_test_window();
433 START_TEST(TrackMouseEvent
)
435 Test_TrackMouseEvent();