2 * Scroll windows and DCs
4 * Copyright 1993 David W. Metcalfe
5 * Copyright 1995, 1996 Alex Korobka
6 * Copyright 2001 Alexandre Julliard
20 #include "debugtools.h"
22 DEFAULT_DEBUG_CHANNEL(x11drv
);
25 /*************************************************************************
28 static BOOL
fix_caret(HWND hWnd
, LPRECT lprc
, UINT flags
)
30 HWND hCaret
= CARET_GetHwnd();
37 (flags
& SW_SCROLLCHILDREN
&& IsChild(hWnd
, hCaret
)) )
42 MapWindowPoints( hCaret
, hWnd
, (LPPOINT
)&rc
, 2 );
43 if( IntersectRect(lprc
, lprc
, &rc
) )
56 /*************************************************************************
59 * Only the hrgnUpdate is returned in device coordinates.
60 * rcUpdate must be returned in logical coordinates to comply with win API.
61 * FIXME: the doc explicitly states the opposite, to be checked
63 BOOL
X11DRV_ScrollDC( HDC hdc
, INT dx
, INT dy
, const RECT
*rc
,
64 const RECT
*clipRect
, HRGN hrgnUpdate
, LPRECT rcUpdate
)
66 RECT rect
, rClip
, rSrc
;
68 TRACE( "%04x %d,%d hrgnUpdate=%04x rcUpdate = %p\n", hdc
, dx
, dy
, hrgnUpdate
, rcUpdate
);
69 if (clipRect
) TRACE( "cliprc = (%d,%d,%d,%d)\n",
70 clipRect
->left
, clipRect
->top
, clipRect
->right
, clipRect
->bottom
);
71 if (rc
) TRACE( "rc = (%d,%d,%d,%d)\n", rc
->left
, rc
->top
, rc
->right
, rc
->bottom
);
73 /* compute device clipping region (in device coordinates) */
76 else GetClipBox( hdc
, &rect
);
81 IntersectRect( &rClip
, &rect
, &rClip
);
86 OffsetRect( &rSrc
, -dx
, -dy
);
87 IntersectRect( &rSrc
, &rSrc
, &rect
);
89 if (!IsRectEmpty(&rSrc
))
92 if (!BitBlt( hdc
, rSrc
.left
+ dx
, rSrc
.top
+ dy
,
93 rSrc
.right
- rSrc
.left
, rSrc
.bottom
- rSrc
.top
,
94 hdc
, rSrc
.left
, rSrc
.top
, SRCCOPY
))
98 /* compute update areas */
100 if (hrgnUpdate
|| rcUpdate
)
102 HRGN hrgn
= hrgnUpdate
, hrgn2
;
105 /* map everything to device coordinates */
106 pt
.x
= rect
.left
+ dx
;
107 pt
.y
= rect
.top
+ dy
;
108 LPtoDP( hdc
, &pt
, 1 );
109 LPtoDP( hdc
, (LPPOINT
)&rect
, 2 );
110 LPtoDP( hdc
, (LPPOINT
)&rClip
, 2 );
111 dx
= pt
.x
- rect
.left
;
112 dy
= pt
.y
- rect
.top
;
114 hrgn2
= CreateRectRgnIndirect( &rect
);
115 if (hrgn
) SetRectRgn( hrgn
, rClip
.left
, rClip
.top
, rClip
.right
, rClip
.bottom
);
116 else hrgn
= CreateRectRgn( rClip
.left
, rClip
.top
, rClip
.right
, rClip
.bottom
);
117 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_AND
);
118 OffsetRgn( hrgn2
, dx
, dy
);
119 CombineRgn( hrgn
, hrgn
, hrgn2
, RGN_DIFF
);
123 GetRgnBox( hrgn
, rcUpdate
);
125 /* Put the rcUpdate in logical coordinate */
126 DPtoLP( hdc
, (LPPOINT
)rcUpdate
, 2 );
128 if (!hrgnUpdate
) DeleteObject( hrgn
);
129 DeleteObject( hrgn2
);
135 /*************************************************************************
136 * ScrollWindowEx (X11DRV.@)
138 INT
X11DRV_ScrollWindowEx( HWND hwnd
, INT dx
, INT dy
,
139 const RECT
*rect
, const RECT
*clipRect
,
140 HRGN hrgnUpdate
, LPRECT rcUpdate
, UINT flags
)
142 INT retVal
= NULLREGION
;
143 BOOL bCaret
= FALSE
, bOwnRgn
= TRUE
;
145 WND
* wnd
= WIN_FindWndPtr( hwnd
);
147 if( !wnd
|| !WIN_IsWindowDrawable( wnd
, TRUE
))
152 hwnd
= wnd
->hwndSelf
; /* make it a full handle */
154 GetClientRect(hwnd
, &rc
);
155 if (rect
) IntersectRect(&rc
, &rc
, rect
);
157 if (clipRect
) IntersectRect(&cliprc
,&rc
,clipRect
);
160 if (!IsRectEmpty(&cliprc
) && (dx
|| dy
))
163 BOOL bUpdate
= (rcUpdate
|| hrgnUpdate
|| flags
& (SW_INVALIDATE
| SW_ERASE
));
164 HRGN hrgnClip
= CreateRectRgnIndirect(&cliprc
);
168 TRACE( "%04x, %d,%d hrgnUpdate=%04x rcUpdate = %p rc=(%d,%d-%d,%d) %04x\n",
169 hwnd
, dx
, dy
, hrgnUpdate
, rcUpdate
,
170 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
, flags
);
171 if (clipRect
) TRACE( "cliprc = (%d,%d,%d,%d)\n",
172 clipRect
->left
, clipRect
->top
,
173 clipRect
->right
, clipRect
->bottom
);
176 bCaret
= fix_caret(hwnd
, &caretrc
, flags
);
178 if( hrgnUpdate
) bOwnRgn
= FALSE
;
179 else if( bUpdate
) hrgnUpdate
= CreateRectRgn( 0, 0, 0, 0 );
181 hDC
= GetDCEx( hwnd
, 0, DCX_CACHE
| DCX_USESTYLE
);
184 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
185 X11DRV_StartGraphicsExposures( hDC
);
186 X11DRV_ScrollDC( hDC
, dx
, dy
, &rc
, &cliprc
, hrgnUpdate
, rcUpdate
);
187 X11DRV_EndGraphicsExposures( hDC
, hrgn
);
188 ReleaseDC( hwnd
, hDC
);
189 if (bUpdate
) CombineRgn( hrgnUpdate
, hrgnUpdate
, hrgn
, RGN_OR
);
190 else RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| RDW_ERASE
);
191 DeleteObject( hrgn
);
194 /* Take into account the fact that some damages may have occured during the scroll */
195 hrgnTemp
= CreateRectRgn( 0, 0, 0, 0 );
196 if (GetUpdateRgn( hwnd
, hrgnTemp
, FALSE
) != NULLREGION
)
198 OffsetRgn( hrgnTemp
, dx
, dy
);
199 CombineRgn( hrgnTemp
, hrgnTemp
, hrgnClip
, RGN_AND
);
200 RedrawWindow( hwnd
, NULL
, hrgnTemp
, RDW_INVALIDATE
| RDW_ERASE
);
202 DeleteObject( hrgnTemp
);
204 if( flags
& SW_SCROLLCHILDREN
)
208 for( w
=WIN_LockWndPtr(wnd
->child
); w
; WIN_UpdateWndPtr(&w
, w
->next
))
211 if( !rect
|| IntersectRect(&r
, &r
, &rc
) )
212 SetWindowPos(w
->hwndSelf
, 0, w
->rectWindow
.left
+ dx
,
213 w
->rectWindow
.top
+ dy
, 0,0, SWP_NOZORDER
|
214 SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOREDRAW
|
219 if( flags
& (SW_INVALIDATE
| SW_ERASE
) )
220 RedrawWindow( hwnd
, NULL
, hrgnUpdate
, RDW_INVALIDATE
| RDW_ERASE
|
221 ((flags
& SW_ERASE
) ? RDW_ERASENOW
: 0) |
222 ((flags
& SW_SCROLLCHILDREN
) ? RDW_ALLCHILDREN
: 0 ) );
226 SetCaretPos( caretrc
.left
+ dx
, caretrc
.top
+ dy
);
230 if( bOwnRgn
&& hrgnUpdate
) DeleteObject( hrgnUpdate
);
231 DeleteObject( hrgnClip
);
234 WIN_ReleaseWndPtr(wnd
);