Changes for multiple window support
[reactos.git] / reactos / subsys / win32k / ntuser / vis.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 *
19 * $Id: vis.c,v 1.1 2003/07/17 07:49:15 gvg Exp $
20 *
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)
26 */
27
28 #include <win32k/win32k.h>
29 #include <include/painting.h>
30 #include <include/rect.h>
31 #include <include/vis.h>
32
33
34 #define NDEBUG
35 #include <win32k/debug1.h>
36 #include <debug.h>
37
38 BOOL STATIC FASTCALL
39 VIS_GetVisRect(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window,
40 BOOLEAN ClientArea, RECT* Rect)
41 {
42 PWINDOW_OBJECT DesktopWindow;
43
44 if (ClientArea)
45 {
46 *Rect = Window->ClientRect;
47 }
48 else
49 {
50 *Rect = Window->WindowRect;
51 }
52
53 if (0 == (Window->Style & WS_VISIBLE))
54 {
55 W32kSetEmptyRect(Rect);
56
57 return FALSE;
58 }
59
60 if (Window->Self == Desktop->DesktopWindow)
61 {
62 return TRUE;
63 }
64
65 if (0 != (Window->Style & WS_CHILD))
66 {
67 do
68 {
69 Window = Window->Parent;
70 if (WS_VISIBLE != (Window->Style & (WS_ICONIC | WS_VISIBLE)))
71 {
72 W32kSetEmptyRect(Rect);
73 return FALSE;
74 }
75 if (! W32kIntersectRect(Rect, Rect, &(Window->ClientRect)))
76 {
77 return FALSE;
78 }
79 }
80 while (0 != (Window->Style & WS_CHILD));
81 }
82
83 DesktopWindow = W32kGetWindowObject(Desktop->DesktopWindow);
84 if (NULL == DesktopWindow)
85 {
86 ASSERT(FALSE);
87 return FALSE;
88 }
89
90 if (! W32kIntersectRect(Rect, Rect, &(DesktopWindow->ClientRect)))
91 {
92 W32kReleaseWindowObject(DesktopWindow);
93 return FALSE;
94 }
95 W32kReleaseWindowObject(DesktopWindow);
96
97 return TRUE;
98 }
99
100 STATIC BOOL FASTCALL
101 VIS_AddClipRects(PWINDOW_OBJECT Parent, PWINDOW_OBJECT End,
102 HRGN ClipRgn, PRECT Rect)
103 {
104 PLIST_ENTRY ChildListEntry;
105 PWINDOW_OBJECT Child;
106 RECT Intersect;
107
108 ExAcquireFastMutexUnsafe(&Parent->ChildrenListLock);
109 ChildListEntry = Parent->ChildrenListHead.Flink;
110 while (ChildListEntry != &Parent->ChildrenListHead)
111 {
112 Child = CONTAINING_RECORD(ChildListEntry, WINDOW_OBJECT,
113 SiblingListEntry);
114 if (Child == End)
115 {
116 ExReleaseFastMutexUnsafe(&Parent->ChildrenListLock);
117 return TRUE;
118 }
119 if (Child->Style & WS_VISIBLE)
120 {
121 if (W32kIntersectRect(&Intersect, &Child->WindowRect, Rect))
122 {
123 UnsafeW32kUnionRectWithRgn(ClipRgn, &Child->WindowRect);
124 }
125 }
126 ChildListEntry = ChildListEntry->Flink;
127 }
128
129 ExReleaseFastMutexUnsafe(&Parent->ChildrenListLock);
130 return FALSE;
131 }
132
133 HRGN FASTCALL
134 VIS_ComputeVisibleRegion(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window,
135 BOOLEAN ClientArea, BOOLEAN ClipChildren,
136 BOOLEAN ClipSiblings)
137 {
138 HRGN VisRgn;
139 RECT Rect;
140 HRGN ClipRgn;
141 PWINDOW_OBJECT DesktopWindow;
142
143 DesktopWindow = W32kGetWindowObject(Desktop->DesktopWindow);
144 if (NULL == DesktopWindow)
145 {
146 ASSERT(FALSE);
147 return NULL;
148 }
149
150 if (VIS_GetVisRect(Desktop, Window, ClientArea, &Rect))
151 {
152 VisRgn = UnsafeW32kCreateRectRgnIndirect(&Rect);
153 if (NULL != VisRgn)
154 {
155 ClipRgn = W32kCreateRectRgn(0, 0, 0, 0);
156
157 if (ClipRgn != NULL)
158 {
159 if (ClipChildren &&
160 ! IsListEmpty(&Window->ChildrenListHead))
161 {
162 VIS_AddClipRects(Window, NULL, ClipRgn, &Rect);
163 }
164
165 if (ClipSiblings && 0 != (Window->Style & WS_CHILD))
166 {
167 VIS_AddClipRects(Window->Parent, Window, ClipRgn, &Rect);
168 }
169
170 while (0 != (Window->Style & WS_CHILD))
171 {
172 if (0 != (Window->Style & WS_CLIPSIBLINGS))
173 {
174 VIS_AddClipRects(Window->Parent, Window, ClipRgn, &Rect);
175 }
176 Window = Window->Parent;
177 }
178
179 VIS_AddClipRects(DesktopWindow, Window, ClipRgn, &Rect);
180
181 W32kCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
182 W32kDeleteObject(ClipRgn);
183 }
184 else
185 {
186 W32kDeleteObject(VisRgn);
187 VisRgn = NULL;
188 }
189 }
190 }
191 else
192 {
193 VisRgn = W32kCreateRectRgn(0, 0, 0, 0);
194 }
195
196 W32kReleaseWindowObject(DesktopWindow);
197
198 return VisRgn;
199 }
200
201 VOID STATIC FASTCALL
202 VIS_RepaintDesktop(HWND Desktop, HRGN RepaintRgn)
203 {
204 HDC dc = NtUserGetDC(Desktop);
205 HBRUSH DesktopBrush = W32kCreateSolidBrush(RGB(58, 110, 165));
206 W32kFillRgn(dc, RepaintRgn, DesktopBrush);
207 W32kDeleteObject(DesktopBrush);
208 NtUserReleaseDC(Desktop, dc);
209 }
210
211
212 VOID FASTCALL
213 VIS_WindowLayoutChanged(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window,
214 HRGN UncoveredRgn)
215 {
216 PWINDOW_OBJECT DesktopWindow;
217 PWINDOW_OBJECT Child;
218 PLIST_ENTRY CurrentEntry;
219 HRGN Uncovered;
220 HRGN Covered;
221
222 DesktopWindow = W32kGetWindowObject(Desktop->DesktopWindow);
223 Uncovered = UnsafeW32kCreateRectRgnIndirect(&DesktopWindow->WindowRect);
224 ExAcquireFastMutexUnsafe(&DesktopWindow->ChildrenListLock);
225 CurrentEntry = DesktopWindow->ChildrenListHead.Flink;
226 while (CurrentEntry != &DesktopWindow->ChildrenListHead)
227 {
228 Child = CONTAINING_RECORD(CurrentEntry, WINDOW_OBJECT, SiblingListEntry);
229 if (0 != (Child->Style & WS_VISIBLE))
230 {
231 Covered = UnsafeW32kCreateRectRgnIndirect(&Child->WindowRect);
232 W32kCombineRgn(Uncovered, Uncovered, Covered, RGN_DIFF);
233 PaintRedrawWindow(Child->Self, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE, 0);
234 W32kDeleteObject(Covered);
235 }
236 CurrentEntry = CurrentEntry->Flink;
237 }
238 ExReleaseFastMutexUnsafe(&DesktopWindow->ChildrenListLock);
239 VIS_RepaintDesktop(DesktopWindow->Self, Uncovered);
240 W32kDeleteObject(Uncovered);
241 }
242
243 /* EOF */