Repaint the whole nonclient window area on SetWindowPos(SWP_FRAMECHANGED)

Dmitry Timoshkov dmitry at baikal.ru
Tue May 25 05:45:03 CDT 2004


Hello,

SetWindowPos(SWP_FRAMECHANGED) causes the whole nonclient window area
to be repainted.

Also, according to the tests Windows always repaints windows before
SetWindowPos has finished.

This patch reduces number of message test failures from 56 to 47.

The patch looks larger than it is because I had to reindent
expose_covered_window_area() and added traces here and there.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    - Repaint the whole nonclient window area on SetWindowPos(SWP_FRAMECHANGED).
    - Repaint windows affected by SetWindowPos immediately.

--- cvs/hq/wine/dlls/x11drv/winpos.c	Sat May  1 18:19:06 2004
+++ wine/dlls/x11drv/winpos.c	Tue May 25 16:56:17 2004
@@ -325,7 +325,7 @@ static void expose_covered_parent_area( 
     if (ret != NULLREGION)
     {
         if (get_covered_region( win, hrgn ) != NULLREGION)
-            expose_window( win->parent, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN );
+            expose_window( win->parent, NULL, hrgn, RDW_INVALIDATE | RDW_ERASENOW | RDW_ALLCHILDREN );
     }
     DeleteObject( hrgn );
 }
@@ -342,42 +342,44 @@ static void expose_covered_window_area( 
     int ret = SIMPLEREGION;
 
     if (frame)
-        hrgn = CreateRectRgn( win->rectWindow.left - win->rectClient.left,
-                              win->rectWindow.top - win->rectClient.top,
-                              win->rectWindow.right - win->rectWindow.left,
-                              win->rectWindow.bottom - win->rectWindow.top );
+        hrgn = 0;
     else
+    {
         hrgn = CreateRectRgn( 0, 0,
                               win->rectClient.right - win->rectClient.left,
                               win->rectClient.bottom - win->rectClient.top );
 
-    /* if the client rect didn't move we don't need to repaint it all */
-    if (old_client_rect->left == win->rectClient.left &&
-        old_client_rect->top == win->rectClient.top)
-    {
-        RECT rc;
-
-        if (IntersectRect( &rc, old_client_rect, &win->rectClient ))
-        {
-            HRGN tmp;
-            /* subtract the unchanged client area from the region to expose */
-            OffsetRect( &rc, -win->rectClient.left, -win->rectClient.top );
-            if ((tmp = CreateRectRgnIndirect( &rc )))
+        /* if the client rect didn't move we don't need to repaint it all */
+        if (old_client_rect->left == win->rectClient.left &&
+            old_client_rect->top == win->rectClient.top)
+        {
+            RECT rc;
+
+            if (IntersectRect( &rc, old_client_rect, &win->rectClient ))
             {
-                ret = CombineRgn( hrgn, hrgn, tmp, RGN_DIFF );
-                DeleteObject( tmp );
+                HRGN tmp;
+                /* subtract the unchanged client area from the region to expose */
+                OffsetRect( &rc, -win->rectClient.left, -win->rectClient.top );
+                if ((tmp = CreateRectRgnIndirect( &rc )))
+                {
+                    ret = CombineRgn( hrgn, hrgn, tmp, RGN_DIFF );
+                    DeleteObject( tmp );
+                }
             }
         }
     }
 
     if (ret != NULLREGION)
     {
-        if (get_covered_region( win, hrgn ) != NULLREGION)
+        if (hrgn)
+            ret = get_covered_region( win, hrgn );
+
+        if (ret != NULLREGION)
             expose_window( win->hwndSelf, NULL, hrgn,
-                           RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
+                           RDW_INVALIDATE | RDW_ERASENOW | RDW_FRAME | RDW_ALLCHILDREN );
     }
 
-    DeleteObject( hrgn );
+    if (hrgn) DeleteObject( hrgn );
 }
 
 
@@ -609,10 +611,11 @@ static UINT SWP_DoNCCalcSize( WINDOWPOS*
         winposCopy = *pWinpos;
         WIN_ReleasePtr( wndPtr );
 
+        TRACE("old client rect %s\n", wine_dbgstr_rect(&params.rgrc[2]));
+
         wvrFlags = SendMessageW( pWinpos->hwnd, WM_NCCALCSIZE, TRUE, (LPARAM)&params );
 
-        TRACE( "(%ld,%ld)-(%ld,%ld)\n", params.rgrc[0].left, params.rgrc[0].top,
-               params.rgrc[0].right, params.rgrc[0].bottom );
+        TRACE("new client rect %s\n", wine_dbgstr_rect(&params.rgrc[0]));
 
         /* If the application send back garbage, ignore it */
         if (params.rgrc[0].left <= params.rgrc[0].right &&
@@ -625,13 +628,19 @@ static UINT SWP_DoNCCalcSize( WINDOWPOS*
 
         if( pNewClientRect->left != wndPtr->rectClient.left ||
             pNewClientRect->top != wndPtr->rectClient.top )
+        {
+            TRACE("client area has moved\n");
             pWinpos->flags &= ~SWP_NOCLIENTMOVE;
+        }
 
         if( (pNewClientRect->right - pNewClientRect->left !=
              wndPtr->rectClient.right - wndPtr->rectClient.left) ||
             (pNewClientRect->bottom - pNewClientRect->top !=
              wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
+        {
+            TRACE("client area has changed size\n");
             pWinpos->flags &= ~SWP_NOCLIENTSIZE;
+        }
     }
     else
     {
@@ -1075,7 +1084,7 @@ BOOL X11DRV_SetWindowPos( WINDOWPOS *win
 
     WIN_ReleaseWndPtr(wndPtr);
 
-    if (wvrFlags & WVR_REDRAW) RedrawWindow( winpos->hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE );
+    if (wvrFlags & WVR_REDRAW) RedrawWindow( winpos->hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASENOW );
 
     if( winpos->flags & SWP_HIDEWINDOW )
         HideCaret(winpos->hwnd);
@@ -1804,7 +1813,7 @@ int X11DRV_SetWindowRgn( HWND hwnd, HRGN
 #endif  /* HAVE_LIBXSHAPE */
 
     WIN_ReleasePtr( wndPtr );
-    if (redraw) RedrawWindow( hwnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE );
+    if (redraw) RedrawWindow( hwnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ERASENOW );
     return TRUE;
 }
 






More information about the wine-patches mailing list