522e76304b66018fbde2613987e2d17253322a0b
[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 (!VerifyWnd(CurrentWindow))
49 {
50 ERR("ATM the Current Window or Parent is dead! %p\n",CurrentWindow);
51 if (VisRgn) GreDeleteObject(VisRgn);
52 return NULL;
53 }
54
55 if (!(CurrentWindow->style & WS_VISIBLE))
56 {
57 if (VisRgn) GreDeleteObject(VisRgn);
58 return NULL;
59 }
60
61 ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWindow->rcClient);
62 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
63 GreDeleteObject(ClipRgn);
64
65 if ((PreviousWindow->style & WS_CLIPSIBLINGS) ||
66 (PreviousWindow == Wnd && ClipSiblings))
67 {
68 CurrentSibling = CurrentWindow->spwndChild;
69 while ( CurrentSibling != NULL &&
70 CurrentSibling != PreviousWindow )
71 {
72 if ((CurrentSibling->style & WS_VISIBLE) &&
73 !(CurrentSibling->ExStyle & WS_EX_TRANSPARENT))
74 {
75 ClipRgn = IntSysCreateRectRgnIndirect(&CurrentSibling->rcWindow);
76 /* Combine it with the window region if available */
77 if (CurrentSibling->hrgnClip && !(CurrentSibling->style & WS_MINIMIZE))
78 {
79 NtGdiOffsetRgn(ClipRgn, -CurrentSibling->rcWindow.left, -CurrentSibling->rcWindow.top);
80 NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentSibling->hrgnClip, RGN_AND);
81 NtGdiOffsetRgn(ClipRgn, CurrentSibling->rcWindow.left, CurrentSibling->rcWindow.top);
82 }
83 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
84 GreDeleteObject(ClipRgn);
85 }
86 CurrentSibling = CurrentSibling->spwndNext;
87 }
88 }
89
90 PreviousWindow = CurrentWindow;
91 CurrentWindow = CurrentWindow->spwndParent;
92 }
93
94 if (ClipChildren)
95 {
96 CurrentWindow = Wnd->spwndChild;
97 while (CurrentWindow)
98 {
99 if ((CurrentWindow->style & WS_VISIBLE) &&
100 !(CurrentWindow->ExStyle & WS_EX_TRANSPARENT))
101 {
102 ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWindow->rcWindow);
103 /* Combine it with the window region if available */
104 if (CurrentWindow->hrgnClip && !(CurrentWindow->style & WS_MINIMIZE))
105 {
106 NtGdiOffsetRgn(ClipRgn, -CurrentWindow->rcWindow.left, -CurrentWindow->rcWindow.top);
107 NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentWindow->hrgnClip, RGN_AND);
108 NtGdiOffsetRgn(ClipRgn, CurrentWindow->rcWindow.left, CurrentWindow->rcWindow.top);
109 }
110 NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
111 GreDeleteObject(ClipRgn);
112 }
113 CurrentWindow = CurrentWindow->spwndNext;
114 }
115 }
116
117 if (Wnd->hrgnClip && !(Wnd->style & WS_MINIMIZE))
118 {
119 NtGdiOffsetRgn(VisRgn, -Wnd->rcWindow.left, -Wnd->rcWindow.top);
120 NtGdiCombineRgn(VisRgn, VisRgn, Wnd->hrgnClip, RGN_AND);
121 NtGdiOffsetRgn(VisRgn, Wnd->rcWindow.left, Wnd->rcWindow.top);
122 }
123
124 return VisRgn;
125 }
126
127 VOID FASTCALL
128 co_VIS_WindowLayoutChanged(
129 PWND Wnd,
130 HRGN NewlyExposed)
131 {
132 HRGN Temp;
133 PWND Parent;
134 USER_REFERENCE_ENTRY Ref;
135
136 ASSERT_REFS_CO(Wnd);
137
138 Parent = Wnd->spwndParent;
139 if(Parent)
140 {
141 Temp = IntSysCreateRectRgn(0, 0, 0, 0);
142
143 NtGdiCombineRgn(Temp, NewlyExposed, NULL, RGN_COPY);
144 NtGdiOffsetRgn(Temp,
145 Wnd->rcWindow.left - Parent->rcClient.left,
146 Wnd->rcWindow.top - Parent->rcClient.top);
147
148 UserRefObjectCo(Parent, &Ref);
149 co_UserRedrawWindow(Parent, NULL, Temp,
150 RDW_FRAME | RDW_ERASE | RDW_INVALIDATE |
151 RDW_ALLCHILDREN);
152 UserDerefObjectCo(Parent);
153
154 GreDeleteObject(Temp);
155 }
156 }
157
158 /* EOF */