0bf5dc88e729c1e83b49917934c1dfcb3317b7e6
[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 PWND Wnd,
35 BOOLEAN ClientArea,
36 BOOLEAN ClipChildren,
37 BOOLEAN ClipSiblings)
38 {
39 HRGN VisRgn, ClipRgn;
40 PWND PreviousWindow, CurrentWindow, CurrentSibling;
41
42 if (!Wnd || !(Wnd->style & WS_VISIBLE))
43 {
44 return NULL;
45 }
46
47 VisRgn = NULL;
48
49 if (ClientArea)
50 {
51 VisRgn = IntSysCreateRectRgnIndirect(&Wnd->rcClient);
52 }
53 else
54 {
55 VisRgn = IntSysCreateRectRgnIndirect(&Wnd->rcWindow);
56 }
57
58 /*
59 * Walk through all parent windows and for each clip the visble region
60 * to the parent's client area and exclude all siblings that are over
61 * our window.
62 */
63
64 PreviousWindow = Wnd;
65 CurrentWindow = Wnd->spwndParent;
66 while (CurrentWindow)
67 {
68 if ( CurrentWindow->state2 & WNDS2_INDESTROY ||
69 CurrentWindow->state & WNDS_DESTROYED )
70 {
71 DPRINT1("ATM the Current Window or Parent is dead!\n");
72 if (VisRgn) REGION_FreeRgnByHandle(VisRgn);
73 return NULL;
74 }
75
76 if (!(CurrentWindow->style & WS_VISIBLE))
77 {
78 if (VisRgn) REGION_FreeRgnByHandle(VisRgn);
79 return NULL;
80 }
81
82 ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWindow->rcClient);
83 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
84 REGION_FreeRgnByHandle(ClipRgn);
85
86 if ((PreviousWindow->style & WS_CLIPSIBLINGS) ||
87 (PreviousWindow == Wnd && ClipSiblings))
88 {
89 CurrentSibling = CurrentWindow->spwndChild;
90 while ( CurrentSibling != NULL &&
91 CurrentSibling != PreviousWindow )
92 {
93 if ((CurrentSibling->style & WS_VISIBLE) &&
94 !(CurrentSibling->ExStyle & WS_EX_TRANSPARENT))
95 {
96 ClipRgn = IntSysCreateRectRgnIndirect(&CurrentSibling->rcWindow);
97 /* Combine it with the window region if available */
98 if (CurrentSibling->hrgnClip && !(CurrentSibling->style & WS_MINIMIZE))
99 {
100 NtGdiOffsetRgn(ClipRgn, -CurrentSibling->rcWindow.left, -CurrentSibling->rcWindow.top);
101 NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentSibling->hrgnClip, RGN_AND);
102 NtGdiOffsetRgn(ClipRgn, CurrentSibling->rcWindow.left, CurrentSibling->rcWindow.top);
103 }
104 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
105 REGION_FreeRgnByHandle(ClipRgn);
106 }
107 CurrentSibling = CurrentSibling->spwndNext;
108 }
109 }
110
111 PreviousWindow = CurrentWindow;
112 CurrentWindow = CurrentWindow->spwndParent;
113 }
114
115 if (ClipChildren)
116 {
117 CurrentWindow = Wnd->spwndChild;
118 while (CurrentWindow)
119 {
120 if ((CurrentWindow->style & WS_VISIBLE) &&
121 !(CurrentWindow->ExStyle & WS_EX_TRANSPARENT))
122 {
123 ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWindow->rcWindow);
124 /* Combine it with the window region if available */
125 if (CurrentWindow->hrgnClip && !(CurrentWindow->style & WS_MINIMIZE))
126 {
127 NtGdiOffsetRgn(ClipRgn, -CurrentWindow->rcWindow.left, -CurrentWindow->rcWindow.top);
128 NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentWindow->hrgnClip, RGN_AND);
129 NtGdiOffsetRgn(ClipRgn, CurrentWindow->rcWindow.left, CurrentWindow->rcWindow.top);
130 }
131 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
132 REGION_FreeRgnByHandle(ClipRgn);
133 }
134 CurrentWindow = CurrentWindow->spwndNext;
135 }
136 }
137
138 if (Wnd->hrgnClip && !(Wnd->style & WS_MINIMIZE))
139 {
140 NtGdiOffsetRgn(VisRgn, -Wnd->rcWindow.left, -Wnd->rcWindow.top);
141 NtGdiCombineRgn(VisRgn, VisRgn, Wnd->hrgnClip, RGN_AND);
142 NtGdiOffsetRgn(VisRgn, Wnd->rcWindow.left, Wnd->rcWindow.top);
143 }
144
145 return VisRgn;
146 }
147
148 VOID FASTCALL
149 co_VIS_WindowLayoutChanged(
150 PWND Wnd,
151 HRGN NewlyExposed)
152 {
153 HRGN Temp;
154 PWND Parent;
155 USER_REFERENCE_ENTRY Ref;
156
157 ASSERT_REFS_CO(Wnd);
158
159 Temp = IntSysCreateRectRgn(0, 0, 0, 0);
160 NtGdiCombineRgn(Temp, NewlyExposed, NULL, RGN_COPY);
161
162 Parent = Wnd->spwndParent;
163 if(Parent)
164 {
165 NtGdiOffsetRgn(Temp,
166 Wnd->rcWindow.left - Parent->rcClient.left,
167 Wnd->rcWindow.top - Parent->rcClient.top);
168
169 UserRefObjectCo(Parent, &Ref);
170 co_UserRedrawWindow(Parent, NULL, Temp,
171 RDW_FRAME | RDW_ERASE | RDW_INVALIDATE |
172 RDW_ALLCHILDREN);
173 UserDerefObjectCo(Parent);
174 }
175 REGION_FreeRgnByHandle(Temp);
176 }
177
178 /* EOF */