Richard Cohen wrote:

This fixes a longstanding bug whereby winemine would move 1 pixel down the screen for every new game.


Changelog:
- Fix off-by-one in menu height calculation (& therefore AdjustWindowRect) + test

diff -N -u -r -p dlls/user/nonclient.c dlls/user/nonclient.c
--- dlls/user/nonclient.c	2005-04-25 12:33:36.000000000 +0100
+++ dlls/user/nonclient.c	2005-05-23 11:27:57.000000000 +0100
@@ -398,7 +398,7 @@ LONG NC_HandleNCCalcSize( HWND hwnd, REC
             winRect->top +=
                 MENU_GetMenuBarHeight( hwnd,
                                        winRect->right - winRect->left,
-                                       -tmpRect.left, -tmpRect.top ) + 1;
+                                       -tmpRect.left, -tmpRect.top );
         }
 
         if( exStyle & WS_EX_CLIENTEDGE)
diff -N -u -r -p dlls/user/tests/win.c dlls/user/tests/win.c
--- dlls/user/tests/win.c	2005-05-15 11:50:17.000000000 +0100
+++ dlls/user/tests/win.c	2005-05-23 11:52:26.000000000 +0100
@@ -55,6 +55,11 @@ static HWND hwndMessage;
 static HWND hwndMain, hwndMain2;
 static HHOOK hhook;
 
+static const char* szAWRClass = "Winsize";
+static HMENU hmenu;
+
+#define COUNTOF(arr) (sizeof(arr)/sizeof(arr[0]))
+
 /* check the values returned by the various parent/owner functions on a given window */
 static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_parent,
                            HWND gw_owner, HWND ga_root, HWND ga_root_owner )
@@ -645,11 +650,27 @@ static void verify_window_info(HWND hwnd
     ok(info->wCreatorVersion == 0x0400, "wrong wCreatorVersion %04x\n", info->wCreatorVersion);
 }
 
+static void FixedAdjustWindowRectEx(RECT* rc, LONG style, BOOL menu, LONG exstyle)
+{
+    AdjustWindowRectEx(rc, style, menu, exstyle);
+    /* AdjustWindowRectEx does not include scroll bars */
+    if (style & WS_VSCROLL)
+    {
+        if(exstyle & WS_EX_LEFTSCROLLBAR)
+            rc->left  -= GetSystemMetrics(SM_CXVSCROLL);
+        else
+            rc->right += GetSystemMetrics(SM_CXVSCROLL);
+    }
+    if (style & WS_HSCROLL)
+	rc->bottom += GetSystemMetrics(SM_CYHSCROLL);
+}
+
 static void test_nonclient_area(HWND hwnd)
 {
     DWORD style, exstyle;
     RECT rc_window, rc_client, rc;
     BOOL menu;
+    BOOL is_win9x = GetWindowLongW(hwnd, GWL_WNDPROC) == 0;
 
     style = GetWindowLongA(hwnd, GWL_STYLE);
     exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
@@ -666,25 +687,27 @@ static void test_nonclient_area(HWND hwn
 
     CopyRect(&rc, &rc_client);
     MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
-    AdjustWindowRectEx(&rc, style, menu, exstyle);
+    FixedAdjustWindowRectEx(&rc, style, menu, exstyle);
+
     trace("calc window: (%ld,%ld)-(%ld,%ld)\n", rc.left, rc.top, rc.right, rc.bottom);
-#if 0 /* Uncomment this once the test succeeds in all cases */
-    ok(EqualRect(&rc, &rc_window), "window rect does not match\n");
-#endif
+    ok(EqualRect(&rc, &rc_window), "window rect does not match: style:exstyle=0x%08lx:0x%08lx, menu=%d\n", style, exstyle, menu);
+
 
     CopyRect(&rc, &rc_window);
     DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc);
     MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2);
     trace("calc client: (%ld,%ld)-(%ld,%ld)\n", rc.left, rc.top, rc.right, rc.bottom);
-#if 0 /* Uncomment this once the test succeeds in all cases */
-    ok(EqualRect(&rc, &rc_client), "client rect does not match\n");
-#endif
+    ok(EqualRect(&rc, &rc_client), "client rect does not match: style:exstyle=0x%08lx:0x%08lx, menu=%d\n", style, exstyle, menu);
+
+    /* Win9x doesn't like WM_NCCALCSIZE with synthetic data and crashes */;
+    if (is_win9x)
+	return;
 
     /* and now test AdjustWindowRectEx and WM_NCCALCSIZE on synthetic data */
     SetRect(&rc_client, 0, 0, 250, 150);
     CopyRect(&rc_window, &rc_client);
     MapWindowPoints(hwnd, 0, (LPPOINT)&rc_window, 2);
-    AdjustWindowRectEx(&rc_window, style, menu, exstyle);
+    FixedAdjustWindowRectEx(&rc_window, style, menu, exstyle);
     trace("calc window: (%ld,%ld)-(%ld,%ld)\n",
 	rc_window.left, rc_window.top, rc_window.right, rc_window.bottom);
 
@@ -692,9 +715,7 @@ static void test_nonclient_area(HWND hwn
     DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc);
     MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2);
     trace("calc client: (%ld,%ld)-(%ld,%ld)\n", rc.left, rc.top, rc.right, rc.bottom);
-#if 0 /* Uncomment this once the test succeeds in all cases */
-    ok(EqualRect(&rc, &rc_client), "client rect does not match\n");
-#endif
+    ok(EqualRect(&rc, &rc_client), "synthetic rect does not match: style:exstyle=0x%08lx:0x%08lx, menu=%d\n", style, exstyle, menu);
 }
 
 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) 
@@ -717,12 +738,6 @@ static LRESULT CALLBACK cbt_hook_proc(in
     /* on HCBT_DESTROYWND window state is undefined */
     if (nCode != HCBT_DESTROYWND && IsWindow((HWND)wParam))
     {
-	BOOL is_win9x = GetWindowLongPtrW((HWND)wParam, GWLP_WNDPROC) == 0;
-	if (is_win9x && nCode == HCBT_CREATEWND)
-	    /* Win9x doesn't like WM_NCCALCSIZE with synthetic data and crashes */;
-	else
-	    test_nonclient_area((HWND)wParam);
-
 	if (pGetWindowInfo)
 	{
 	    WINDOWINFO info;
@@ -1755,7 +1770,10 @@ static void test_SetMenu(HWND parent)
     assert(hMenu);
 
     ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
-    test_nonclient_area(parent);
+#if 0
+    /* fails on (at least) Wine, NT4, XP SP2 */
+    test_nonclient_area(parent); 
+#endif
     ret = GetMenu(parent);
     ok(ret == hMenu, "unexpected menu id %p\n", ret);
     /* test whether we can destroy a menu assigned to a window */
@@ -1782,7 +1800,10 @@ static void test_SetMenu(HWND parent)
     ok(ret == 0, "unexpected menu id %p\n", ret);
 
     ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
+#if 0
+    /* fails on (at least) Wine, NT4, XP SP2 */
     test_nonclient_area(parent);
+#endif
     ret = GetMenu(parent);
     ok(ret == hMenu, "unexpected menu id %p\n", ret);
 
@@ -2781,6 +2802,121 @@ static void test_params()
     ok( rc==0, "GetWindowText: rc=%d err=%ld\n",rc,GetLastError());
 }
 
+static void test_AWRwindow(LPCSTR class, LONG style, LONG exStyle, BOOL menu)
+{
+    HWND hwnd = 0;
+
+    hwnd = CreateWindowEx(exStyle, class, class, style,
+			  110, 100,
+			  225, 200,
+			  0,
+			  menu ? hmenu : 0,
+			  0, 0);
+    if (!hwnd) {
+	trace("Failed to create window class=%s, style=0x%08lx, exStyle=0x%08lx\n", class, style, exStyle);
+        return;
+    }
+    ShowWindow(hwnd, SW_SHOW);
+
+    test_nonclient_area(hwnd);
+
+    SetMenu(hwnd, 0);
+    DestroyWindow(hwnd);
+}
+
+static BOOL AWR_init(void)
+{
+    WNDCLASS class;
+
+    class.style         = CS_HREDRAW | CS_VREDRAW;
+    class.lpfnWndProc     = DefWindowProcA;
+    class.cbClsExtra    = 0;
+    class.cbWndExtra    = 0;
+    class.hInstance     = 0;
+    class.hIcon         = LoadIcon (0, IDI_APPLICATION);
+    class.hCursor       = LoadCursor (0, IDC_ARROW);
+    class.hbrBackground = 0;
+    class.lpszMenuName  = 0;
+    class.lpszClassName = szAWRClass;
+    
+    if (!RegisterClass (&class)) {
+	ok(FALSE, "RegisterClass failed\n");
+	return FALSE;
+    }
+
+    hmenu = CreateMenu();
+    if (!hmenu)
+	return FALSE;
+    ok(hmenu != 0, "Failed to create menu\n");
+    ok(AppendMenu(hmenu, MF_STRING, 1, "Test!"), "Failed to create menu item\n");
+    
+    return TRUE;
+}
+
+
+static void test_AWR_window_size(BOOL menu)
+{
+    LONG styles[] = {
+	WS_POPUP,
+	WS_MAXIMIZE, WS_BORDER, WS_DLGFRAME, 
+	WS_SYSMENU, 
+	WS_THICKFRAME,
+	WS_MINIMIZEBOX, WS_MAXIMIZEBOX,
+	WS_HSCROLL, WS_VSCROLL
+    };
+    LONG exStyles[] = {
+	WS_EX_CLIENTEDGE,
+	WS_EX_TOOLWINDOW, WS_EX_WINDOWEDGE,
+	WS_EX_APPWINDOW,
+#if 0
+	/* These styles have problems on (at least) WinXP (SP2) and Wine */
+	WS_EX_DLGMODALFRAME, 
+	WS_EX_STATICEDGE, 
+#endif
+    };
+
+    int i;    
+
+    /* A exhaustive check of all the styles takes too long
+     * so just do a (hopefully representative) sample
+     */
+    for (i = 0; i < COUNTOF(styles); ++i)
+        test_AWRwindow(szAWRClass, styles[i], 0, menu);
+    for (i = 0; i < COUNTOF(exStyles); ++i) {
+        test_AWRwindow(szAWRClass, WS_POPUP, exStyles[i], menu);
+        test_AWRwindow(szAWRClass, WS_THICKFRAME, exStyles[i], menu);
+    }
+}
+#undef COUNTOF
+
+#define SHOWSYSMETRIC(SM) trace(#SM "=%d\n", GetSystemMetrics(SM))
+
+static void test_AdjustWindowRect()
+{
+    if (!AWR_init())
+	return;
+    
+    SHOWSYSMETRIC(SM_CYCAPTION);
+    SHOWSYSMETRIC(SM_CYSMCAPTION);
+    SHOWSYSMETRIC(SM_CYMENU);
+    SHOWSYSMETRIC(SM_CXEDGE);
+    SHOWSYSMETRIC(SM_CYEDGE);
+    SHOWSYSMETRIC(SM_CXVSCROLL);
+    SHOWSYSMETRIC(SM_CYHSCROLL);
+    SHOWSYSMETRIC(SM_CXFRAME);
+    SHOWSYSMETRIC(SM_CYFRAME);
+    SHOWSYSMETRIC(SM_CXDLGFRAME);
+    SHOWSYSMETRIC(SM_CYDLGFRAME);
+    SHOWSYSMETRIC(SM_CXBORDER);
+    SHOWSYSMETRIC(SM_CYBORDER);  
+
+    test_AWR_window_size(FALSE);
+    test_AWR_window_size(TRUE);
+
+    DestroyMenu(hmenu);
+}
+#undef SHOWSYSMETRIC
+
 START_TEST(win)
 {
     pGetAncestor = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetAncestor" );
@@ -2811,6 +2947,8 @@ START_TEST(win)
                                WS_MAXIMIZEBOX | WS_POPUP,
                                100, 100, 200, 200,
                                0, 0, 0, NULL);
+    test_nonclient_area(hwndMain);
+
     hwndMain2 = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window 2",
                                 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
                                 WS_MAXIMIZEBOX | WS_POPUP,
@@ -2846,5 +2984,6 @@ START_TEST(win)
 
     UnhookWindowsHookEx(hhook);
 
+    test_AdjustWindowRect();
     test_window_styles();
 }

Reply via email to