611f2486a7632fac009e042d29d24454ddbfe540
[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->spwndParent;
69 while (CurrentWindow)
70 {
71 if ( CurrentWindow->Status & WINDOWSTATUS_DESTROYING ||
72 CurrentWindow->Status & WINDOWSTATUS_DESTROYED )
73 {
74 DPRINT1("ATM the Current Window or Parent is dead!\n");
75 return NULL;
76 }
77
78 CurrentWnd = CurrentWindow->Wnd;
79 if (!CurrentWnd || !(CurrentWnd->style & WS_VISIBLE))
80 {
81 GreDeleteObject(VisRgn);
82 return NULL;
83 }
84
85 ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentWnd->rcClient);
86 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
87 GreDeleteObject(ClipRgn);
88
89 if ((PreviousWnd->style & WS_CLIPSIBLINGS) ||
90 (PreviousWnd == Wnd && ClipSiblings))
91 {
92 CurrentSibling = CurrentWindow->spwndChild;
93 while (CurrentSibling != NULL && CurrentSibling != PreviousWindow)
94 {
95 CurrentSiblingWnd = CurrentSibling->Wnd;
96 if ((CurrentSiblingWnd->style & WS_VISIBLE) &&
97 !(CurrentSiblingWnd->ExStyle & WS_EX_TRANSPARENT))
98 {
99 ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentSiblingWnd->rcWindow);
100 /* Combine it with the window region if available */
101 if (CurrentSibling->WindowRegion && !(CurrentSiblingWnd->style & WS_MINIMIZE))
102 {
103 NtGdiOffsetRgn(ClipRgn, -CurrentSiblingWnd->rcWindow.left, -CurrentSiblingWnd->rcWindow.top);
104 NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentSibling->WindowRegion, RGN_AND);
105 NtGdiOffsetRgn(ClipRgn, CurrentSiblingWnd->rcWindow.left, CurrentSiblingWnd->rcWindow.top);
106 }
107 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
108 GreDeleteObject(ClipRgn);
109 }
110 CurrentSibling = CurrentSibling->spwndNext;
111 }
112 }
113
114 PreviousWindow = CurrentWindow;
115 PreviousWnd = PreviousWindow->Wnd;
116 CurrentWindow = CurrentWindow->spwndParent;
117 }
118
119 if (ClipChildren)
120 {
121 CurrentWindow = Window->spwndChild;
122 while (CurrentWindow)
123 {
124 CurrentWnd = CurrentWindow->Wnd;
125 if ((CurrentWnd->style & WS_VISIBLE) &&
126 !(CurrentWnd->ExStyle & WS_EX_TRANSPARENT))
127 {
128 ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentWnd->rcWindow);
129 /* Combine it with the window region if available */
130 if (CurrentWindow->WindowRegion && !(CurrentWnd->style & WS_MINIMIZE))
131 {
132 NtGdiOffsetRgn(ClipRgn, -CurrentWnd->rcWindow.left, -CurrentWnd->rcWindow.top);
133 NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentWindow->WindowRegion, RGN_AND);
134 NtGdiOffsetRgn(ClipRgn, CurrentWnd->rcWindow.left, CurrentWnd->rcWindow.top);
135 }
136 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
137 GreDeleteObject(ClipRgn);
138 }
139 CurrentWindow = CurrentWindow->spwndNext;
140 }
141 }
142
143 if (Window->WindowRegion && !(Wnd->style & WS_MINIMIZE))
144 {
145 NtGdiOffsetRgn(VisRgn, -Wnd->rcWindow.left, -Wnd->rcWindow.top);
146 NtGdiCombineRgn(VisRgn, VisRgn, Window->WindowRegion, RGN_AND);
147 NtGdiOffsetRgn(VisRgn, Wnd->rcWindow.left, Wnd->rcWindow.top);
148 }
149
150 return VisRgn;
151 }
152
153 VOID FASTCALL
154 co_VIS_WindowLayoutChanged(
155 PWINDOW_OBJECT Window,
156 HRGN NewlyExposed)
157 {
158 HRGN Temp;
159 PWINDOW_OBJECT Parent;
160 USER_REFERENCE_ENTRY Ref;
161 PWND Wnd, ParentWnd;
162
163 ASSERT_REFS_CO(Window);
164
165 Wnd = Window->Wnd;
166
167 Temp = NtGdiCreateRectRgn(0, 0, 0, 0);
168 NtGdiCombineRgn(Temp, NewlyExposed, NULL, RGN_COPY);
169
170 Parent = Window->spwndParent;
171 if(Parent)
172 {
173 ParentWnd = Parent->Wnd;
174 NtGdiOffsetRgn(Temp,
175 Wnd->rcWindow.left - ParentWnd->rcClient.left,
176 Wnd->rcWindow.top - ParentWnd->rcClient.top);
177
178 UserRefObjectCo(Parent, &Ref);
179 co_UserRedrawWindow(Parent, NULL, Temp,
180 RDW_FRAME | RDW_ERASE | RDW_INVALIDATE |
181 RDW_ALLCHILDREN);
182 UserDerefObjectCo(Parent);
183 }
184 GreDeleteObject(Temp);
185 }
186
187 /* EOF */