diff --git a/rostests/apitests/user32/SetActiveWindow.c b/rostests/apitests/user32/SetActiveWindow.c index a4ef9d6592e..f5fb42e59fb 100644 --- a/rostests/apitests/user32/SetActiveWindow.c +++ b/rostests/apitests/user32/SetActiveWindow.c @@ -11,7 +11,6 @@ #include "helper.h" #include -MSG_ENTRY message_cache[100]; HWND hWnd1, hWnd2, hWnd3, hWnd4; /* FIXME: test for HWND_TOP, etc...*/ @@ -81,123 +80,223 @@ static void create_test_windows() 250, 250, 200, 200, hWnd1, NULL, 0, NULL); } +static void set_default_zorder() +{ + /* show the windows */ + ShowWindow(hWnd1, SW_SHOW); + UpdateWindow(hWnd1); + ShowWindow(hWnd2, SW_SHOW); + UpdateWindow(hWnd2); + ShowWindow(hWnd3, SW_SHOW); + UpdateWindow(hWnd3); + ShowWindow(hWnd4, SW_SHOW); + UpdateWindow(hWnd4); + + SetWindowPos(hWnd3, 0, 0,0,0,0, SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + SetWindowPos(hWnd1, 0, 0,0,0,0, SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + SetWindowPos(hWnd2, 0, 0,0,0,0, SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + SetWindowPos(hWnd4, 0, 0,0,0,0, SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + + FlushMessages(); + empty_message_cache(); +} + +static void destroy_test_window() +{ + DestroyWindow(hWnd1); + DestroyWindow(hWnd2); + DestroyWindow(hWnd3); + DestroyWindow(hWnd4); + UnregisterClassW(L"testClass", 0); +} + +#define EXPECT_NEXT(hWnd1, hWnd2) \ + ok(get_iwnd(GetWindow(hWnd1,GW_HWNDNEXT)) == get_iwnd(hWnd2), \ + "After hwnd%d, expected hwnd%d not hwnd%d\n", \ + get_iwnd(hWnd1), get_iwnd(hWnd2),get_iwnd(GetWindow(hWnd1,GW_HWNDNEXT)) ) + +#define EXPECT_CHAIN(A,B,C,D,X) \ + EXPECT_NEXT(hWnd##A, hWnd##B); \ + EXPECT_NEXT(hWnd##B, hWnd##C); \ + EXPECT_NEXT(hWnd##C, hWnd##D); \ + EXPECT_NEXT(hWnd##D, 0); \ + EXPECT_ACTIVE(hWnd##X); + /* the actual test begins here */ -MSG_ENTRY Activate1_chain[]={{4,WM_NCACTIVATE}, - {4,WM_ACTIVATE}, - {4,WM_WINDOWPOSCHANGING,SENT,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE}, - {2,WM_WINDOWPOSCHANGING,SENT,4,SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE}, - {1,WM_WINDOWPOSCHANGING,SENT,2,SWP_NOMOVE | SWP_NOSIZE}, - {1,WM_NCACTIVATE}, - {1,WM_ACTIVATE}, - {4,WM_KILLFOCUS}, - {1,WM_SETFOCUS}, - {0,0}}; +MSG_ENTRY Activate1_chain[]= + {{4,WM_NCACTIVATE}, + {4,WM_ACTIVATE}, + {4,WM_WINDOWPOSCHANGING,SENT,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE}, + {2,WM_WINDOWPOSCHANGING,SENT,4,SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE}, + {1,WM_WINDOWPOSCHANGING,SENT,2,SWP_NOMOVE | SWP_NOSIZE}, + {1,WM_NCACTIVATE}, + {1,WM_ACTIVATE}, + {4,WM_KILLFOCUS}, + {1,WM_SETFOCUS}, + {0,0}}; -MSG_ENTRY Activate2_chain[]={{1,WM_NCACTIVATE}, - {1,WM_ACTIVATE}, - {3,WM_WINDOWPOSCHANGING,SENT, 0, SWP_NOMOVE | SWP_NOSIZE}, - {3,WM_WINDOWPOSCHANGED ,SENT, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE}, - {3,WM_NCACTIVATE}, - {3,WM_ACTIVATE}, - {1,WM_KILLFOCUS}, - {3,WM_SETFOCUS}, - {0,0}}; +MSG_ENTRY Activate2_chain[]= + {{1,WM_NCACTIVATE}, + {1,WM_ACTIVATE}, + {3,WM_WINDOWPOSCHANGING,SENT, 0, SWP_NOMOVE | SWP_NOSIZE}, + {3,WM_WINDOWPOSCHANGED ,SENT, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE}, + {3,WM_NCACTIVATE}, + {3,WM_ACTIVATE}, + {1,WM_KILLFOCUS}, + {3,WM_SETFOCUS}, + {0,0}}; -MSG_ENTRY Activate3_chain[]={{3,WM_NCACTIVATE}, - {3,WM_ACTIVATE}, - {2,WM_WINDOWPOSCHANGING, SENT,0, SWP_NOMOVE | SWP_NOSIZE }, - {4,WM_WINDOWPOSCHANGING, SENT,2, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE}, - {1,WM_WINDOWPOSCHANGING, SENT,4, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE}, - {2,WM_WINDOWPOSCHANGED, SENT,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOCLIENTMOVE |SWP_NOCLIENTSIZE }, - {4,WM_WINDOWPOSCHANGED, SENT,2, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE |SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE}, - {1,WM_WINDOWPOSCHANGED, SENT,4, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE |SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE}, - {2,WM_NCACTIVATE}, - {2,WM_ACTIVATE}, - {3,WM_KILLFOCUS}, - {2,WM_SETFOCUS}, - {0,0}}; +MSG_ENTRY Activate3_chain[]= + {{3,WM_NCACTIVATE}, + {3,WM_ACTIVATE}, + {2,WM_WINDOWPOSCHANGING, SENT,0, SWP_NOMOVE | SWP_NOSIZE }, + {4,WM_WINDOWPOSCHANGING, SENT,2, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE}, + {1,WM_WINDOWPOSCHANGING, SENT,4, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE}, + {2,WM_WINDOWPOSCHANGED, SENT,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOCLIENTMOVE |SWP_NOCLIENTSIZE }, + {4,WM_WINDOWPOSCHANGED, SENT,2, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE |SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE}, + {1,WM_WINDOWPOSCHANGED, SENT,4, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE |SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE}, + {2,WM_NCACTIVATE}, + {2,WM_ACTIVATE}, + {3,WM_KILLFOCUS}, + {2,WM_SETFOCUS}, + {0,0}}; -MSG_ENTRY Activate4_chain[]={{2,WM_NCACTIVATE, }, - {2,WM_ACTIVATE}, - {2,WM_WINDOWPOSCHANGING, SENT ,0 ,SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE}, - {4,WM_WINDOWPOSCHANGING, SENT, 2, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE} , - {1,WM_WINDOWPOSCHANGING, SENT, 4, SWP_NOMOVE | SWP_NOSIZE}, - {1,WM_NCACTIVATE}, - {1,WM_ACTIVATE}, - {2,WM_KILLFOCUS}, - {1,WM_SETFOCUS}, - {0,0}}; +MSG_ENTRY Activate4_chain[]= + {{2,WM_NCACTIVATE, }, + {2,WM_ACTIVATE}, + {2,WM_WINDOWPOSCHANGING, SENT ,0 ,SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE}, + {4,WM_WINDOWPOSCHANGING, SENT, 2, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE} , + {1,WM_WINDOWPOSCHANGING, SENT, 4, SWP_NOMOVE | SWP_NOSIZE}, + {1,WM_NCACTIVATE}, + {1,WM_ACTIVATE}, + {2,WM_KILLFOCUS}, + {1,WM_SETFOCUS}, + {0,0}}; -void Test_SetActiveWindow() +MSG_ENTRY Activate5_chain[]= + {{1,WM_NCACTIVATE, }, + {1,WM_ACTIVATE}, + {4,WM_WINDOWPOSCHANGING, SENT, 0 ,SWP_NOMOVE | SWP_NOSIZE}, + {2,WM_WINDOWPOSCHANGING, SENT, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE}, + {1,WM_WINDOWPOSCHANGING, SENT, 2, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE}, + {4,WM_WINDOWPOSCHANGED, SENT, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE}, + {4,WM_NCACTIVATE}, + {4,WM_ACTIVATE}, + {1,WM_KILLFOCUS}, + {4,WM_SETFOCUS}, + {0,0}}; + +/* + some notes about this testcase: + from the expected series of messages it is obbvious that SetActiveWindow uses SetWindowPos. + So the big question is, that if this behaviour (of changing the z order of owner and owned windows) + is implemented in SetActiveWindow or SetWindowPos. + More tests reveal that calling SetWindowPos like this, has the same effect in the zorder: + SetWindowPos(hWndX, 0, 0,0,0,0, SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW); + However if it is called like this it does NOT change the z-order of owner or owned windows: + SetWindowPos(hWndX, 0, 0,0,0,0, SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + So the conclusion is that SetActiveWindow calls Begin/Defer/EndDeferWindow pos + moving all affected windows in a batch move operation +*/ + +void Test_OwnerWindows() { SetCursorPos(0,0); create_test_windows(); + set_default_zorder(); - ShowWindow(hWnd1, SW_SHOW); - UpdateWindow(hWnd1); - FlushMessages(); - EXPECT_NEXT(hWnd4,hWnd2); - EXPECT_NEXT(hWnd1,hWnd3); - - ShowWindow(hWnd2, SW_SHOW); - UpdateWindow(hWnd2); - FlushMessages(); - EXPECT_NEXT(hWnd2,hWnd4); - EXPECT_NEXT(hWnd4,hWnd1); - - ShowWindow(hWnd3, SW_SHOW); - UpdateWindow(hWnd3); - FlushMessages(); - EXPECT_NEXT(hWnd3,hWnd2); - EXPECT_NEXT(hWnd2,hWnd4); - EXPECT_NEXT(hWnd4,hWnd1); - - ShowWindow(hWnd4, SW_SHOW); - UpdateWindow(hWnd4); - FlushMessages(); - EXPECT_NEXT(hWnd4,hWnd2); - EXPECT_NEXT(hWnd2,hWnd1); - EXPECT_NEXT(hWnd1,hWnd3); - EXPECT_ACTIVE(hWnd4); - - empty_message_cache(); + /* before we start testing SetActiveWindow we have to be sure they are on the ocrrect order*/ + EXPECT_CHAIN(4,2,1,3,4); + /* move the windows on top in the following order 1 2 3 1 4 */ SetActiveWindow(hWnd1); FlushMessages(); - EXPECT_NEXT(hWnd4,hWnd2); - EXPECT_NEXT(hWnd2,hWnd1); - EXPECT_NEXT(hWnd1,hWnd3); - EXPECT_ACTIVE(hWnd1); + EXPECT_CHAIN(4,2,1,3,1); COMPARE_CACHE(Activate1_chain); SetActiveWindow(hWnd3); FlushMessages(); - EXPECT_NEXT(hWnd3,hWnd4); - EXPECT_NEXT(hWnd4,hWnd2); - EXPECT_NEXT(hWnd2,hWnd1); - EXPECT_ACTIVE(hWnd3); + EXPECT_CHAIN(3,4,2,1,3); COMPARE_CACHE(Activate2_chain); SetActiveWindow(hWnd2); FlushMessages(); - EXPECT_NEXT(hWnd2,hWnd4); - EXPECT_NEXT(hWnd4,hWnd1); - EXPECT_NEXT(hWnd1,hWnd3); - EXPECT_ACTIVE(hWnd2); + EXPECT_CHAIN(2,4,1,3,2); COMPARE_CACHE(Activate3_chain); SetActiveWindow(hWnd1); FlushMessages(); - EXPECT_NEXT(hWnd2,hWnd4); - EXPECT_NEXT(hWnd4,hWnd1); - EXPECT_NEXT(hWnd1,hWnd3); - EXPECT_ACTIVE(hWnd1); + EXPECT_CHAIN(2,4,1,3,1); COMPARE_CACHE(Activate4_chain); + + SetActiveWindow(hWnd4); + FlushMessages(); + EXPECT_CHAIN(4,2,1,3,4); + /* in this test xp and 7 give different results :/ */ + /*COMPARE_CACHE(Activate5_chain);*/ + + /* move the windows on top with the same order but now using SetWindowPos */ + /* note: the zorder of windows change in the same way they change with SetActiveWindow */ + set_default_zorder(); + + SetWindowPos(hWnd1, 0, 0,0,0,0, SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW); + FlushMessages(); + empty_message_cache(); + EXPECT_CHAIN(4,2,1,3,1); + + SetWindowPos(hWnd3, 0, 0,0,0,0, SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW); + FlushMessages(); + empty_message_cache(); + EXPECT_CHAIN(3,4,2,1,3); + + SetWindowPos(hWnd2, 0, 0,0,0,0, SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW); + FlushMessages(); + empty_message_cache(); + EXPECT_CHAIN(2,4,1,3,2); + + SetWindowPos(hWnd1, 0, 0,0,0,0, SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW); + FlushMessages(); + empty_message_cache(); + EXPECT_CHAIN(2,4,1,3,1); + + SetWindowPos(hWnd4, 0, 0,0,0,0, SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW); + FlushMessages(); + empty_message_cache(); + EXPECT_CHAIN(4,2,1,3,4); + + /* now do the same thing one more time with SWP_NOACTIVATE */ + set_default_zorder(); + + SetWindowPos(hWnd1, 0, 0,0,0,0, SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + FlushMessages(); + empty_message_cache(); + EXPECT_CHAIN(1,4,2,3,4); + + SetWindowPos(hWnd3, 0, 0,0,0,0, SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + FlushMessages(); + empty_message_cache(); + EXPECT_CHAIN(3,1,4,2,4); + + SetWindowPos(hWnd2, 0, 0,0,0,0, SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + FlushMessages(); + empty_message_cache(); + EXPECT_CHAIN(2,3,1,4,4); + + SetWindowPos(hWnd1, 0, 0,0,0,0, SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + FlushMessages(); + empty_message_cache(); + EXPECT_CHAIN(1,2,3,4,4); + + SetWindowPos(hWnd4, 0, 0,0,0,0, SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + FlushMessages(); + EXPECT_CHAIN(4,1,2,3,4); + + destroy_test_window(); } START_TEST(SetActiveWindow) { - Test_SetActiveWindow(); + Test_OwnerWindows(); } diff --git a/rostests/apitests/user32/TrackMouseEvent.c b/rostests/apitests/user32/TrackMouseEvent.c index a920f0a8964..03a31cdcc67 100644 --- a/rostests/apitests/user32/TrackMouseEvent.c +++ b/rostests/apitests/user32/TrackMouseEvent.c @@ -104,15 +104,12 @@ static void FlushMessages() static void create_test_windows() { - WNDCLASSEXW wcex; - hMouseHookLL = SetWindowsHookExW(WH_MOUSE_LL, MouseLLHookProc, GetModuleHandleW( NULL ), 0); hMouseHook = SetWindowsHookExW(WH_MOUSE, MouseHookProc, GetModuleHandleW( NULL ), GetCurrentThreadId()); ok(hMouseHook!=NULL,"failed to set hook\n"); ok(hMouseHookLL!=NULL,"failed to set hook\n"); RegisterSimpleClass(TmeTestProc, L"testClass"); - RegisterClassExW(&wcex); hWnd1 = CreateWindowW(L"testClass", L"test", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, 0, NULL); @@ -130,6 +127,14 @@ static void create_test_windows() //SetWindowPos (hWnd3, HWND_TOP, 0,0,0,0, SWP_NOMOVE|SWP_NOREDRAW); } +static void destroy_test_window() +{ + DestroyWindow(hWnd1); + UnregisterClassW(L"testClass", 0); + UnhookWindowsHookEx(hMouseHookLL); + UnhookWindowsHookEx(hMouseHook); +} + static void TmeStartTracking(HWND hwnd, DWORD Flags) { TRACKMOUSEEVENT tme; @@ -162,8 +167,6 @@ DWORD TmeQuery(HWND hwnd) x*(65535/GetSystemMetrics(SM_CXVIRTUALSCREEN)), \ y*(65535/GetSystemMetrics(SM_CYVIRTUALSCREEN)) , 0,0); -MSG_ENTRY empty_chain[]= {{0,0}}; - /* the mouse moves over hwnd2 */ MSG_ENTRY mousemove2_chain[]={{0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE}, {2, WM_NCHITTEST}, @@ -427,6 +430,8 @@ void Test_TrackMouseEvent() FlushMessages(); COMPARE_CACHE(empty_chain); + + destroy_test_window(); } START_TEST(TrackMouseEvent) diff --git a/rostests/apitests/user32/helper.c b/rostests/apitests/user32/helper.c index bd37ecc7467..ac91023d476 100644 --- a/rostests/apitests/user32/helper.c +++ b/rostests/apitests/user32/helper.c @@ -15,6 +15,8 @@ MSG_ENTRY last_post_message; MSG_ENTRY message_cache[100]; static int message_cache_size = 0; +MSG_ENTRY empty_chain[]= {{0,0}}; + static char* get_msg_name(UINT msg) { switch(msg) @@ -41,6 +43,8 @@ static char* get_msg_name(UINT msg) case WM_SETCURSOR: return "WM_SETCURSOR"; case WM_MOUSEMOVE: return "WM_MOUSEMOVE"; case WM_SYSTIMER: return "WM_SYSTIMER"; + case WM_GETMINMAXINFO: return "WM_GETMINMAXINFO"; + case WM_NCCALCSIZE: return "WM_NCCALCSIZE"; default: return NULL; } } diff --git a/rostests/apitests/user32/helper.h b/rostests/apitests/user32/helper.h index de4cbdf27ca..246c1c914d1 100644 --- a/rostests/apitests/user32/helper.h +++ b/rostests/apitests/user32/helper.h @@ -16,6 +16,9 @@ typedef struct _MSG_ENTRY int param2; } MSG_ENTRY; + +extern MSG_ENTRY empty_chain[]; + void record_message(int iwnd, UINT message, MSG_TYPE type, int param1,int param2); void compare_cache(const char* file, int line, MSG_ENTRY *msg_chain); void trace_cache(const char* file, int line); @@ -44,7 +47,6 @@ static inline BOOL IseKeyMsg(UINT msg) #define COMPARE_CACHE(...) compare_cache(__FILE__, __LINE__, ##__VA_ARGS__) #define TRACE_CACHE() trace_cache(__FILE__, __LINE__) -#define EXPECT_NEXT(hWnd1, hWnd2) ok(GetWindow(hWnd1,GW_HWNDNEXT) == hWnd2, "Expected %p after %p, not %p\n",hWnd2,hWnd1,GetWindow(hWnd1,GW_HWNDNEXT) ) #define EXPECT_ACTIVE(hwnd) ok(GetActiveWindow() == hwnd, "Expected %p to be the active window, not %p\n",hwnd,GetActiveWindow()) #define EXPECT_QUEUE_STATUS(expected, notexpected) \