Move scroll from x11drv to USER

Dimitrie O. Paun dpaun at rogers.com
Sat Sep 21 01:29:34 CDT 2002


This patch depends on the previous patch I've sent.

It moves scrolling functions to x11drv to USER.
The X11DRV was dealing with two scroll functions:
  ScrollDC
  ScrollWindowEx

The first one had no X11DRV dependency, while the second
one can now be implemented in USER directly with the help
of the newly exported {Start,End}GraphicsExposures functions.

Mind you that the driver can still provide functions for
these operations, if it thinks it can do a better job than
the USER. If the driver does not provide an implemention
for these functions, USER will default to its own implementation.

Oh, BTW, you should also do:
	cvs rm -f dlls/x11drv/scroll.c
after applying this patch.

ChangeLog
  Move scroll from x11drv to USER, and make scrolling functions
  optional in a USER driver.

Index: dlls/x11drv/Makefile.in
===================================================================
RCS file: /var/cvs/wine/dlls/x11drv/Makefile.in,v
retrieving revision 1.26
diff -u -r1.26 Makefile.in
--- dlls/x11drv/Makefile.in	6 Sep 2002 18:51:32 -0000	1.26
+++ dlls/x11drv/Makefile.in	21 Sep 2002 05:14:53 -0000
@@ -30,7 +30,6 @@
 	event.c \
 	keyboard.c \
 	mouse.c \
-	scroll.c \
 	window.c \
 	winpos.c \
 	x11ddraw.c \
Index: dlls/x11drv/x11drv.spec
===================================================================
RCS file: /var/cvs/wine/dlls/x11drv/x11drv.spec,v
retrieving revision 1.39
diff -u -r1.39 x11drv.spec
--- dlls/x11drv/x11drv.spec	27 Aug 2002 19:19:49 -0000	1.39
+++ dlls/x11drv/x11drv.spec	21 Sep 2002 05:59:48 -0000
@@ -79,8 +79,6 @@
 @ cdecl GetDC(long long long long) X11DRV_GetDC
 @ cdecl ForceWindowRaise(long) X11DRV_ForceWindowRaise
 @ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) X11DRV_MsgWaitForMultipleObjectsEx
-@ cdecl ScrollDC(long long long ptr ptr long ptr) X11DRV_ScrollDC
-@ cdecl ScrollWindowEx(long long long ptr ptr long ptr long) X11DRV_ScrollWindowEx
 @ cdecl SetFocus(long) X11DRV_SetFocus
 @ cdecl SetParent(long long) X11DRV_SetParent
 @ cdecl SetWindowPos(ptr) X11DRV_SetWindowPos
Index: windows/scroll.c
===================================================================
RCS file: /var/cvs/wine/windows/scroll.c,v
retrieving revision 1.37
diff -u -r1.37 scroll.c
--- windows/scroll.c	20 Sep 2002 19:35:54 -0000	1.37
+++ windows/scroll.c	21 Sep 2002 05:54:49 -0000
@@ -1,8 +1,10 @@
 /*
  * Scroll windows and DCs
  *
- * Copyright  David W. Metcalfe, 1993
- *	      Alex Korobka       1995,1996
+ * Copyright 1993 David W. Metcalfe
+ * Copyright 1995, 1996 Alex Korobka
+ * Copyright 2001 Alexandre Julliard
+ * Copyright 2002 Dimitrie O. Paun
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -95,19 +97,176 @@
 
 
 /*************************************************************************
+ *		USER_ScrollDC [Internal]
+ *
+ * Internal implementation of the ScrollDC function.
+ */
+static BOOL USER_ScrollDC( HDC hdc, INT dx, INT dy, const RECT *rc,
+                           const RECT *clipRect, HRGN hrgnUpdate, LPRECT rcUpdate )
+{
+    RECT rect, rClip, rDst;
+    
+    /* compute device clipping region (in device coordinates) */
+
+    if (rc) rect = *rc;
+    else GetClipBox( hdc, &rect );
+
+    if (clipRect)
+    {
+        rClip = *clipRect;
+        IntersectRect( &rClip, &rect, &rClip );
+    }
+    else rClip = rect;
+
+    rDst = rClip;
+    OffsetRect( &rDst, dx,  dy );
+    IntersectRect( &rDst, &rDst, &rClip );
+
+    if (!IsRectEmpty(&rDst))
+    {
+        /* copy bits */
+        if (!BitBlt( hdc, rDst.left, rDst.top,
+                     rDst.right - rDst.left, rDst.bottom - rDst.top,
+                     hdc, rDst.left - dx, rDst.top - dy, SRCCOPY))
+            return FALSE;
+    }
+
+    /* compute update areas */
+
+    if (hrgnUpdate || rcUpdate)
+    {
+        HRGN hrgn = hrgnUpdate, hrgn2;
+
+        /* map everything to device coordinates */
+        LPtoDP( hdc, (LPPOINT)&rClip, 2 );
+        LPtoDP( hdc, (LPPOINT)&rDst, 2 );
+
+        hrgn2 = CreateRectRgnIndirect( &rDst );
+        if (hrgn) SetRectRgn( hrgn, rClip.left, rClip.top, rClip.right, rClip.bottom );
+        else hrgn = CreateRectRgn( rClip.left, rClip.top, rClip.right, rClip.bottom );
+        CombineRgn( hrgn, hrgn, hrgn2, RGN_DIFF );
+
+        if( rcUpdate )
+        {
+            GetRgnBox( hrgn, rcUpdate );
+
+            /* Put the rcUpdate in logical coordinate */
+            DPtoLP( hdc, (LPPOINT)rcUpdate, 2 );
+        }
+        if (!hrgnUpdate) DeleteObject( hrgn );
+        DeleteObject( hrgn2 );
+    }
+    return TRUE;
+}
+    
+/*************************************************************************
  *		ScrollDC (USER32.@)
  *
  *   Only the hrgnUpdate is return in device coordinate.
  *   rcUpdate must be returned in logical coordinate to comply with win API.
+ *   FIXME: the doc explicitly states the opposite, to be checked
  *
  */
 BOOL WINAPI ScrollDC( HDC hdc, INT dx, INT dy, const RECT *rc,
-                          const RECT *prLClip, HRGN hrgnUpdate,
-                          LPRECT rcUpdate )
+                      const RECT *clipRect, HRGN hrgnUpdate, LPRECT rcUpdate )
 {
+    TRACE( "%04x %d,%d hrgnUpdate=%04x rcUpdate = %p\n", hdc, dx, dy, hrgnUpdate, rcUpdate );
+    
+    if (clipRect) TRACE( "cliprc = (%d,%d,%d,%d)\n",
+                         clipRect->left, clipRect->top, clipRect->right, clipRect->bottom );
+    
+    if (rc) TRACE( "rc = (%d,%d,%d,%d)\n", rc->left, rc->top, rc->right, rc->bottom );
+
     if (USER_Driver.pScrollDC)
-        return USER_Driver.pScrollDC( hdc, dx, dy, rc, prLClip, hrgnUpdate, rcUpdate );
-    return FALSE;
+        return USER_Driver.pScrollDC( hdc, dx, dy, rc, clipRect, hrgnUpdate, rcUpdate );
+    else
+	return USER_ScrollDC( hdc, dx, dy, rc, clipRect, hrgnUpdate, rcUpdate );
+}
+
+/*************************************************************************
+ *		USER_ScrollWindowEx   [Internal]
+ *
+ * Note: contrary to what the doc says, pixels that are scrolled from the
+ *      outside of clipRect to the inside are NOT painted.
+ *
+ * Parameter are the same as in ScrollWindowEx, with the additional
+ * requirement that rect and clipRect are _valid_ pointers, to
+ * rectangles _within_ the client are. Moreover, there is something
+ * to scroll.
+ */
+static INT USER_ScrollWindowEx( HWND hwnd, INT dx, INT dy,
+                                const RECT *rect, const RECT *clipRect,
+                                HRGN hrgnUpdate, LPRECT rcUpdate, UINT flags )
+{
+    INT   retVal;
+    BOOL  bOwnRgn = TRUE;
+    BOOL  bUpdate = (rcUpdate || hrgnUpdate || flags & (SW_INVALIDATE | SW_ERASE));
+    HRGN  hrgnClip = CreateRectRgnIndirect(clipRect);
+    HRGN  hrgnTemp;
+    HDC   hDC;
+
+    TRACE( "%04x, %d,%d hrgnUpdate=%04x rcUpdate = %p rect=(%d,%d-%d,%d) %04x\n",
+           hwnd, dx, dy, hrgnUpdate, rcUpdate,
+           rect->left, rect->top, rect->right, rect->bottom, flags );
+    TRACE( "clipRect = (%d,%d,%d,%d)\n",
+           clipRect->left, clipRect->top, clipRect->right, clipRect->bottom );
+
+    if( hrgnUpdate ) bOwnRgn = FALSE;
+    else if( bUpdate ) hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
+
+    hDC = GetDCEx( hwnd, 0, DCX_CACHE | DCX_USESTYLE );
+    if (hDC)
+    {
+        HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
+        USER_Driver.pStartGraphicsExposures( hDC );
+        ScrollDC( hDC, dx, dy, rect, clipRect, hrgnUpdate, rcUpdate );
+        USER_Driver.pEndGraphicsExposures( hDC, hrgn );
+        ReleaseDC( hwnd, hDC );
+        if (bUpdate) CombineRgn( hrgnUpdate, hrgnUpdate, hrgn, RGN_OR );
+        else RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE );
+        DeleteObject( hrgn );
+    }
+
+    /* Take into account the fact that some damages may have occured during the scroll */
+    hrgnTemp = CreateRectRgn( 0, 0, 0, 0 );
+    retVal = GetUpdateRgn( hwnd, hrgnTemp, FALSE );
+    if (retVal != NULLREGION)
+    {
+        OffsetRgn( hrgnTemp, dx, dy );
+        CombineRgn( hrgnTemp, hrgnTemp, hrgnClip, RGN_AND );
+        RedrawWindow( hwnd, NULL, hrgnTemp, RDW_INVALIDATE | RDW_ERASE );
+    }
+    DeleteObject( hrgnTemp );
+
+    if( flags & SW_SCROLLCHILDREN )
+    {
+        HWND *list = WIN_ListChildren( hwnd );
+        if (list)
+        {
+            int i;
+            RECT r, dummy;
+            for (i = 0; list[i]; i++)
+            {
+                GetWindowRect( list[i], &r );
+                MapWindowPoints( 0, hwnd, (POINT *)&r, 2 );
+                if (!rect || IntersectRect(&dummy, &r, rect))
+                    SetWindowPos( list[i], 0, r.left + dx, r.top  + dy, 0, 0,
+                                  SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE |
+                                  SWP_NOREDRAW | SWP_DEFERERASE );
+            }
+            HeapFree( GetProcessHeap(), 0, list );
+        }
+    }
+
+    if( flags & (SW_INVALIDATE | SW_ERASE) )
+        RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
+                      ((flags & SW_ERASE) ? RDW_ERASENOW : 0) |
+                      ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0 ) );
+
+    if( bOwnRgn && hrgnUpdate ) DeleteObject( hrgnUpdate );
+    DeleteObject( hrgnClip );
+    
+    return retVal;
 }
 
 
@@ -142,7 +301,8 @@
             result = USER_Driver.pScrollWindowEx( hwnd, dx, dy, &rc, &cliprc,
                                                   hrgnUpdate, rcUpdate, flags );
 	else
-	    result = ERROR; /* FIXME: we should have a fallback implementation */
+	    result = USER_ScrollWindowEx( hwnd, dx, dy, &rc, &cliprc,
+			    		  hrgnUpdate, rcUpdate, flags );
 	
         if( hwndCaret )
         {
@@ -155,3 +315,4 @@
     
     return result;
 }
+




More information about the wine-patches mailing list