1f0b7dc98f7aca4203ff717b4683b4526769ae1d
[reactos.git] / reactos / win32ss / user / ntuser / vis.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Visibility computations
5 * FILE: subsys/win32k/ntuser/vis.c
6 * PROGRAMMER: Ge van Geldorp (ge@gse.nl)
7 */
8
9 #include <win32k.h>
10 DBG_DEFAULT_CHANNEL(UserWinpos);
11
12 HRGN FASTCALL
13 VIS_ComputeVisibleRegion(
14 PWND Wnd,
15 BOOLEAN ClientArea,
16 BOOLEAN ClipChildren,
17 BOOLEAN ClipSiblings)
18 {
19 HRGN VisRgn, ClipRgn;
20 PWND PreviousWindow, CurrentWindow, CurrentSibling;
21
22 if (!Wnd || !(Wnd->style & WS_VISIBLE))
23 {
24 return NULL;
25 }
26
27 VisRgn = NULL;
28
29 if (ClientArea)
30 {
31 VisRgn = IntSysCreateRectRgnIndirect(&Wnd->rcClient);
32 }
33 else
34 {
35 VisRgn = IntSysCreateRectRgnIndirect(&Wnd->rcWindow);
36 }
37
38 /*
39 * Walk through all parent windows and for each clip the visble region
40 * to the parent's client area and exclude all siblings that are over
41 * our window.
42 */
43
44 PreviousWindow = Wnd;
45 CurrentWindow = Wnd->spwndParent;
46 while (CurrentWindow)
47 {
48 if ( CurrentWindow->state2 & WNDS2_INDESTROY ||
49 CurrentWindow->state & WNDS_DESTROYED )
50 {
51 ERR("ATM the Current Window or Parent is dead!\n");
52 if (VisRgn) GreDeleteObject(VisRgn);
53 return NULL;
54 }
55
56 if (!(CurrentWindow->style & WS_VISIBLE))
57 {
58 if (VisRgn) GreDeleteObject(VisRgn);
59 return NULL;
60 }
61
62 ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWindow->rcClient);
63 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
64 GreDeleteObject(ClipRgn);
65
66 if ((PreviousWindow->style & WS_CLIPSIBLINGS) ||
67 (PreviousWindow == Wnd && ClipSiblings))
68 {
69 CurrentSibling = CurrentWindow->spwndChild;
70 while ( CurrentSibling != NULL &&
71 CurrentSibling != PreviousWindow )
72 {
73 if ((CurrentSibling->style & WS_VISIBLE) &&
74 !(CurrentSibling->ExStyle & WS_EX_TRANSPARENT))
75 {
76 ClipRgn = IntSysCreateRectRgnIndirect(&CurrentSibling->rcWindow);
77 /* Combine it with the window region if available */
78 if (CurrentSibling->hrgnClip && !(CurrentSibling->style & WS_MINIMIZE))
79 {
80 NtGdiOffsetRgn(ClipRgn, -CurrentSibling->rcWindow.left, -CurrentSibling->rcWindow.top);
81 NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentSibling->hrgnClip, RGN_AND);
82 NtGdiOffsetRgn(ClipRgn, CurrentSibling->rcWindow.left, CurrentSibling->rcWindow.top);
83 }
84 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
85 GreDeleteObject(ClipRgn);
86 }
87 CurrentSibling = CurrentSibling->spwndNext;
88 }
89 }
90
91 PreviousWindow = CurrentWindow;
92 CurrentWindow = CurrentWindow->spwndParent;
93 }
94
95 if (ClipChildren)
96 {
97 CurrentWindow = Wnd->spwndChild;
98 while (CurrentWindow)
99 {
100 if ((CurrentWindow->style & WS_VISIBLE) &&
101 !(CurrentWindow->ExStyle & WS_EX_TRANSPARENT))
102 {
103 ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWindow->rcWindow);
104 /* Combine it with the window region if available */
105 if (CurrentWindow->hrgnClip && !(CurrentWindow->style & WS_MINIMIZE))
106 {
107 NtGdiOffsetRgn(ClipRgn, -CurrentWindow->rcWindow.left, -CurrentWindow->rcWindow.top);
108 NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentWindow->hrgnClip, RGN_AND);
109 NtGdiOffsetRgn(ClipRgn, CurrentWindow->rcWindow.left, CurrentWindow->rcWindow.top);
110 }
111 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
112 GreDeleteObject(ClipRgn);
113 }
114 CurrentWindow = CurrentWindow->spwndNext;
115 }
116 }
117
118 if (Wnd->hrgnClip && !(Wnd->style & WS_MINIMIZE))
119 {
120 NtGdiOffsetRgn(VisRgn, -Wnd->rcWindow.left, -Wnd->rcWindow.top);
121 NtGdiCombineRgn(VisRgn, VisRgn, Wnd->hrgnClip, RGN_AND);
122 NtGdiOffsetRgn(VisRgn, Wnd->rcWindow.left, Wnd->rcWindow.top);
123 }
124
125 return VisRgn;
126 }
127
128 VOID FASTCALL
129 co_VIS_WindowLayoutChanged(
130 PWND Wnd,
131 HRGN NewlyExposed)
132 {
133 HRGN Temp;
134 PWND Parent;
135 USER_REFERENCE_ENTRY Ref;
136
137 ASSERT_REFS_CO(Wnd);
138
139 Parent = Wnd->spwndParent;
140 if(Parent)
141 {
142 Temp = IntSysCreateRectRgn(0, 0, 0, 0);
143
144 NtGdiCombineRgn(Temp, NewlyExposed, NULL, RGN_COPY);
145 NtGdiOffsetRgn(Temp,
146 Wnd->rcWindow.left - Parent->rcClient.left,
147 Wnd->rcWindow.top - Parent->rcClient.top);
148
149 UserRefObjectCo(Parent, &Ref);
150 co_UserRedrawWindow(Parent, NULL, Temp,
151 RDW_FRAME | RDW_ERASE | RDW_INVALIDATE |
152 RDW_ALLCHILDREN);
153 UserDerefObjectCo(Parent);
154
155 GreDeleteObject(Temp);
156 }
157 }
158
159 /* EOF */