Sync with trunk head (part 1 of 2)
[reactos.git] / 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 *
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * PURPOSE: Visibility computations
23 * FILE: subsys/win32k/ntuser/vis.c
24 * PROGRAMMER: Ge van Geldorp (ge@gse.nl)
25 */
26
27 #include <win32k.h>
28
29 #define NDEBUG
30 #include <debug.h>
31
32 HRGN FASTCALL
33 VIS_ComputeVisibleRegion(
34 PWINDOW_OBJECT Window,
35 BOOLEAN ClientArea,
36 BOOLEAN ClipChildren,
37 BOOLEAN ClipSiblings)
38 {
39 HRGN VisRgn, ClipRgn;
40 PWINDOW_OBJECT PreviousWindow, CurrentWindow, CurrentSibling;
41 PWND Wnd, CurrentWnd, PreviousWnd, CurrentSiblingWnd;
42
43 Wnd = Window->Wnd;
44
45 if (!Wnd || !(Wnd->style & WS_VISIBLE))
46 {
47 return NULL;
48 }
49
50 VisRgn = NULL;
51
52 if (ClientArea)
53 {
54 VisRgn = IntSysCreateRectRgnIndirect(&Window->Wnd->rcClient);
55 }
56 else
57 {
58 VisRgn = IntSysCreateRectRgnIndirect(&Window->Wnd->rcWindow);
59 }
60
61 /*
62 * Walk through all parent windows and for each clip the visble region
63 * to the parent's client area and exclude all siblings that are over
64 * our window.
65 */
66
67 PreviousWindow = Window;
68 PreviousWnd = PreviousWindow->Wnd;
69 CurrentWindow = Window->spwndParent;
70 while (CurrentWindow)
71 {
72 if ( CurrentWindow->state & WINDOWSTATUS_DESTROYING || // state2
73 CurrentWindow->state & WINDOWSTATUS_DESTROYED )
74 {
75 DPRINT1("ATM the Current Window or Parent is dead!\n");
76 if (VisRgn) REGION_FreeRgnByHandle(VisRgn);
77 return NULL;
78 }
79
80 CurrentWnd = CurrentWindow->Wnd;
81 if (!CurrentWnd || !(CurrentWnd->style & WS_VISIBLE))
82 {
83 if (VisRgn) REGION_FreeRgnByHandle(VisRgn);
84 return NULL;
85 }
86
87 ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWnd->rcClient);
88 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
89 REGION_FreeRgnByHandle(ClipRgn);
90
91 if ((PreviousWnd->style & WS_CLIPSIBLINGS) ||
92 (PreviousWnd == Wnd && ClipSiblings))
93 {
94 CurrentSibling = CurrentWindow->spwndChild;
95 while ( CurrentSibling != NULL &&
96 CurrentSibling != PreviousWindow &&
97 CurrentSibling->Wnd )
98 {
99 CurrentSiblingWnd = CurrentSibling->Wnd;
100 if ((CurrentSiblingWnd->style & WS_VISIBLE) &&
101 !(CurrentSiblingWnd->ExStyle & WS_EX_TRANSPARENT))
102 {
103 ClipRgn = IntSysCreateRectRgnIndirect(&CurrentSiblingWnd->rcWindow);
104 /* Combine it with the window region if available */
105 if (CurrentSibling->hrgnClip && !(CurrentSiblingWnd->style & WS_MINIMIZE))
106 {
107 NtGdiOffsetRgn(ClipRgn, -CurrentSiblingWnd->rcWindow.left, -CurrentSiblingWnd->rcWindow.top);
108 NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentSibling->hrgnClip, RGN_AND);
109 NtGdiOffsetRgn(ClipRgn, CurrentSiblingWnd->rcWindow.left, CurrentSiblingWnd->rcWindow.top);
110 }
111 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
112 REGION_FreeRgnByHandle(ClipRgn);
113 }
114 CurrentSibling = CurrentSibling->spwndNext;
115 }
116 }
117
118 PreviousWindow = CurrentWindow;
119 PreviousWnd = PreviousWindow->Wnd;
120 CurrentWindow = CurrentWindow->spwndParent;
121 }
122
123 if (ClipChildren)
124 {
125 CurrentWindow = Window->spwndChild;
126 while (CurrentWindow && CurrentWindow->Wnd)
127 {
128 CurrentWnd = CurrentWindow->Wnd;
129 if ((CurrentWnd->style & WS_VISIBLE) &&
130 !(CurrentWnd->ExStyle & WS_EX_TRANSPARENT))
131 {
132 ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWnd->rcWindow);
133 /* Combine it with the window region if available */
134 if (CurrentWindow->hrgnClip && !(CurrentWnd->style & WS_MINIMIZE))
135 {
136 NtGdiOffsetRgn(ClipRgn, -CurrentWnd->rcWindow.left, -CurrentWnd->rcWindow.top);
137 NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentWindow->hrgnClip, RGN_AND);
138 NtGdiOffsetRgn(ClipRgn, CurrentWnd->rcWindow.left, CurrentWnd->rcWindow.top);
139 }
140 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
141 REGION_FreeRgnByHandle(ClipRgn);
142 }
143 CurrentWindow = CurrentWindow->spwndNext;
144 }
145 }
146
147 if (Window->hrgnClip && !(Wnd->style & WS_MINIMIZE))
148 {
149 NtGdiOffsetRgn(VisRgn, -Wnd->rcWindow.left, -Wnd->rcWindow.top);
150 NtGdiCombineRgn(VisRgn, VisRgn, Window->hrgnClip, RGN_AND);
151 NtGdiOffsetRgn(VisRgn, Wnd->rcWindow.left, Wnd->rcWindow.top);
152 }
153
154 return VisRgn;
155 }
156
157 VOID FASTCALL
158 co_VIS_WindowLayoutChanged(
159 PWINDOW_OBJECT Window,
160 HRGN NewlyExposed)
161 {
162 HRGN Temp;
163 PWINDOW_OBJECT Parent;
164 USER_REFERENCE_ENTRY Ref;
165 PWND Wnd, ParentWnd;
166
167 ASSERT_REFS_CO(Window);
168
169 Wnd = Window->Wnd;
170
171 Temp = IntSysCreateRectRgn(0, 0, 0, 0);
172 NtGdiCombineRgn(Temp, NewlyExposed, NULL, RGN_COPY);
173
174 Parent = Window->spwndParent;
175 if(Parent)
176 {
177 ParentWnd = Parent->Wnd;
178 NtGdiOffsetRgn(Temp,
179 Wnd->rcWindow.left - ParentWnd->rcClient.left,
180 Wnd->rcWindow.top - ParentWnd->rcClient.top);
181
182 UserRefObjectCo(Parent, &Ref);
183 co_UserRedrawWindow(Parent, NULL, Temp,
184 RDW_FRAME | RDW_ERASE | RDW_INVALIDATE |
185 RDW_ALLCHILDREN);
186 UserDerefObjectCo(Parent);
187 }
188 REGION_FreeRgnByHandle(Temp);
189 }
190
191 /* EOF */