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
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(scroll
);
40 /*************************************************************************
43 * dx, dy, lprcScroll and lprcClip are all in logical coordinates (msdn is wrong)
44 * hrgnUpdate is returned in device coordinates with rcUpdate in logical coordinates.
47 BOOL
X11DRV_ScrollDC( HDC hdc
, INT dx
, INT dy
, const RECT
*lprcScroll
,
48 const RECT
*lprcClip
, HRGN hrgnUpdate
, LPRECT lprcUpdate
)
50 RECT rSrc
, rClipped_src
, rClip
, rDst
, offset
;
52 TRACE( "%p %d,%d hrgnUpdate=%p lprcUpdate = %p\n", hdc
, dx
, dy
, hrgnUpdate
, lprcUpdate
);
53 if (lprcClip
) TRACE( "lprcClip = %s\n", wine_dbgstr_rect(lprcClip
));
54 if (lprcScroll
) TRACE( "lprcScroll = %s\n", wine_dbgstr_rect(lprcScroll
));
56 /* compute device clipping region (in device coordinates) */
58 if (lprcScroll
) rSrc
= *lprcScroll
;
59 else GetClipBox( hdc
, &rSrc
);
60 LPtoDP(hdc
, (LPPOINT
)&rSrc
, 2);
62 if (lprcClip
) rClip
= *lprcClip
;
63 else GetClipBox( hdc
, &rClip
);
64 LPtoDP(hdc
, (LPPOINT
)&rClip
, 2);
66 IntersectRect( &rClipped_src
, &rSrc
, &rClip
);
67 TRACE("rSrc %s rClip %s clipped rSrc %s\n", wine_dbgstr_rect(&rSrc
),
68 wine_dbgstr_rect(&rClip
), wine_dbgstr_rect(&rClipped_src
));
71 SetRect(&offset
, 0, 0, dx
, dy
);
72 LPtoDP(hdc
, (LPPOINT
)&offset
, 2);
73 OffsetRect( &rDst
, offset
.right
- offset
.left
, offset
.bottom
- offset
.top
);
74 TRACE("rDst before clipping %s\n", wine_dbgstr_rect(&rDst
));
75 IntersectRect( &rDst
, &rDst
, &rClip
);
76 TRACE("rDst after clipping %s\n", wine_dbgstr_rect(&rDst
));
78 if (!IsRectEmpty(&rDst
))
81 RECT rDst_lp
= rDst
, rSrc_lp
= rDst
;
83 OffsetRect( &rSrc_lp
, offset
.left
- offset
.right
, offset
.top
- offset
.bottom
);
84 DPtoLP(hdc
, (LPPOINT
)&rDst_lp
, 2);
85 DPtoLP(hdc
, (LPPOINT
)&rSrc_lp
, 2);
87 if (!BitBlt( hdc
, rDst_lp
.left
, rDst_lp
.top
,
88 rDst_lp
.right
- rDst_lp
.left
, rDst_lp
.bottom
- rDst_lp
.top
,
89 hdc
, rSrc_lp
.left
, rSrc_lp
.top
, SRCCOPY
))
93 /* compute update areas. This is the clipped source or'ed with the unclipped source translated minus the
94 clipped src translated (rDst) all clipped to rClip */
96 if (hrgnUpdate
|| lprcUpdate
)
98 HRGN hrgn
= hrgnUpdate
, hrgn2
;
100 if (hrgn
) SetRectRgn( hrgn
, rClipped_src
.left
, rClipped_src
.top
, rClipped_src
.right
, rClipped_src
.bottom
);
101 else hrgn
= CreateRectRgn( rClipped_src
.left
, rClipped_src
.top
, rClipped_src
.right
, rClipped_src
.bottom
);
103 hrgn2
= CreateRectRgnIndirect( &rSrc
);
104 OffsetRgn(hrgn2
, offset
.right
- offset
.left
, offset
.bottom
- offset
.top
);
105 CombineRgn(hrgn
, hrgn
, hrgn2
, RGN_OR
);
107 SetRectRgn( hrgn2
, rDst
.left
, rDst
.top
, rDst
.right
, rDst
.bottom
);
108 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_DIFF
);
110 SetRectRgn( hrgn2
, rClip
.left
, rClip
.top
, rClip
.right
, rClip
.bottom
);
111 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_AND
);
115 GetRgnBox( hrgn
, lprcUpdate
);
117 /* Put the lprcUpdate in logical coordinate */
118 DPtoLP( hdc
, (LPPOINT
)lprcUpdate
, 2 );
119 TRACE("returning lprcUpdate %s\n", wine_dbgstr_rect(lprcUpdate
));
121 if (!hrgnUpdate
) DeleteObject( hrgn
);
122 DeleteObject( hrgn2
);
128 /*************************************************************************
129 * ScrollWindowEx (X11DRV.@)
131 * Note: contrary to what the doc says, pixels that are scrolled from the
132 * outside of clipRect to the inside are NOT painted.
134 * Parameter are the same as in ScrollWindowEx, with the additional
135 * requirement that rect and clipRect are _valid_ pointers, to
136 * rectangles _within_ the client are. Moreover, there is something
139 INT
X11DRV_ScrollWindowEx( HWND hwnd
, INT dx
, INT dy
,
140 const RECT
*rect
, const RECT
*clipRect
,
141 HRGN hrgnUpdate
, LPRECT rcUpdate
, UINT flags
)
145 BOOL bUpdate
= (rcUpdate
|| hrgnUpdate
|| flags
& (SW_INVALIDATE
| SW_ERASE
));
150 TRACE( "%p, %d,%d hrgnUpdate=%p rcUpdate = %p %s %04x\n",
151 hwnd
, dx
, dy
, hrgnUpdate
, rcUpdate
, wine_dbgstr_rect(rect
), flags
);
152 TRACE( "clipRect = %s\n", wine_dbgstr_rect(clipRect
));
154 GetClientRect(hwnd
, &rc
);
155 if (rect
) IntersectRect(&rc
, &rc
, rect
);
157 if (clipRect
) IntersectRect(&cliprc
,&rc
,clipRect
);
160 if( hrgnUpdate
) bOwnRgn
= FALSE
;
161 else if( bUpdate
) hrgnUpdate
= CreateRectRgn( 0, 0, 0, 0 );
163 hDC
= GetDCEx( hwnd
, 0, DCX_CACHE
| DCX_USESTYLE
);
166 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
167 X11DRV_StartGraphicsExposures( hDC
);
168 X11DRV_ScrollDC( hDC
, dx
, dy
, &rc
, &cliprc
, hrgnUpdate
, rcUpdate
);
169 X11DRV_EndGraphicsExposures( hDC
, hrgn
);
170 ReleaseDC( hwnd
, hDC
);
171 if (bUpdate
) CombineRgn( hrgnUpdate
, hrgnUpdate
, hrgn
, RGN_OR
);
172 else RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
173 DeleteObject( hrgn
);
176 /* Take into account the fact that some damage may have occurred during the scroll */
177 hrgnTemp
= CreateRectRgn( 0, 0, 0, 0 );
178 retVal
= GetUpdateRgn( hwnd
, hrgnTemp
, FALSE
);
179 if (retVal
!= NULLREGION
)
181 HRGN hrgnClip
= CreateRectRgnIndirect(&cliprc
);
182 OffsetRgn( hrgnTemp
, dx
, dy
);
183 CombineRgn( hrgnTemp
, hrgnTemp
, hrgnClip
, RGN_AND
);
184 RedrawWindow( hwnd
, NULL
, hrgnTemp
, RDW_INVALIDATE
| RDW_ERASE
);
185 DeleteObject( hrgnClip
);
187 DeleteObject( hrgnTemp
);
189 if( flags
& SW_SCROLLCHILDREN
)
191 HWND
*list
= WIN_ListChildren( hwnd
);
196 for (i
= 0; list
[i
]; i
++)
198 GetWindowRect( list
[i
], &r
);
199 MapWindowPoints( 0, hwnd
, (POINT
*)&r
, 2 );
200 if (!rect
|| IntersectRect(&dummy
, &r
, &rc
))
201 SetWindowPos( list
[i
], 0, r
.left
+ dx
, r
.top
+ dy
, 0, 0,
202 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
|
203 SWP_NOREDRAW
| SWP_DEFERERASE
);
205 HeapFree( GetProcessHeap(), 0, list
);
209 if( flags
& (SW_INVALIDATE
| SW_ERASE
) )
210 RedrawWindow( hwnd
, NULL
, hrgnUpdate
, RDW_INVALIDATE
| RDW_ERASE
|
211 ((flags
& SW_ERASE
) ? RDW_ERASENOW
: 0) |
212 ((flags
& SW_SCROLLCHILDREN
) ? RDW_ALLCHILDREN
: 0 ) );
214 if( bOwnRgn
&& hrgnUpdate
) DeleteObject( hrgnUpdate
);