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