2 * Scroll windows and DCs
4 * Copyright 1993 David W. Metcalfe
5 * Copyright 1995, 1996 Alex Korobka
6 * Copyright 2001 Alexandre Julliard
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(scroll
);
38 /*************************************************************************
41 * Only the hrgnUpdate is returned in device coordinates.
42 * rcUpdate must be returned in logical coordinates to comply with win API.
43 * FIXME: the doc explicitly states the opposite, to be checked
45 BOOL
X11DRV_ScrollDC( HDC hdc
, INT dx
, INT dy
, const RECT
*rc
,
46 const RECT
*clipRect
, HRGN hrgnUpdate
, LPRECT rcUpdate
)
48 RECT rect
, rClip
, rDst
;
50 TRACE( "%p %d,%d hrgnUpdate=%p rcUpdate = %p\n", hdc
, dx
, dy
, hrgnUpdate
, rcUpdate
);
51 if (clipRect
) TRACE( "cliprc = (%ld,%ld,%ld,%ld)\n",
52 clipRect
->left
, clipRect
->top
, clipRect
->right
, clipRect
->bottom
);
53 if (rc
) TRACE( "rc = (%ld,%ld,%ld,%ld)\n", rc
->left
, rc
->top
, rc
->right
, rc
->bottom
);
55 /* compute device clipping region (in device coordinates) */
58 else GetClipBox( hdc
, &rect
);
63 IntersectRect( &rClip
, &rect
, &rClip
);
68 OffsetRect( &rDst
, dx
, dy
);
69 IntersectRect( &rDst
, &rDst
, &rClip
);
71 if (!IsRectEmpty(&rDst
))
74 if (!BitBlt( hdc
, rDst
.left
, rDst
.top
,
75 rDst
.right
- rDst
.left
, rDst
.bottom
- rDst
.top
,
76 hdc
, rDst
.left
- dx
, rDst
.top
- dy
, SRCCOPY
))
80 /* compute update areas */
82 if (hrgnUpdate
|| rcUpdate
)
84 HRGN hrgn
= hrgnUpdate
, hrgn2
;
86 /* map everything to device coordinates */
87 LPtoDP( hdc
, (LPPOINT
)&rClip
, 2 );
88 LPtoDP( hdc
, (LPPOINT
)&rDst
, 2 );
90 hrgn2
= CreateRectRgnIndirect( &rDst
);
91 if (hrgn
) SetRectRgn( hrgn
, rClip
.left
, rClip
.top
, rClip
.right
, rClip
.bottom
);
92 else hrgn
= CreateRectRgn( rClip
.left
, rClip
.top
, rClip
.right
, rClip
.bottom
);
93 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_DIFF
);
97 GetRgnBox( hrgn
, rcUpdate
);
99 /* Put the rcUpdate in logical coordinate */
100 DPtoLP( hdc
, (LPPOINT
)rcUpdate
, 2 );
102 if (!hrgnUpdate
) DeleteObject( hrgn
);
103 DeleteObject( hrgn2
);
109 /*************************************************************************
110 * ScrollWindowEx (X11DRV.@)
112 * Note: contrary to what the doc says, pixels that are scrolled from the
113 * outside of clipRect to the inside are NOT painted.
115 * Parameter are the same as in ScrollWindowEx, with the additional
116 * requirement that rect and clipRect are _valid_ pointers, to
117 * rectangles _within_ the client are. Moreover, there is something
120 INT
X11DRV_ScrollWindowEx( HWND hwnd
, INT dx
, INT dy
,
121 const RECT
*rect
, const RECT
*clipRect
,
122 HRGN hrgnUpdate
, LPRECT rcUpdate
, UINT flags
)
126 BOOL bUpdate
= (rcUpdate
|| hrgnUpdate
|| flags
& (SW_INVALIDATE
| SW_ERASE
));
127 HRGN hrgnClip
= CreateRectRgnIndirect(clipRect
);
131 TRACE( "%p, %d,%d hrgnUpdate=%p rcUpdate = %p rect=(%ld,%ld-%ld,%ld) %04x\n",
132 hwnd
, dx
, dy
, hrgnUpdate
, rcUpdate
,
133 rect
->left
, rect
->top
, rect
->right
, rect
->bottom
, flags
);
134 TRACE( "clipRect = (%ld,%ld,%ld,%ld)\n",
135 clipRect
->left
, clipRect
->top
, clipRect
->right
, clipRect
->bottom
);
137 if( hrgnUpdate
) bOwnRgn
= FALSE
;
138 else if( bUpdate
) hrgnUpdate
= CreateRectRgn( 0, 0, 0, 0 );
140 hDC
= GetDCEx( hwnd
, 0, DCX_CACHE
| DCX_USESTYLE
);
143 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
144 X11DRV_StartGraphicsExposures( hDC
);
145 X11DRV_ScrollDC( hDC
, dx
, dy
, rect
, clipRect
, hrgnUpdate
, rcUpdate
);
146 X11DRV_EndGraphicsExposures( hDC
, hrgn
);
147 ReleaseDC( hwnd
, hDC
);
148 if (bUpdate
) CombineRgn( hrgnUpdate
, hrgnUpdate
, hrgn
, RGN_OR
);
149 else RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
150 DeleteObject( hrgn
);
153 /* Take into account the fact that some damages may have occured during the scroll */
154 hrgnTemp
= CreateRectRgn( 0, 0, 0, 0 );
155 retVal
= GetUpdateRgn( hwnd
, hrgnTemp
, FALSE
);
156 if (retVal
!= NULLREGION
)
158 OffsetRgn( hrgnTemp
, dx
, dy
);
159 CombineRgn( hrgnTemp
, hrgnTemp
, hrgnClip
, RGN_AND
);
160 RedrawWindow( hwnd
, NULL
, hrgnTemp
, RDW_INVALIDATE
| RDW_ERASE
);
162 DeleteObject( hrgnTemp
);
164 if( flags
& SW_SCROLLCHILDREN
)
166 HWND
*list
= WIN_ListChildren( hwnd
);
171 for (i
= 0; list
[i
]; i
++)
173 GetWindowRect( list
[i
], &r
);
174 MapWindowPoints( 0, hwnd
, (POINT
*)&r
, 2 );
175 if (!rect
|| IntersectRect(&dummy
, &r
, rect
))
176 SetWindowPos( list
[i
], 0, r
.left
+ dx
, r
.top
+ dy
, 0, 0,
177 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
|
178 SWP_NOREDRAW
| SWP_DEFERERASE
);
180 HeapFree( GetProcessHeap(), 0, list
);
184 if( flags
& (SW_INVALIDATE
| SW_ERASE
) )
185 RedrawWindow( hwnd
, NULL
, hrgnUpdate
, RDW_INVALIDATE
| RDW_ERASE
|
186 ((flags
& SW_ERASE
) ? RDW_ERASENOW
: 0) |
187 ((flags
& SW_SCROLLCHILDREN
) ? RDW_ALLCHILDREN
: 0 ) );
189 if( bOwnRgn
&& hrgnUpdate
) DeleteObject( hrgnUpdate
);
190 DeleteObject( hrgnClip
);