2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Visibility computations
24 * FILE: subsys/win32k/ntuser/vis.c
25 * PROGRAMMER: Ge van Geldorp (ge@gse.nl)
28 #include <win32k/win32k.h>
29 #include <include/painting.h>
30 #include <include/rect.h>
31 #include <include/vis.h>
35 #include <win32k/debug1.h>
39 VIS_GetVisRect(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window,
40 BOOLEAN ClientArea, RECT* Rect)
42 PWINDOW_OBJECT DesktopWindow;
46 *Rect = Window->ClientRect;
50 *Rect = Window->WindowRect;
53 if (0 == (Window->Style & WS_VISIBLE))
55 NtGdiSetEmptyRect(Rect);
60 if (Window->Self == Desktop->DesktopWindow)
65 if (0 != (Window->Style & WS_CHILD))
69 Window = Window->Parent;
70 if (WS_VISIBLE != (Window->Style & (WS_ICONIC | WS_VISIBLE)))
72 NtGdiSetEmptyRect(Rect);
75 if (! NtGdiIntersectRect(Rect, Rect, &(Window->ClientRect)))
80 while (0 != (Window->Style & WS_CHILD));
83 DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow);
84 if (NULL == DesktopWindow)
90 if (! NtGdiIntersectRect(Rect, Rect, &(DesktopWindow->ClientRect)))
92 IntReleaseWindowObject(DesktopWindow);
95 IntReleaseWindowObject(DesktopWindow);
101 VIS_AddClipRects(PWINDOW_OBJECT Parent, PWINDOW_OBJECT End,
102 HRGN ClipRgn, PRECT Rect)
104 PWINDOW_OBJECT Child;
107 ExAcquireFastMutexUnsafe(&Parent->ChildrenListLock);
108 Child = Parent->FirstChild;
113 ExReleaseFastMutexUnsafe(&Parent->ChildrenListLock);
117 if (Child->Style & WS_VISIBLE)
119 if (NtGdiIntersectRect(&Intersect, &Child->WindowRect, Rect))
121 UnsafeIntUnionRectWithRgn(ClipRgn, &Child->WindowRect);
125 Child = Child->NextSibling;
128 ExReleaseFastMutexUnsafe(&Parent->ChildrenListLock);
134 VIS_ComputeVisibleRegion(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window,
135 BOOLEAN ClientArea, BOOLEAN ClipChildren,
136 BOOLEAN ClipSiblings)
141 PWINDOW_OBJECT DesktopWindow;
142 INT LeftOffset, TopOffset;
144 DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow);
145 if (NULL == DesktopWindow)
151 if (VIS_GetVisRect(Desktop, Window, ClientArea, &Rect))
153 VisRgn = UnsafeIntCreateRectRgnIndirect(&Rect);
158 LeftOffset = Window->ClientRect.left;
159 TopOffset = Window->ClientRect.top;
163 LeftOffset = Window->WindowRect.left;
164 TopOffset = Window->WindowRect.top;
167 ClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
171 if (ClipChildren && Window->FirstChild)
173 VIS_AddClipRects(Window, NULL, ClipRgn, &Rect);
176 if (ClipSiblings && 0 != (Window->Style & WS_CHILD))
178 VIS_AddClipRects(Window->Parent, Window, ClipRgn, &Rect);
181 while (0 != (Window->Style & WS_CHILD))
183 if (0 != (Window->Style & WS_CLIPSIBLINGS))
185 VIS_AddClipRects(Window->Parent, Window, ClipRgn, &Rect);
187 Window = Window->Parent;
190 VIS_AddClipRects(DesktopWindow, Window, ClipRgn, &Rect);
192 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
193 NtGdiDeleteObject(ClipRgn);
194 NtGdiOffsetRgn(VisRgn, -LeftOffset, -TopOffset);
198 NtGdiDeleteObject(VisRgn);
205 VisRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
208 IntReleaseWindowObject(DesktopWindow);
213 /* FIXME: to be replaced by a normal window proc in CSRSS */
215 VIS_RepaintDesktop(HWND Desktop, HRGN RepaintRgn)
217 HDC dc = NtUserGetDC(Desktop);
218 HBRUSH DesktopBrush = NtGdiCreateSolidBrush(RGB(58, 110, 165));
219 NtGdiFillRgn(dc, RepaintRgn, DesktopBrush);
220 NtGdiDeleteObject(DesktopBrush);
221 NtUserReleaseDC(Desktop, dc);
226 GetUncoveredArea(HRGN Uncovered, PWINDOW_OBJECT Parent, PWINDOW_OBJECT TargetChild,
229 PWINDOW_OBJECT Child;
234 ExAcquireFastMutexUnsafe(&Parent->ChildrenListLock);
235 Child = Parent->FirstChild;
236 while (! Passed && Child)
238 if (0 != (Child->Style & WS_VISIBLE) && (Child != TargetChild || IncludeTarget))
240 Covered = UnsafeIntCreateRectRgnIndirect(&Child->WindowRect);
241 NtGdiCombineRgn(Uncovered, Uncovered, Covered, RGN_DIFF);
242 NtGdiDeleteObject(Covered);
244 if (Child == TargetChild)
248 Child = Child->NextSibling;
250 ExReleaseFastMutexUnsafe(&Parent->ChildrenListLock);
255 VIS_WindowLayoutChanged(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window,
258 PWINDOW_OBJECT DesktopWindow;
259 PWINDOW_OBJECT Parent;
260 PWINDOW_OBJECT Sibling;
261 PWINDOW_OBJECT TopLevel;
270 DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow);
271 Uncovered = UnsafeIntCreateRectRgnIndirect(&DesktopWindow->WindowRect);
273 if (Window->Style & WS_CHILD)
275 /* Determine our toplevel window */
277 while (TopLevel->Style & WS_CHILD)
279 TopLevel = TopLevel->Parent;
282 GetUncoveredArea(Uncovered, DesktopWindow, TopLevel, FALSE);
283 Parent = Window->Parent;
287 Parent = DesktopWindow;
289 GetUncoveredArea(Uncovered, Parent, Window, TRUE);
291 ExAcquireFastMutexUnsafe(&Parent->ChildrenListLock);
292 Sibling = Window->NextSibling;
295 if (0 != (Sibling->Style & WS_VISIBLE))
297 Offset.x = - Sibling->WindowRect.left;
298 Offset.y = - Sibling->WindowRect.top;
299 DirtyRgn = REGION_CropRgn(NULL, Uncovered, &Sibling->WindowRect, &Offset);
300 Offset.x = Window->WindowRect.left - Sibling->WindowRect.left;
301 Offset.y = Window->WindowRect.top - Sibling->WindowRect.top;
302 ExposedWindow = REGION_CropRgn(NULL, NewlyExposed, NULL, &Offset);
303 RgnType = NtGdiCombineRgn(DirtyRgn, DirtyRgn, ExposedWindow, RGN_AND);
304 if (NULLREGION != RgnType && ERROR != RgnType)
306 PaintRedrawWindow(Sibling, NULL, DirtyRgn,
307 RDW_INVALIDATE | RDW_FRAME | RDW_ERASE
308 | RDW_ALLCHILDREN, RDW_EX_XYWINDOW);
310 Covered = UnsafeIntCreateRectRgnIndirect(&Sibling->WindowRect);
311 NtGdiCombineRgn(Uncovered, Uncovered, Covered, RGN_DIFF);
312 NtGdiDeleteObject(Covered);
313 NtGdiDeleteObject(ExposedWindow);
314 NtGdiDeleteObject(DirtyRgn);
317 Sibling = Sibling->NextSibling;
319 ExReleaseFastMutexUnsafe(&Parent->ChildrenListLock);
321 if (Window->Style & WS_CHILD)
323 Offset.x = - Parent->WindowRect.left;
324 Offset.y = - Parent->WindowRect.top;
325 DirtyRgn = REGION_CropRgn(NULL, Uncovered, &Parent->WindowRect, &Offset);
326 Offset.x = Window->WindowRect.left - Parent->WindowRect.left;
327 Offset.y = Window->WindowRect.top - Parent->WindowRect.top;
328 ExposedWindow = REGION_CropRgn(NULL, NewlyExposed, NULL, &Offset);
329 RgnType = NtGdiCombineRgn(DirtyRgn, DirtyRgn, ExposedWindow, RGN_AND);
330 if (NULLREGION != RgnType && ERROR != RgnType)
332 PaintRedrawWindow(Parent, NULL, DirtyRgn,
333 RDW_INVALIDATE | RDW_FRAME | RDW_ERASE
334 | RDW_NOCHILDREN, RDW_EX_XYWINDOW);
336 NtGdiDeleteObject(ExposedWindow);
337 NtGdiDeleteObject(DirtyRgn);
341 Repaint = NtGdiCreateRectRgn(0, 0, 0, 0);
342 NtGdiCombineRgn(Repaint, NewlyExposed, NULL, RGN_COPY);
343 NtGdiOffsetRgn(Repaint, Window->WindowRect.left, Window->WindowRect.top);
344 NtGdiCombineRgn(Repaint, Repaint, Uncovered, RGN_AND);
345 VIS_RepaintDesktop(DesktopWindow->Self, Repaint);
346 NtGdiDeleteObject(Repaint);
349 NtGdiDeleteObject(Uncovered);