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
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(scroll
);
39 /*************************************************************************
42 * Only the hrgnUpdate is returned in device coordinates.
43 * rcUpdate must be returned in logical coordinates to comply with win API.
44 * FIXME: the doc explicitly states the opposite, to be checked
46 BOOL
X11DRV_ScrollDC( HDC hdc
, INT dx
, INT dy
, const RECT
*rc
,
47 const RECT
*clipRect
, HRGN hrgnUpdate
, LPRECT rcUpdate
)
49 RECT rect
, rClip
, rDst
;
51 TRACE( "%04x %d,%d hrgnUpdate=%04x rcUpdate = %p\n", hdc
, dx
, dy
, hrgnUpdate
, rcUpdate
);
52 if (clipRect
) TRACE( "cliprc = (%d,%d,%d,%d)\n",
53 clipRect
->left
, clipRect
->top
, clipRect
->right
, clipRect
->bottom
);
54 if (rc
) TRACE( "rc = (%d,%d,%d,%d)\n", rc
->left
, rc
->top
, rc
->right
, rc
->bottom
);
56 /* compute device clipping region (in device coordinates) */
59 else GetClipBox( hdc
, &rect
);
64 IntersectRect( &rClip
, &rect
, &rClip
);
69 OffsetRect( &rDst
, dx
, dy
);
70 IntersectRect( &rDst
, &rDst
, &rClip
);
72 if (!IsRectEmpty(&rDst
))
75 if (!BitBlt( hdc
, rDst
.left
, rDst
.top
,
76 rDst
.right
- rDst
.left
, rDst
.bottom
- rDst
.top
,
77 hdc
, rDst
.left
- dx
, rDst
.top
- dy
, SRCCOPY
))
81 /* compute update areas */
83 if (hrgnUpdate
|| rcUpdate
)
85 HRGN hrgn
= hrgnUpdate
, hrgn2
;
87 /* map everything to device coordinates */
88 LPtoDP( hdc
, (LPPOINT
)&rClip
, 2 );
89 LPtoDP( hdc
, (LPPOINT
)&rDst
, 2 );
91 hrgn2
= CreateRectRgnIndirect( &rDst
);
92 if (hrgn
) SetRectRgn( hrgn
, rClip
.left
, rClip
.top
, rClip
.right
, rClip
.bottom
);
93 else hrgn
= CreateRectRgn( rClip
.left
, rClip
.top
, rClip
.right
, rClip
.bottom
);
94 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_DIFF
);
98 GetRgnBox( hrgn
, rcUpdate
);
100 /* Put the rcUpdate in logical coordinate */
101 DPtoLP( hdc
, (LPPOINT
)rcUpdate
, 2 );
103 if (!hrgnUpdate
) DeleteObject( hrgn
);
104 DeleteObject( hrgn2
);
110 /*************************************************************************
111 * ScrollWindowEx (X11DRV.@)
113 * Note: contrary to what the doc says, pixels that are scrolled from the
114 * outside of clipRect to the inside are NOT painted.
116 * Parameter are the same as in ScrollWindowEx, with the additional
117 * requirement that rect and clipRect are _valid_ pointers, to
118 * rectangles _within_ the client are. Moreover, there is something
121 INT
X11DRV_ScrollWindowEx( HWND hwnd
, INT dx
, INT dy
,
122 const RECT
*rect
, const RECT
*clipRect
,
123 HRGN hrgnUpdate
, LPRECT rcUpdate
, UINT flags
)
127 BOOL bUpdate
= (rcUpdate
|| hrgnUpdate
|| flags
& (SW_INVALIDATE
| SW_ERASE
));
128 HRGN hrgnClip
= CreateRectRgnIndirect(clipRect
);
132 TRACE( "%04x, %d,%d hrgnUpdate=%04x rcUpdate = %p rect=(%d,%d-%d,%d) %04x\n",
133 hwnd
, dx
, dy
, hrgnUpdate
, rcUpdate
,
134 rect
->left
, rect
->top
, rect
->right
, rect
->bottom
, flags
);
135 TRACE( "clipRect = (%d,%d,%d,%d)\n",
136 clipRect
->left
, clipRect
->top
, clipRect
->right
, clipRect
->bottom
);
138 if( hrgnUpdate
) bOwnRgn
= FALSE
;
139 else if( bUpdate
) hrgnUpdate
= CreateRectRgn( 0, 0, 0, 0 );
141 hDC
= GetDCEx( hwnd
, 0, DCX_CACHE
| DCX_USESTYLE
);
144 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
145 X11DRV_StartGraphicsExposures( hDC
);
146 X11DRV_ScrollDC( hDC
, dx
, dy
, rect
, clipRect
, hrgnUpdate
, rcUpdate
);
147 X11DRV_EndGraphicsExposures( hDC
, hrgn
);
148 ReleaseDC( hwnd
, hDC
);
149 if (bUpdate
) CombineRgn( hrgnUpdate
, hrgnUpdate
, hrgn
, RGN_OR
);
150 else RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
151 DeleteObject( hrgn
);
154 /* Take into account the fact that some damages may have occured during the scroll */
155 hrgnTemp
= CreateRectRgn( 0, 0, 0, 0 );
156 retVal
= GetUpdateRgn( hwnd
, hrgnTemp
, FALSE
);
157 if (retVal
!= NULLREGION
)
159 OffsetRgn( hrgnTemp
, dx
, dy
);
160 CombineRgn( hrgnTemp
, hrgnTemp
, hrgnClip
, RGN_AND
);
161 RedrawWindow( hwnd
, NULL
, hrgnTemp
, RDW_INVALIDATE
| RDW_ERASE
);
163 DeleteObject( hrgnTemp
);
165 if( flags
& SW_SCROLLCHILDREN
)
167 HWND
*list
= WIN_ListChildren( hwnd
);
172 for (i
= 0; list
[i
]; i
++)
174 GetWindowRect( list
[i
], &r
);
175 MapWindowPoints( 0, hwnd
, (POINT
*)&r
, 2 );
176 if (!rect
|| IntersectRect(&dummy
, &r
, rect
))
177 SetWindowPos( list
[i
], 0, r
.left
+ dx
, r
.top
+ dy
, 0, 0,
178 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
|
179 SWP_NOREDRAW
| SWP_DEFERERASE
);
181 HeapFree( GetProcessHeap(), 0, list
);
185 if( flags
& (SW_INVALIDATE
| SW_ERASE
) )
186 RedrawWindow( hwnd
, NULL
, hrgnUpdate
, RDW_INVALIDATE
| RDW_ERASE
|
187 ((flags
& SW_ERASE
) ? RDW_ERASENOW
: 0) |
188 ((flags
& SW_SCROLLCHILDREN
) ? RDW_ALLCHILDREN
: 0 ) );
190 if( bOwnRgn
&& hrgnUpdate
) DeleteObject( hrgnUpdate
);
191 DeleteObject( hrgnClip
);