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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(scroll
);
38 static void dump_region( const 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 %d 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 rcScroll %s rcClip %s hrgnUpdate %p lprcUpdate %p\n",
72 dx
, dy
, wine_dbgstr_rect(lprcScroll
), wine_dbgstr_rect(lprcClip
),
73 hrgnUpdate
, lprcUpdate
);
74 /* enable X-exposure events */
75 if (hrgnUpdate
|| lprcUpdate
)
76 ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(code
), (LPSTR
)&code
, 0, NULL
);
77 /* get the visible region */
78 visrgn
=CreateRectRgn( 0, 0, 0, 0);
79 GetRandomRgn( hdc
, visrgn
, SYSRGN
);
80 if( !(GetVersion() & 0x80000000)) {
83 GetDCOrgEx(hdc
, &org
);
84 OffsetRgn( visrgn
, -org
.x
, -org
.y
);
86 /* intersect with the clipping Region if the DC has one */
87 clipRgn
= CreateRectRgn( 0, 0, 0, 0);
88 if (GetClipRgn( hdc
, clipRgn
) != 1) {
89 DeleteObject(clipRgn
);
92 CombineRgn( visrgn
, visrgn
, clipRgn
, RGN_AND
);
93 /* only those pixels in the scroll rectangle that remain in the clipping
94 * rect are scrolled. */
98 GetClipBox( hdc
, &rcClip
);
100 OffsetRect( &rcClip
, -dx
, -dy
);
101 IntersectRect( &rcSrc
, &rcSrc
, &rcClip
);
102 /* if an scroll rectangle is specified, only the pixels within that
103 * rectangle are scrolled */
105 IntersectRect( &rcSrc
, &rcSrc
, lprcScroll
);
106 /* now convert to device coordinates */
107 LPtoDP(hdc
, (LPPOINT
)&rcSrc
, 2);
108 TRACE("source rect: %s\n", wine_dbgstr_rect(&rcSrc
));
110 SetRect(&offset
, 0, 0, dx
, dy
);
111 LPtoDP(hdc
, (LPPOINT
)&offset
, 2);
112 dxdev
= offset
.right
- offset
.left
;
113 dydev
= offset
.bottom
- offset
.top
;
114 /* now intersect with the visible region to get the pixels that will
116 DstRgn
= CreateRectRgnIndirect( &rcSrc
);
117 res
= CombineRgn( DstRgn
, DstRgn
, visrgn
, RGN_AND
);
118 /* and translate, giving the destination region */
119 OffsetRgn( DstRgn
, dxdev
, dydev
);
120 if( TRACE_ON( scroll
)) dump_region( "Destination scroll region: ", DstRgn
);
121 /* if there are any, do it */
122 if( res
> NULLREGION
) {
124 /* clip to the destination region, so we can BitBlt with a simple
125 * bounding rectangle */
127 ExtSelectClipRgn( hdc
, DstRgn
, RGN_AND
);
129 SelectClipRgn( hdc
, DstRgn
);
130 GetRgnBox( DstRgn
, &rect
);
131 DPtoLP(hdc
, (LPPOINT
)&rect
, 2);
132 TRACE("destination rect: %s\n", wine_dbgstr_rect(&rect
));
134 BitBlt( hdc
, rect
.left
, rect
.top
,
135 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
136 hdc
, rect
.left
- dx
, rect
.top
- dy
, SRCCOPY
);
138 /* compute the update areas. This is the combined clip rectangle
139 * minus the scrolled region, and intersected with the visible
141 if (hrgnUpdate
|| lprcUpdate
)
143 HRGN hrgn
= hrgnUpdate
;
146 /* collect all the exposures */
147 code
= X11DRV_END_EXPOSURES
;
148 ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(code
), (LPSTR
)&code
,
149 sizeof(ExpRgn
), (LPSTR
)&ExpRgn
);
150 /* Intersect clip and scroll rectangles, allowing NULL values */
153 IntersectRect( &rcClip
, lprcClip
, lprcScroll
);
155 rcClip
= *lprcScroll
;
160 GetClipBox( hdc
, &rcClip
);
161 /* Convert the combined clip rectangle to device coordinates */
162 LPtoDP(hdc
, (LPPOINT
)&rcClip
, 2);
164 SetRectRgn( hrgn
, rcClip
.left
, rcClip
.top
, rcClip
.right
,
167 hrgn
= CreateRectRgnIndirect( &rcClip
);
168 CombineRgn( hrgn
, hrgn
, visrgn
, RGN_AND
);
169 CombineRgn( hrgn
, hrgn
, DstRgn
, RGN_DIFF
);
170 /* add the exposures to this */
172 if( TRACE_ON( scroll
)) dump_region( "Expose region: ", ExpRgn
);
173 CombineRgn( hrgn
, hrgn
, ExpRgn
, RGN_OR
);
174 DeleteObject( ExpRgn
);
176 if( TRACE_ON( scroll
)) dump_region( "Update region: ", hrgn
);
178 GetRgnBox( hrgn
, lprcUpdate
);
179 /* Put the lprcUpdate in logical coordinates */
180 DPtoLP( hdc
, (LPPOINT
)lprcUpdate
, 2 );
181 TRACE("returning lprcUpdate %s\n", wine_dbgstr_rect(lprcUpdate
));
186 /* restore original clipping region */
187 SelectClipRgn( hdc
, clipRgn
);
188 DeleteObject( visrgn
);
189 DeleteObject( DstRgn
);
190 if( clipRgn
) DeleteObject( clipRgn
);