[WIN32K]
[reactos.git] / reactos / win32ss / gdi / eng / engwindow.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI WNDOBJ Functions
5 * FILE: subsystems/win32/win32k/eng/engwindow.c
6 * PROGRAMER: Gregor Anich
7 */
8
9 #include <win32k.h>
10 #include <debug.h>
11 DBG_DEFAULT_CHANNEL(EngWnd);
12
13 INT gcountPWO = 0;
14
15 /*
16 * Calls the WNDOBJCHANGEPROC of the given WNDOBJ
17 */
18 VOID
19 FASTCALL
20 IntEngWndCallChangeProc(
21 IN WNDOBJ *pwo,
22 IN FLONG flChanged)
23 {
24 XCLIPOBJ* Clip = CONTAINING_RECORD(pwo, XCLIPOBJ, WndObj);
25
26 if (Clip->ChangeProc == NULL)
27 {
28 return;
29 }
30
31 /* check flags of the WNDOBJ */
32 flChanged &= Clip->Flags;
33 if (flChanged == 0)
34 {
35 return;
36 }
37
38 /* Call the WNDOBJCHANGEPROC */
39 if (flChanged == WOC_CHANGED)
40 {
41 pwo = NULL;
42 }
43
44 TRACE("Calling WNDOBJCHANGEPROC (0x%p), Changed = 0x%x\n",
45 Clip->ChangeProc, flChanged);
46 Clip->ChangeProc(pwo, flChanged);
47 }
48
49 /*
50 * Fills the CLIPOBJ and client rect of the WNDOBJ with the data from the given WND
51 */
52 BOOLEAN
53 FASTCALL
54 IntEngWndUpdateClipObj(
55 XCLIPOBJ* Clip,
56 PWND Window)
57 {
58 HRGN hVisRgn;
59 PROSRGNDATA visRgn;
60
61 TRACE("IntEngWndUpdateClipObj\n");
62
63 hVisRgn = VIS_ComputeVisibleRegion(Window, TRUE, TRUE, TRUE);
64 if (hVisRgn != NULL)
65 {
66 visRgn = RGNOBJAPI_Lock(hVisRgn, NULL);
67 if (visRgn != NULL)
68 {
69 if (visRgn->rdh.nCount > 0)
70 {
71 IntEngUpdateClipRegion(Clip, visRgn->rdh.nCount, visRgn->Buffer, &visRgn->rdh.rcBound);
72 TRACE("Created visible region with %lu rects\n", visRgn->rdh.nCount);
73 TRACE(" BoundingRect: %d, %d %d, %d\n",
74 visRgn->rdh.rcBound.left, visRgn->rdh.rcBound.top,
75 visRgn->rdh.rcBound.right, visRgn->rdh.rcBound.bottom);
76 {
77 ULONG i;
78 for (i = 0; i < visRgn->rdh.nCount; i++)
79 {
80 TRACE(" Rect #%lu: %ld,%ld %ld,%ld\n", i+1,
81 visRgn->Buffer[i].left, visRgn->Buffer[i].top,
82 visRgn->Buffer[i].right, visRgn->Buffer[i].bottom);
83 }
84 }
85 }
86 RGNOBJAPI_Unlock(visRgn);
87 }
88 else
89 {
90 WARN("Couldn't lock visible region of window DC\n");
91 }
92 GreDeleteObject(hVisRgn);
93 }
94 else
95 {
96 /* Fall back to client rect */
97 IntEngUpdateClipRegion(Clip, 1, &Window->rcClient, &Window->rcClient);
98 }
99
100 /* Update the WNDOBJ */
101 Clip->WndObj.rclClient = Window->rcClient;
102
103 return TRUE;
104 }
105
106 /*
107 * Updates all WNDOBJs of the given WND and calls the change-procs.
108 */
109 VOID
110 FASTCALL
111 IntEngWindowChanged(
112 _In_ PWND Window,
113 _In_ FLONG flChanged)
114 {
115 PPROPERTY pprop;
116 XCLIPOBJ *Current;
117 HWND hWnd;
118
119 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL);
120
121 hWnd = Window->head.h;
122 pprop = IntGetProp(Window, AtomWndObj);
123 if (!pprop)
124 {
125 return;
126 }
127 Current = (XCLIPOBJ *)pprop->Data;
128 if ( gcountPWO &&
129 Current &&
130 Current->Hwnd == hWnd &&
131 Current->WndObj.pvConsumer != NULL )
132 {
133 /* Update the WNDOBJ */
134 switch (flChanged)
135 {
136 case WOC_RGN_CLIENT:
137 /* Update the clipobj and client rect of the WNDOBJ */
138 IntEngWndUpdateClipObj(Current, Window);
139 break;
140
141 case WOC_DELETE:
142 /* FIXME: Should the WNDOBJs be deleted by win32k or by the driver? */
143 break;
144 }
145
146 /* Call the change proc */
147 IntEngWndCallChangeProc(&Current->WndObj, flChanged);
148
149 /* HACK: Send WOC_CHANGED after WOC_RGN_CLIENT */
150 if (flChanged == WOC_RGN_CLIENT)
151 {
152 IntEngWndCallChangeProc(&Current->WndObj, WOC_CHANGED);
153 }
154 }
155 }
156
157 /*
158 * @implemented
159 */
160 WNDOBJ*
161 APIENTRY
162 EngCreateWnd(
163 SURFOBJ *pso,
164 HWND hWnd,
165 WNDOBJCHANGEPROC pfn,
166 FLONG fl,
167 int iPixelFormat)
168 {
169 XCLIPOBJ *Clip = NULL;
170 WNDOBJ *WndObjUser = NULL;
171 PWND Window;
172 BOOL calledFromUser;
173 DECLARE_RETURN(WNDOBJ*);
174
175 TRACE("EngCreateWnd: pso = 0x%p, hwnd = 0x%p, pfn = 0x%p, fl = 0x%lx, pixfmt = %d\n",
176 pso, hWnd, pfn, fl, iPixelFormat);
177
178 calledFromUser = UserIsEntered();
179 if (!calledFromUser) {
180 UserEnterShared();
181 }
182
183 /* Get window object */
184 Window = UserGetWindowObject(hWnd);
185 if (Window == NULL)
186 {
187 RETURN( NULL);
188 }
189
190 /* Create WNDOBJ */
191 Clip = EngAllocMem(FL_ZERO_MEMORY, sizeof (XCLIPOBJ), GDITAG_WNDOBJ);
192 if (Clip == NULL)
193 {
194 ERR("Failed to allocate memory for a WND structure!\n");
195 RETURN( NULL);
196 }
197 IntEngInitClipObj(Clip);
198
199 /* Fill the clipobj */
200 if (!IntEngWndUpdateClipObj(Clip, Window))
201 {
202 EngFreeMem(Clip);
203 RETURN( NULL);
204 }
205
206 /* Fill user object */
207 WndObjUser = &Clip->WndObj;
208 WndObjUser->psoOwner = pso;
209 WndObjUser->pvConsumer = NULL;
210
211 /* Fill internal object */
212 Clip->Hwnd = hWnd;
213 Clip->ChangeProc = pfn;
214 Clip->Flags = fl;
215 Clip->PixelFormat = iPixelFormat;
216
217 /* associate object with window */
218 IntSetProp(Window, AtomWndObj, Clip);
219 ++gcountPWO;
220
221 TRACE("EngCreateWnd: SUCCESS!\n");
222
223 RETURN( WndObjUser);
224
225 CLEANUP:
226
227 if (!calledFromUser) {
228 UserLeave();
229 }
230
231 END_CLEANUP;
232 }
233
234
235 /*
236 * @implemented
237 */
238 VOID
239 APIENTRY
240 EngDeleteWnd(
241 IN WNDOBJ *pwo)
242 {
243 XCLIPOBJ* Clip = CONTAINING_RECORD(pwo, XCLIPOBJ, WndObj);
244 PWND Window;
245 BOOL calledFromUser;
246
247 TRACE("EngDeleteWnd: pwo = 0x%p\n", pwo);
248
249 calledFromUser = UserIsEntered();
250 if (!calledFromUser) {
251 UserEnterExclusive();
252 }
253
254 /* Get window object */
255 Window = UserGetWindowObject(Clip->Hwnd);
256 if (Window == NULL)
257 {
258 ERR("Couldnt get window object for WndObjInt->Hwnd!!!\n");
259 }
260 else
261 {
262 /* Remove object from window */
263 IntRemoveProp(Window, AtomWndObj);
264 --gcountPWO;
265 }
266
267 if (!calledFromUser) {
268 UserLeave();
269 }
270
271 /* Free resources */
272 IntEngFreeClipResources(Clip);
273 EngFreeMem(Clip);
274 }
275
276
277 /*
278 * @implemented
279 */
280 BOOL
281 APIENTRY
282 WNDOBJ_bEnum(
283 IN WNDOBJ *pwo,
284 IN ULONG cj,
285 OUT ULONG *pul)
286 {
287 /* Relay */
288 return CLIPOBJ_bEnum(&pwo->coClient, cj, pul);
289 }
290
291
292 /*
293 * @implemented
294 */
295 ULONG
296 APIENTRY
297 WNDOBJ_cEnumStart(
298 IN WNDOBJ *pwo,
299 IN ULONG iType,
300 IN ULONG iDirection,
301 IN ULONG cLimit)
302 {
303 /* Relay */
304 // FIXME: Should we enumerate all rectangles or not?
305 return CLIPOBJ_cEnumStart(&pwo->coClient, FALSE, iType, iDirection, cLimit);
306 }
307
308
309 /*
310 * @implemented
311 */
312 VOID
313 APIENTRY
314 WNDOBJ_vSetConsumer(
315 IN WNDOBJ *pwo,
316 IN PVOID pvConsumer)
317 {
318 BOOL Hack;
319
320 TRACE("WNDOBJ_vSetConsumer: pwo = 0x%p, pvConsumer = 0x%p\n", pwo, pvConsumer);
321
322 Hack = (pwo->pvConsumer == NULL);
323 pwo->pvConsumer = pvConsumer;
324
325 /* HACKHACKHACK
326 *
327 * MSDN says that the WNDOBJCHANGEPROC will be called with the most recent state
328 * when a WNDOBJ is created - we do it here because most drivers will need pvConsumer
329 * in the callback to identify the WNDOBJ I think.
330 *
331 * - blight
332 */
333 if (Hack)
334 {
335 FIXME("Is this hack really needed?\n");
336 IntEngWndCallChangeProc(pwo, WOC_RGN_CLIENT);
337 IntEngWndCallChangeProc(pwo, WOC_CHANGED);
338 IntEngWndCallChangeProc(pwo, WOC_DRAWN);
339 }
340 }
341
342 /* EOF */
343