- fix IntValidateParent
[reactos.git] / reactos / subsystems / win32 / 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$
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 <w32k.h>
29
30 #define NDEBUG
31 #include <debug.h>
32
33 HRGN FASTCALL
34 VIS_ComputeVisibleRegion(
35 PWINDOW_OBJECT Window,
36 BOOLEAN ClientArea,
37 BOOLEAN ClipChildren,
38 BOOLEAN ClipSiblings)
39 {
40 HRGN VisRgn, ClipRgn;
41 PWINDOW_OBJECT PreviousWindow, CurrentWindow, CurrentSibling;
42
43 if (!(Window->Style & WS_VISIBLE))
44 {
45 return NULL;
46 }
47
48 if (ClientArea)
49 {
50 if (!(ClipRgn = VIS_ComputeVisibleRegion(Window, FALSE, ClipChildren, ClipSiblings)))
51 {
52 return NULL;
53 }
54 if (!(VisRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect)))
55 {
56 NtGdiDeleteObject(VisRgn);
57 return NULL;
58 }
59 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
60 NtGdiDeleteObject(ClipRgn);
61 return VisRgn;
62 }
63
64 VisRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
65
66 /*
67 * Walk through all parent windows and for each clip the visble region
68 * to the parent's client area and exclude all siblings that are over
69 * our window.
70 */
71
72 PreviousWindow = Window;
73 CurrentWindow = Window->Parent;
74 while (CurrentWindow)
75 {
76 if (!(CurrentWindow->Style & WS_VISIBLE))
77 {
78 NtGdiDeleteObject(VisRgn);
79 return NULL;
80 }
81
82 ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentWindow->ClientRect);
83 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
84 NtGdiDeleteObject(ClipRgn);
85
86 if ((PreviousWindow->Style & WS_CLIPSIBLINGS) ||
87 (PreviousWindow == Window && ClipSiblings))
88 {
89 CurrentSibling = CurrentWindow->FirstChild;
90 while (CurrentSibling != NULL && CurrentSibling != PreviousWindow)
91 {
92 if ((CurrentSibling->Style & WS_VISIBLE) &&
93 !(CurrentSibling->ExStyle & WS_EX_TRANSPARENT))
94 {
95 ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentSibling->WindowRect);
96 /* Combine it with the window region if available */
97 if (CurrentSibling->WindowRegion && !(CurrentSibling->Style & WS_MINIMIZE))
98 {
99 NtGdiOffsetRgn(ClipRgn, -CurrentSibling->WindowRect.left, -CurrentSibling->WindowRect.top);
100 NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentSibling->WindowRegion, RGN_AND);
101 NtGdiOffsetRgn(ClipRgn, CurrentSibling->WindowRect.left, CurrentSibling->WindowRect.top);
102 }
103 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
104 NtGdiDeleteObject(ClipRgn);
105 }
106 CurrentSibling = CurrentSibling->NextSibling;
107 }
108 }
109
110 PreviousWindow = CurrentWindow;
111 CurrentWindow = CurrentWindow->Parent;
112 }
113
114 if (ClipChildren)
115 {
116 CurrentWindow = Window->FirstChild;
117 while (CurrentWindow)
118 {
119 if ((CurrentWindow->Style & WS_VISIBLE) &&
120 !(CurrentWindow->ExStyle & WS_EX_TRANSPARENT))
121 {
122 ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentWindow->WindowRect);
123 /* Combine it with the window region if available */
124 if (CurrentWindow->WindowRegion && !(CurrentWindow->Style & WS_MINIMIZE))
125 {
126 NtGdiOffsetRgn(ClipRgn, -CurrentWindow->WindowRect.left, -CurrentWindow->WindowRect.top);
127 NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentWindow->WindowRegion, RGN_AND);
128 NtGdiOffsetRgn(ClipRgn, CurrentWindow->WindowRect.left, CurrentWindow->WindowRect.top);
129 }
130 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
131 NtGdiDeleteObject(ClipRgn);
132 }
133 CurrentWindow = CurrentWindow->NextSibling;
134 }
135 }
136
137 if (Window->WindowRegion && !(Window->Style & WS_MINIMIZE))
138 {
139 NtGdiOffsetRgn(VisRgn, -Window->WindowRect.left, -Window->WindowRect.top);
140 NtGdiCombineRgn(VisRgn, VisRgn, Window->WindowRegion, RGN_AND);
141 NtGdiOffsetRgn(VisRgn, Window->WindowRect.left, Window->WindowRect.top);
142 }
143
144 return VisRgn;
145 }
146
147 VOID FASTCALL
148 co_VIS_WindowLayoutChanged(
149 PWINDOW_OBJECT Window,
150 HRGN NewlyExposed)
151 {
152 HRGN Temp;
153 PWINDOW_OBJECT Parent;
154 USER_REFERENCE_ENTRY Ref;
155
156 ASSERT_REFS_CO(Window);
157
158 Temp = NtGdiCreateRectRgn(0, 0, 0, 0);
159 NtGdiCombineRgn(Temp, NewlyExposed, NULL, RGN_COPY);
160
161 Parent = Window->Parent;
162 if(Parent)
163 {
164 NtGdiOffsetRgn(Temp,
165 Window->WindowRect.left - Parent->ClientRect.left,
166 Window->WindowRect.top - Parent->ClientRect.top);
167
168 UserRefObjectCo(Parent, &Ref);
169 co_UserRedrawWindow(Parent, NULL, Temp,
170 RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_INVALIDATE |
171 RDW_ALLCHILDREN);
172 UserDerefObjectCo(Parent);
173 }
174 NtGdiDeleteObject(Temp);
175 }
176
177 /* EOF */