ScrollDC fixes.

Rein Klazes wijn at wanadoo.nl
Fri Mar 4 10:10:20 CST 2005


Hi,

This solves a number of scroll defects: areas that are not properly
repainted and flickering's. 
The observation here is that the DC's visible region should be included
in the calculations. The changelog should explain.

Changelog:

dlls/x11drv	: scroll.c, init.c
windows		: scroll.c
dlls/user/tests	: win.c, msg.c

ScrollDC and X11DRV_SCROLLDC should scroll only pixels coming from
within the visible region. Add the destination of pixels coming from the
outside of the visible region to the update region. With a test that
depends on this.

Rein.
-------------- next part --------------
--- wine/dlls/x11drv/scroll.c	2005-01-17 20:17:47.000000000 +0100
+++ mywine/dlls/x11drv/scroll.c	2005-03-04 10:34:38.000000000 +0100
@@ -35,96 +35,157 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(scroll);
 
+void dump_region( char *p, HRGN hrgn)
+{
+    DWORD i, size;
+    RGNDATA *data = NULL;
+    RECT *rect;
+
+    if (!hrgn) {
+        TRACE( "%s null region\n", p );
+        return;
+    }
+    if (!(size = GetRegionData( hrgn, 0, NULL ))) {
+        return;
+    }
+    if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
+    GetRegionData( hrgn, size, data );
+    TRACE("%s %ld rects:", p, data->rdh.nCount );
+    for (i = 0, rect = (RECT *)data->Buffer; i<20 && i < data->rdh.nCount; i++, rect++)
+        TRACE( " %s", wine_dbgstr_rect( rect));
+    TRACE("\n");
+    HeapFree( GetProcessHeap(), 0, data );
+}
 
 /*************************************************************************
  *		ScrollDC   (X11DRV.@)
  */
 BOOL X11DRV_ScrollDC( HDC hdc, INT dx, INT dy, const RECT *lprcScroll,
-                      const RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate )
-
+        const RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate )
 {
-    RECT rSrc, rClipped_src, rClip, rDst, offset;
+    RECT rcSrc, rcClip, offset;
+    INT dxdev, dydev, res;
+    HRGN SrcRgn, visrgn;
     INT code = X11DRV_START_EXPOSURES;
 
+    TRACE("dx,dy %d,%d lprcScroll %p lprcClip %p hrgnUpdate %p lprcUpdate %p\n",
+            dx, dy, lprcScroll, lprcClip, hrgnUpdate, lprcUpdate);
+    /* enable X-exposure events */
     if (hrgnUpdate || lprcUpdate)
         ExtEscape( hdc, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code, 0, NULL );
-
-    /* compute device clipping region (in device coordinates) */
-
-    if (lprcScroll) rSrc = *lprcScroll;
-    else GetClipBox( hdc, &rSrc );
-    LPtoDP(hdc, (LPPOINT)&rSrc, 2);
-
-    if (lprcClip) rClip = *lprcClip;
-    else GetClipBox( hdc, &rClip );
-    LPtoDP(hdc, (LPPOINT)&rClip, 2);
-
-    IntersectRect( &rClipped_src, &rSrc, &rClip );
-    TRACE("rSrc %s rClip %s clipped rSrc %s\n", wine_dbgstr_rect(&rSrc),
-          wine_dbgstr_rect(&rClip), wine_dbgstr_rect(&rClipped_src));
-
-    rDst = rClipped_src;
+    /* get the visible region */
+    visrgn=CreateRectRgn( 0, 0, 0, 0);
+    GetRandomRgn( hdc, visrgn, SYSRGN);
+    if( !(GetVersion() & 0x80000000)) {
+        /* Window NT/2k/XP */
+        POINT org;
+        GetDCOrgEx(hdc, &org);
+        OffsetRgn( visrgn, -org.x, -org.y);
+    }
+    /* only those pixels in the scroll rectangle that remain in the clipping
+     * rect are scrolled. So first combine Scroll and Clipping rectangles,
+     * if available */
+    if( lprcScroll)
+        if( lprcClip)
+            IntersectRect( &rcClip, lprcClip, lprcScroll);
+        else
+            rcClip = *lprcScroll;
+    else
+        if( lprcClip)
+            rcClip = *lprcClip;
+        else
+            GetClipBox( hdc, &rcClip);
+    /* Then clip again to get the source rectangle that will remain in the
+     * clipping rect */
+    rcSrc = rcClip;
+    OffsetRect( &rcSrc, -dx, -dy);
+    IntersectRect( &rcSrc, &rcSrc, &rcClip);
+    /* now convert to device coordinates */
+    LPtoDP(hdc, (LPPOINT)&rcSrc, 2);
+    /* also dx and dy */
     SetRect(&offset, 0, 0, dx, dy);
     LPtoDP(hdc, (LPPOINT)&offset, 2);
-    OffsetRect( &rDst, offset.right - offset.left,  offset.bottom - offset.top );
-    TRACE("rDst before clipping %s\n", wine_dbgstr_rect(&rDst));
-    IntersectRect( &rDst, &rDst, &rClip );
-    TRACE("rDst after clipping %s\n", wine_dbgstr_rect(&rDst));
-
-    if (!IsRectEmpty(&rDst))
-    {
-        /* copy bits */
-        RECT rDst_lp = rDst, rSrc_lp = rDst;
-
-        OffsetRect( &rSrc_lp, offset.left - offset.right, offset.top - offset.bottom );
-        DPtoLP(hdc, (LPPOINT)&rDst_lp, 2);
-        DPtoLP(hdc, (LPPOINT)&rSrc_lp, 2);
-
-        if (!BitBlt( hdc, rDst_lp.left, rDst_lp.top,
-                     rDst_lp.right - rDst_lp.left, rDst_lp.bottom - rDst_lp.top,
-                     hdc, rSrc_lp.left, rSrc_lp.top, SRCCOPY))
-            return FALSE;
+    dxdev = offset.right - offset.left;
+    dydev= offset.bottom - offset.top;
+    /* now intersect with the visible region to get the pixels that will
+     * actually scroll */
+    SrcRgn = CreateRectRgnIndirect( &rcSrc);
+    res = CombineRgn( SrcRgn, SrcRgn, visrgn, RGN_AND);
+    if( TRACE_ON( scroll)) dump_region( "Source scroll region: ", SrcRgn);
+    /* if there are any, do it */
+    if( res > NULLREGION) {
+        DWORD i, size;
+        int step;
+        RECT *rect;
+        RGNDATA *rdata = NULL;
+        if(( size = GetRegionData( SrcRgn, 0, NULL )) &&
+                (rdata = HeapAlloc( GetProcessHeap(), 0, size ))) {
+            GetRegionData( SrcRgn, size, rdata );
+            /* the rectangles in the region data are ordered top-to-bottom
+             * So if the scrolling is downward, traverse the array backwards
+             * to avoid touching pixels that have yet to be scrolled  */
+            /* FIXME: implement something similar for left-to-right
+             * scrolling. */
+            if( dydev < 0 ) {
+                step = 1;
+                rect = (RECT *)rdata->Buffer;
+            } else {
+                step = -1;
+                rect = ((RECT *)rdata->Buffer) + rdata->rdh.nCount - 1;
+            }
+            for( i = 0; i < rdata->rdh.nCount; i++, rect += step) {
+                DPtoLP(hdc, (LPPOINT)rect, 2);
+                TRACE("Bit blitting %s to %ld,%ld\n", wine_dbgstr_rect(rect),
+                        rect->left + dx, rect->top + dy);
+                BitBlt( hdc, rect->left + dx, rect->top + dy,
+                            rect->right - rect->left, rect->bottom -rect->top,
+                            hdc, rect->left, rect->top, SRCCOPY);
+            }
+            HeapFree( GetProcessHeap(), 0, rdata );
+        } else
+            ERR("Out of memory\n");
     }
-
-    /* compute update areas.  This is the clipped source or'ed with the unclipped source translated minus the
-     clipped src translated (rDst) all clipped to rClip */
-
+    /* compute the update areas.  This is the combined clip rectangle
+     * minus the scrolled region, and intersected with the visible
+     * region. */
     if (hrgnUpdate || lprcUpdate)
     {
-        HRGN hrgn = hrgnUpdate, hrgn2, hrgn3 = 0;
+        HRGN hrgn = hrgnUpdate;
+        HRGN ExpRgn = 0;
+        HRGN DstRgn;
 
+        /* collect all the exposures */
         code = X11DRV_END_EXPOSURES;
-        ExtEscape( hdc, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code, sizeof(hrgn3), (LPSTR)&hrgn3 );
-
-        if (hrgn) SetRectRgn( hrgn, rClipped_src.left, rClipped_src.top, rClipped_src.right, rClipped_src.bottom );
-        else hrgn = CreateRectRgn( rClipped_src.left, rClipped_src.top, rClipped_src.right, rClipped_src.bottom );
-
-        hrgn2 = CreateRectRgnIndirect( &rSrc );
-        OffsetRgn(hrgn2, offset.right - offset.left,  offset.bottom - offset.top );
-        CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
-
-        SetRectRgn( hrgn2, rDst.left, rDst.top, rDst.right, rDst.bottom );
-        CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF );
-
-        SetRectRgn( hrgn2, rClip.left, rClip.top, rClip.right, rClip.bottom );
-        CombineRgn( hrgn, hrgn, hrgn2, RGN_AND );
-
-        if (hrgn3)
-        {
-            CombineRgn( hrgn, hrgn, hrgn3, RGN_OR );
-            DeleteObject( hrgn3 );
+        ExtEscape( hdc, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code,
+                sizeof(ExpRgn), (LPSTR)&ExpRgn );
+        /* still needs to be converted to device coordinates */
+        LPtoDP(hdc, (LPPOINT)&rcClip, 2);
+        if( hrgn )
+            SetRectRgn( hrgn, rcClip.left, rcClip.top, rcClip.right,
+                    rcClip.bottom);
+        else
+            hrgn = CreateRectRgnIndirect( &rcClip);
+        DstRgn = SrcRgn; /* change the name */
+        OffsetRgn( DstRgn, dxdev, dydev);
+        CombineRgn( hrgn, hrgn, visrgn, RGN_AND);
+        CombineRgn( hrgn, hrgn, DstRgn, RGN_DIFF);
+        /* add the exposures to this */
+        if( ExpRgn) {
+            if( TRACE_ON( scroll)) dump_region( "Expose region: ", ExpRgn);
+            CombineRgn( hrgn, hrgn, ExpRgn, RGN_OR );
+            DeleteObject( ExpRgn );
         }
-
-        if( lprcUpdate )
-        {
+        if( TRACE_ON( scroll)) dump_region( "Update region: ", hrgn);
+        if( lprcUpdate ) {
             GetRgnBox( hrgn, lprcUpdate );
-
             /* Put the lprcUpdate in logical coordinate */
             DPtoLP( hdc, (LPPOINT)lprcUpdate, 2 );
             TRACE("returning lprcUpdate %s\n", wine_dbgstr_rect(lprcUpdate));
         }
-        if (!hrgnUpdate) DeleteObject( hrgn );
-        DeleteObject( hrgn2 );
+        if( !hrgnUpdate)
+            DeleteObject( hrgn);
     }
+    DeleteObject( visrgn );
+    DeleteObject( SrcRgn );
     return TRUE;
 }
--- wine/dlls/x11drv/init.c	2004-11-30 22:38:58.000000000 +0100
+++ mywine/dlls/x11drv/init.c	2005-03-03 21:19:21.000000000 +0100
@@ -353,6 +353,7 @@ INT X11DRV_ExtEscape( X11DRV_PDEVICE *ph
                     HRGN hrgn = 0, tmp = 0;
 
                     wine_tsx11_lock();
+                    XFlush( gdi_display);
                     XSetGraphicsExposures( gdi_display, physDev->gc, False );
                     if (physDev->exposures)
                     {
@@ -360,8 +361,9 @@ INT X11DRV_ExtEscape( X11DRV_PDEVICE *ph
                         {
                             XEvent event;
 
-                            XWindowEvent( gdi_display, physDev->drawable, ~0, &event );
-                            if (event.type == NoExpose) break;
+                            if( !XCheckWindowEvent( gdi_display, physDev->drawable, ~0, &event ))
+                                break;
+                            if (event.type == NoExpose) continue;
                             if (event.type == GraphicsExpose)
                             {
                                 int x = event.xgraphicsexpose.x - physDev->org.x;
@@ -382,7 +384,6 @@ INT X11DRV_ExtEscape( X11DRV_PDEVICE *ph
                                     hrgn = tmp;
                                     tmp = 0;
                                 }
-                                if (!event.xgraphicsexpose.count) break;
                             }
                             else
                             {
--- wine/windows/scroll.c	2005-02-08 15:27:39.000000000 +0100
+++ mywine/windows/scroll.c	2005-03-04 12:52:04.000000000 +0100
@@ -185,17 +185,42 @@ BOOL WINAPI ScrollWindow( HWND hwnd, INT
                                     SW_INVALIDATE ));
 }
 
+static void dump_region( char *p, HRGN hrgn)
+{
+    DWORD i, size;
+    RGNDATA *data = NULL;
+    RECT *rect;
+
+    if (!hrgn) {
+        TRACE( "%s null region\n", p );
+        return;
+    }
+    if (!(size = GetRegionData( hrgn, 0, NULL ))) {
+        return;
+    }
+    if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return;
+    GetRegionData( hrgn, size, data );
+    TRACE("%s %ld rects:", p, data->rdh.nCount );
+    for (i = 0, rect = (RECT *)data->Buffer; i<20 && i < data->rdh.nCount; i++, rect++)
+        TRACE( " %s", wine_dbgstr_rect( rect));
+    TRACE("\n");
+    HeapFree( GetProcessHeap(), 0, data );
+}
+
 /*************************************************************************
  *		ScrollDC (USER32.@)
  *
- * dx, dy, lprcScroll and lprcClip are all in logical coordinates (msdn is wrong)
- * hrgnUpdate is returned in device coordinates with rcUpdate in logical coordinates.
+ * dx, dy, lprcScroll and lprcClip are all in logical coordinates (msdn is
+ * wrong) hrgnUpdate is returned in device coordinates with rcUpdate in
+ * logical coordinates.
  */
 BOOL WINAPI ScrollDC( HDC hdc, INT dx, INT dy, const RECT *lprcScroll,
-                      const RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate )
+        const RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate )
 
 {
-    RECT rSrc, rClipped_src, rClip, rDst, offset;
+    RECT rcSrc, rcClip, offset;
+    INT dxdev, dydev, res;
+    HRGN SrcRgn, visrgn;
 
     TRACE( "%p %d,%d hrgnUpdate=%p lprcUpdate = %p\n", hdc, dx, dy, hrgnUpdate, lprcUpdate );
     if (lprcClip) TRACE( "lprcClip = %s\n", wine_dbgstr_rect(lprcClip));
@@ -204,72 +229,109 @@ BOOL WINAPI ScrollDC( HDC hdc, INT dx, I
     if (USER_Driver.pScrollDC)
         return USER_Driver.pScrollDC( hdc, dx, dy, lprcScroll, lprcClip, hrgnUpdate, lprcUpdate );
 
-    /* compute device clipping region (in device coordinates) */
-    if (lprcScroll) rSrc = *lprcScroll;
-    else GetClipBox( hdc, &rSrc );
-    LPtoDP(hdc, (LPPOINT)&rSrc, 2);
-
-    if (lprcClip) rClip = *lprcClip;
-    else GetClipBox( hdc, &rClip );
-    LPtoDP(hdc, (LPPOINT)&rClip, 2);
-
-    IntersectRect( &rClipped_src, &rSrc, &rClip );
-    TRACE("rSrc %s rClip %s clipped rSrc %s\n", wine_dbgstr_rect(&rSrc),
-          wine_dbgstr_rect(&rClip), wine_dbgstr_rect(&rClipped_src));
-
-    rDst = rClipped_src;
+    /* get the visible region */
+    visrgn=CreateRectRgn( 0, 0, 0, 0);
+    GetRandomRgn( hdc, visrgn, SYSRGN);
+    if( !(GetVersion() & 0x80000000)) {
+        /* Window NT/2k/XP */
+        POINT org;
+        GetDCOrgEx(hdc, &org);
+        OffsetRgn( visrgn, -org.x, -org.y);
+    }
+    /* only those pixels in the scroll rectangle that remain in the clipping
+     * rect are scrolled. So first combine Scroll and Clipping rectangles,
+     * if available */
+    if( lprcScroll)
+        if( lprcClip)
+            IntersectRect( &rcClip, lprcClip, lprcScroll);
+        else
+            rcClip = *lprcScroll;
+    else
+        if( lprcClip)
+            rcClip = *lprcClip;
+        else
+            GetClipBox( hdc, &rcClip);
+    /* Then clip again to get the source rectangle that will remain in the
+     * clipping rect */
+    rcSrc = rcClip;
+    OffsetRect( &rcSrc, -dx, -dy);
+    IntersectRect( &rcSrc, &rcSrc, &rcClip);
+    /* now convert to device coordinates */
+    LPtoDP(hdc, (LPPOINT)&rcSrc, 2);
+    /* also dx and dy */
     SetRect(&offset, 0, 0, dx, dy);
     LPtoDP(hdc, (LPPOINT)&offset, 2);
-    OffsetRect( &rDst, offset.right - offset.left,  offset.bottom - offset.top );
-    TRACE("rDst before clipping %s\n", wine_dbgstr_rect(&rDst));
-    IntersectRect( &rDst, &rDst, &rClip );
-    TRACE("rDst after clipping %s\n", wine_dbgstr_rect(&rDst));
-
-    if (!IsRectEmpty(&rDst))
-    {
-        /* copy bits */
-        RECT rDst_lp = rDst, rSrc_lp = rDst;
-
-        OffsetRect( &rSrc_lp, offset.left - offset.right, offset.top - offset.bottom );
-        DPtoLP(hdc, (LPPOINT)&rDst_lp, 2);
-        DPtoLP(hdc, (LPPOINT)&rSrc_lp, 2);
-
-        if (!BitBlt( hdc, rDst_lp.left, rDst_lp.top,
-                     rDst_lp.right - rDst_lp.left, rDst_lp.bottom - rDst_lp.top,
-                     hdc, rSrc_lp.left, rSrc_lp.top, SRCCOPY))
-            return FALSE;
+    dxdev = offset.right - offset.left;
+    dydev= offset.bottom - offset.top;
+    /* now intersect with the visible region to get the pixels that will
+     * actually scroll */
+    SrcRgn = CreateRectRgnIndirect( &rcSrc);
+    res = CombineRgn( SrcRgn, SrcRgn, visrgn, RGN_AND);
+    if( TRACE_ON( scroll)) dump_region( "Source scroll region: ", SrcRgn);
+    /* if there are any, do it */
+    if( res > NULLREGION) {
+        DWORD i, size;
+        int step;
+        RECT *rect;
+        RGNDATA *rdata = NULL;
+        if(( size = GetRegionData( SrcRgn, 0, NULL )) &&
+                (rdata = HeapAlloc( GetProcessHeap(), 0, size ))) {
+            GetRegionData( SrcRgn, size, rdata );
+            /* the rectangles in the region data are ordered top-to-bottom
+             * So if the scrolling is downward, traverse the array backwards
+             * to avoid touching pixels that have yet to be scrolled  */
+            /* FIXME: implement something similar for left-to-right
+             * scrolling. */
+            if( dydev < 0 ) {
+                step = 1;
+                rect = (RECT *)rdata->Buffer;
+            } else {
+                step = -1;
+                rect = ((RECT *)rdata->Buffer) + rdata->rdh.nCount - 1;
+            }
+            for( i = 0; i < rdata->rdh.nCount; i++, rect += step) {
+                DPtoLP(hdc, (LPPOINT)rect, 2);
+                TRACE("Bit blitting %s to %ld,%ld\n", wine_dbgstr_rect(rect),
+                        rect->left + dx, rect->top + dy);
+                BitBlt( hdc, rect->left + dx, rect->top + dy,
+                            rect->right - rect->left, rect->bottom -rect->top,
+                            hdc, rect->left, rect->top, SRCCOPY);
+            }
+            HeapFree( GetProcessHeap(), 0, rdata );
+        } else
+            ERR("Out of memory\n");
     }
-
-    /* compute update areas.  This is the clipped source or'ed with the unclipped source translated minus the
-     clipped src translated (rDst) all clipped to rClip */
-
+    /* compute the update areas.  This is the combined clip rectangle
+     * minus the scrolled region, and intersected with the visible
+     * region. */
     if (hrgnUpdate || lprcUpdate)
     {
-        HRGN hrgn = hrgnUpdate, hrgn2;
-
-        if (hrgn) SetRectRgn( hrgn, rClipped_src.left, rClipped_src.top, rClipped_src.right, rClipped_src.bottom );
-        else hrgn = CreateRectRgn( rClipped_src.left, rClipped_src.top, rClipped_src.right, rClipped_src.bottom );
-
-        hrgn2 = CreateRectRgnIndirect( &rSrc );
-        OffsetRgn(hrgn2, offset.right - offset.left,  offset.bottom - offset.top );
-        CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
-
-        SetRectRgn( hrgn2, rDst.left, rDst.top, rDst.right, rDst.bottom );
-        CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF );
+        HRGN hrgn = hrgnUpdate;
+        HRGN DstRgn;
 
-        SetRectRgn( hrgn2, rClip.left, rClip.top, rClip.right, rClip.bottom );
-        CombineRgn( hrgn, hrgn, hrgn2, RGN_AND );
+        /* still needs to be converted to device coordinates */
+        LPtoDP(hdc, (LPPOINT)&rcClip, 2);
+        if( hrgn )
+            SetRectRgn( hrgn, rcClip.left, rcClip.top, rcClip.right,
+                    rcClip.bottom);
+        else
+            hrgn = CreateRectRgnIndirect( &rcClip);
+        DstRgn = SrcRgn; /* change the name */
+        OffsetRgn( DstRgn, dxdev, dydev);
+        CombineRgn( hrgn, hrgn, visrgn, RGN_AND);
+        CombineRgn( hrgn, hrgn, DstRgn, RGN_DIFF);
 
-        if( lprcUpdate )
-        {
+        if( TRACE_ON( scroll)) dump_region( "Update region: ", hrgn);
+        if( lprcUpdate ) {
             GetRgnBox( hrgn, lprcUpdate );
-
             /* Put the lprcUpdate in logical coordinate */
             DPtoLP( hdc, (LPPOINT)lprcUpdate, 2 );
             TRACE("returning lprcUpdate %s\n", wine_dbgstr_rect(lprcUpdate));
         }
-        if (!hrgnUpdate) DeleteObject( hrgn );
-        DeleteObject( hrgn2 );
+        if( !hrgnUpdate)
+            DeleteObject( hrgn);
     }
+    DeleteObject( visrgn );
+    DeleteObject( SrcRgn );
     return TRUE;
 }
--- wine/dlls/user/tests/win.c	2005-03-01 10:16:21.000000000 +0100
+++ mywine/dlls/user/tests/win.c	2005-03-04 14:12:33.000000000 +0100
@@ -45,6 +45,8 @@
 #define LONG_PTR INT_PTR
 #define ULONG_PTR UINT_PTR
 
+void dump_region(HRGN hrgn);
+
 static HWND (WINAPI *pGetAncestor)(HWND,UINT);
 static BOOL (WINAPI *pGetWindowInfo)(HWND,WINDOWINFO*);
 
@@ -2333,6 +2335,48 @@ void test_nccalcscroll( HWND parent)
 
     DestroyWindow( hwnd);
 }
+
+void test_scrollvalidate( HWND parent)
+{
+    HDC hdc;
+    HRGN hrgn=CreateRectRgn(0,0,0,0);
+    HRGN exprgn, tmprgn;
+    RECT rc, rcu, cliprc;
+    /* create two overlapping child windows. The visual region
+     * of hwnd1 is clipped by the overlapping part of
+     * hwnd2 because of the WS_CLIPSIBLING style */
+    HWND hwnd2 = CreateWindowExA(0, "static", NULL, 
+            WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER , 
+            75, 50, 100, 100, parent, 0, 0, NULL); 
+    HWND hwnd1 = CreateWindowExA(0, "static", NULL, 
+            WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER , 
+            25, 70, 100, 100, parent, 0, 0, NULL); 
+    ShowWindow( parent, SW_SHOW);
+    UpdateWindow( parent);
+    GetClientRect( hwnd1, &rc);
+    cliprc=rc; 
+    hdc = GetDC( hwnd1);
+    /* for a visual touch */
+    TextOut( hdc, 0,10, "0123456789", 10);
+    ScrollDC( hdc, -10, -5, &rc, &cliprc, hrgn, &rcu);
+    dump_region(hrgn);
+    /* create a region with what is expected */
+    exprgn = CreateRectRgn( 39,0,49,74);
+    tmprgn = CreateRectRgn( 88,79,98,93);
+    CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
+    tmprgn = CreateRectRgn( 0, 93,98,98);
+    CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
+    ok( EqualRgn( exprgn, exprgn), "wrong update region\n");
+    trace("update rect is %ld,%ld - %ld,%ld\n",
+            rcu.left,rcu.top,rcu.right,rcu.bottom);
+    /* clean up */
+    DeleteObject( hrgn);
+    DeleteObject( exprgn);
+    DeleteObject( tmprgn);
+    DestroyWindow( hwnd1);
+    DestroyWindow( hwnd2);
+}
+
 START_TEST(win)
 {
     pGetAncestor = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetAncestor" );
@@ -2390,6 +2434,7 @@ START_TEST(win)
     test_mouse_input(hwndMain);
     test_validatergn(hwndMain);
     test_nccalcscroll( hwndMain);
+    test_scrollvalidate( hwndMain);
 
     UnhookWindowsHookEx(hhook);
 }
--- wine/dlls/user/tests/msg.c	2005-03-01 10:16:20.000000000 +0100
+++ mywine/dlls/user/tests/msg.c	2005-03-01 12:27:21.000000000 +0100
@@ -3305,7 +3305,7 @@ static void test_button_messages(void)
 
 /************* painting message test ********************/
 
-static void dump_region(HRGN hrgn)
+void dump_region(HRGN hrgn)
 {
     DWORD i, size;
     RGNDATA *data = NULL;


More information about the wine-patches mailing list