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
);
38 static void dump_region( char *p
, HRGN hrgn
)
45 TRACE( "%s null region\n", p
);
48 if (!(size
= GetRegionData( hrgn
, 0, NULL
))) {
51 if (!(data
= HeapAlloc( GetProcessHeap(), 0, size
))) return;
52 GetRegionData( hrgn
, size
, data
);
53 TRACE("%s %ld rects:", p
, data
->rdh
.nCount
);
54 for (i
= 0, rect
= (RECT
*)data
->Buffer
; i
<20 && i
< data
->rdh
.nCount
; i
++, rect
++)
55 TRACE( " %s", wine_dbgstr_rect( rect
));
57 HeapFree( GetProcessHeap(), 0, data
);
60 /*************************************************************************
63 BOOL
X11DRV_ScrollDC( HDC hdc
, INT dx
, INT dy
, const RECT
*lprcScroll
,
64 const RECT
*lprcClip
, HRGN hrgnUpdate
, LPRECT lprcUpdate
)
66 RECT rcSrc
, rcClip
, offset
;
67 INT dxdev
, dydev
, res
;
68 HRGN DstRgn
, clipRgn
, visrgn
;
69 INT code
= X11DRV_START_EXPOSURES
;
71 TRACE("dx,dy %d,%d lprcScroll %p lprcClip %p hrgnUpdate %p lprcUpdate %p\n",
72 dx
, dy
, lprcScroll
, lprcClip
, hrgnUpdate
, lprcUpdate
);
73 /* enable X-exposure events */
74 if (hrgnUpdate
|| lprcUpdate
)
75 ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(code
), (LPSTR
)&code
, 0, NULL
);
76 /* get the visible region */
77 visrgn
=CreateRectRgn( 0, 0, 0, 0);
78 GetRandomRgn( hdc
, visrgn
, SYSRGN
);
79 if( !(GetVersion() & 0x80000000)) {
82 GetDCOrgEx(hdc
, &org
);
83 OffsetRgn( visrgn
, -org
.x
, -org
.y
);
85 /* intersect with the clipping Region if the DC has one */
86 clipRgn
= CreateRectRgn( 0, 0, 0, 0);
87 if (GetClipRgn( hdc
, clipRgn
) != 1) {
88 DeleteObject(clipRgn
);
91 CombineRgn( visrgn
, visrgn
, clipRgn
, RGN_AND
);
92 /* only those pixels in the scroll rectangle that remain in the clipping
93 * rect are scrolled. So first combine Scroll and Clipping rectangles,
97 IntersectRect( &rcClip
, lprcClip
, lprcScroll
);
104 GetClipBox( hdc
, &rcClip
);
105 /* Then clip again to get the source rectangle that will remain in the
108 OffsetRect( &rcSrc
, -dx
, -dy
);
109 IntersectRect( &rcSrc
, &rcSrc
, &rcClip
);
110 /* now convert to device coordinates */
111 LPtoDP(hdc
, (LPPOINT
)&rcSrc
, 2);
113 SetRect(&offset
, 0, 0, dx
, dy
);
114 LPtoDP(hdc
, (LPPOINT
)&offset
, 2);
115 dxdev
= offset
.right
- offset
.left
;
116 dydev
= offset
.bottom
- offset
.top
;
117 /* now intersect with the visible region to get the pixels that will
119 DstRgn
= CreateRectRgnIndirect( &rcSrc
);
120 res
= CombineRgn( DstRgn
, DstRgn
, visrgn
, RGN_AND
);
121 /* and translate, giving the destination region */
122 OffsetRgn( DstRgn
, dxdev
, dydev
);
123 if( TRACE_ON( scroll
)) dump_region( "Destination scroll region: ", DstRgn
);
124 /* if there are any, do it */
125 if( res
> NULLREGION
) {
127 /* clip to the destination region, so we can BitBlt with a simple
128 * bounding rectangle */
130 ExtSelectClipRgn( hdc
, DstRgn
, RGN_AND
);
132 SelectClipRgn( hdc
, DstRgn
);
133 GetRgnBox( DstRgn
, &rect
);
134 DPtoLP(hdc
, (LPPOINT
)&rect
, 2);
135 BitBlt( hdc
, rect
.left
, rect
.top
,
136 rect
.right
- rect
.left
, rect
.bottom
-rect
.top
,
137 hdc
, rect
.left
- dx
, rect
.top
- dy
, SRCCOPY
);
139 /* compute the update areas. This is the combined clip rectangle
140 * minus the scrolled region, and intersected with the visible
142 if (hrgnUpdate
|| lprcUpdate
)
144 HRGN hrgn
= hrgnUpdate
;
147 /* collect all the exposures */
148 code
= X11DRV_END_EXPOSURES
;
149 ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(code
), (LPSTR
)&code
,
150 sizeof(ExpRgn
), (LPSTR
)&ExpRgn
);
151 /* Covert the combined clip rectangle to device coordinates */
152 LPtoDP(hdc
, (LPPOINT
)&rcClip
, 2);
154 SetRectRgn( hrgn
, rcClip
.left
, rcClip
.top
, rcClip
.right
,
157 hrgn
= CreateRectRgnIndirect( &rcClip
);
158 CombineRgn( hrgn
, hrgn
, visrgn
, RGN_AND
);
159 CombineRgn( hrgn
, hrgn
, DstRgn
, RGN_DIFF
);
160 /* add the exposures to this */
162 if( TRACE_ON( scroll
)) dump_region( "Expose region: ", ExpRgn
);
163 CombineRgn( hrgn
, hrgn
, ExpRgn
, RGN_OR
);
164 DeleteObject( ExpRgn
);
166 if( TRACE_ON( scroll
)) dump_region( "Update region: ", hrgn
);
168 GetRgnBox( hrgn
, lprcUpdate
);
169 /* Put the lprcUpdate in logical coordinates */
170 DPtoLP( hdc
, (LPPOINT
)lprcUpdate
, 2 );
171 TRACE("returning lprcUpdate %s\n", wine_dbgstr_rect(lprcUpdate
));
176 SelectClipRgn( hdc
, clipRgn
);
177 DeleteObject( visrgn
);
178 DeleteObject( DstRgn
);
179 if( clipRgn
) DeleteObject( clipRgn
);