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