c5b4d937814cd2716f527324b96a61e6b4c46e14
[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 WNDGDI *WndObjInt = ObjToGDI(pwo, WND);
25
26 if (WndObjInt->ChangeProc == NULL)
27 {
28 return;
29 }
30
31 /* check flags of the WNDOBJ */
32 flChanged &= WndObjInt->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 WndObjInt->ChangeProc, flChanged);
46 WndObjInt->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 WNDGDI *WndObjInt,
56 PWND Window)
57 {
58 HRGN hVisRgn;
59 PROSRGNDATA visRgn;
60 CLIPOBJ *ClipObj = NULL;
61 CLIPOBJ *OldClipObj;
62
63 TRACE("IntEngWndUpdateClipObj\n");
64
65 hVisRgn = VIS_ComputeVisibleRegion(Window, TRUE, TRUE, TRUE);
66 if (hVisRgn != NULL)
67 {
68 visRgn = RGNOBJAPI_Lock(hVisRgn, NULL);
69 if (visRgn != NULL)
70 {
71 if (visRgn->rdh.nCount > 0)
72 {
73 ClipObj = IntEngCreateClipRegion(visRgn->rdh.nCount, visRgn->Buffer,
74 &visRgn->rdh.rcBound);
75 TRACE("Created visible region with %lu rects\n", visRgn->rdh.nCount);
76 TRACE(" BoundingRect: %d, %d %d, %d\n",
77 visRgn->rdh.rcBound.left, visRgn->rdh.rcBound.top,
78 visRgn->rdh.rcBound.right, visRgn->rdh.rcBound.bottom);
79 {
80 ULONG i;
81 for (i = 0; i < visRgn->rdh.nCount; i++)
82 {
83 TRACE(" Rect #%lu: %ld,%ld %ld,%ld\n", i+1,
84 visRgn->Buffer[i].left, visRgn->Buffer[i].top,
85 visRgn->Buffer[i].right, visRgn->Buffer[i].bottom);
86 }
87 }
88 }
89 RGNOBJAPI_Unlock(visRgn);
90 }
91 else
92 {
93 WARN("Couldn't lock visible region of window DC\n");
94 }
95 GreDeleteObject(hVisRgn);
96 }
97 else
98 {
99 WARN("VIS_ComputeVisibleRegion failed!\n");
100 }
101
102 if (ClipObj == NULL)
103 {
104 /* Fall back to client rect */
105 ClipObj = IntEngCreateClipRegion(1, &Window->rcClient,
106 &Window->rcClient);
107 }
108
109 if (ClipObj == NULL)
110 {
111 ERR("IntEngCreateClipRegion() failed!\n");
112 return FALSE;
113 }
114
115 RtlCopyMemory(&WndObjInt->WndObj.coClient, ClipObj, sizeof (CLIPOBJ));
116 RtlCopyMemory(&WndObjInt->WndObj.rclClient, &Window->rcClient, sizeof (RECT));
117 OldClipObj = InterlockedExchangePointer((PVOID*)&WndObjInt->ClientClipObj, ClipObj);
118 if (OldClipObj != NULL)
119 IntEngDeleteClipRegion(OldClipObj);
120
121 return TRUE;
122 }
123
124 /*
125 * Updates all WNDOBJs of the given WND and calls the change-procs.
126 */
127 VOID
128 FASTCALL
129 IntEngWindowChanged(
130 _In_ PWND Window,
131 _In_ FLONG flChanged)
132 {
133 PPROPERTY pprop;
134 WNDGDI *Current;
135 HWND hWnd;
136
137 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL);
138
139 hWnd = Window->head.h;
140 pprop = IntGetProp(Window, AtomWndObj);
141 if (!pprop)
142 {
143 return;
144 }
145 Current = (WNDGDI *)pprop->Data;
146 if ( gcountPWO &&
147 Current &&
148 Current->Hwnd == hWnd &&
149 Current->WndObj.pvConsumer != NULL )
150 {
151 /* Update the WNDOBJ */
152 switch (flChanged)
153 {
154 case WOC_RGN_CLIENT:
155 /* Update the clipobj and client rect of the WNDOBJ */
156 IntEngWndUpdateClipObj(Current, Window);
157 break;
158
159 case WOC_DELETE:
160 /* FIXME: Should the WNDOBJs be deleted by win32k or by the driver? */
161 break;
162 }
163
164 /* Call the change proc */
165 IntEngWndCallChangeProc(&Current->WndObj, flChanged);
166
167 /* HACK: Send WOC_CHANGED after WOC_RGN_CLIENT */
168 if (flChanged == WOC_RGN_CLIENT)
169 {
170 IntEngWndCallChangeProc(&Current->WndObj, WOC_CHANGED);
171 }
172 }
173 }
174
175 /*
176 * @implemented
177 */
178 WNDOBJ*
179 APIENTRY
180 EngCreateWnd(
181 SURFOBJ *pso,
182 HWND hWnd,
183 WNDOBJCHANGEPROC pfn,
184 FLONG fl,
185 int iPixelFormat)
186 {
187 WNDGDI *WndObjInt = NULL;
188 WNDOBJ *WndObjUser = NULL;
189 PWND Window;
190 BOOL calledFromUser;
191 DECLARE_RETURN(WNDOBJ*);
192
193 TRACE("EngCreateWnd: pso = 0x%p, hwnd = 0x%p, pfn = 0x%p, fl = 0x%lx, pixfmt = %d\n",
194 pso, hWnd, pfn, fl, iPixelFormat);
195
196 calledFromUser = UserIsEntered();
197 if (!calledFromUser) {
198 UserEnterShared();
199 }
200
201 /* Get window object */
202 Window = UserGetWindowObject(hWnd);
203 if (Window == NULL)
204 {
205 RETURN( NULL);
206 }
207
208 /* Create WNDOBJ */
209 WndObjInt = EngAllocMem(0, sizeof (WNDGDI), GDITAG_WNDOBJ);
210 if (WndObjInt == NULL)
211 {
212 ERR("Failed to allocate memory for a WND structure!\n");
213 RETURN( NULL);
214 }
215
216 /* Fill the clipobj */
217 WndObjInt->ClientClipObj = NULL;
218 if (!IntEngWndUpdateClipObj(WndObjInt, Window))
219 {
220 EngFreeMem(WndObjInt);
221 RETURN( NULL);
222 }
223
224 /* Fill user object */
225 WndObjUser = GDIToObj(WndObjInt, WND);
226 WndObjUser->psoOwner = pso;
227 WndObjUser->pvConsumer = NULL;
228
229 /* Fill internal object */
230 WndObjInt->Hwnd = hWnd;
231 WndObjInt->ChangeProc = pfn;
232 WndObjInt->Flags = fl;
233 WndObjInt->PixelFormat = iPixelFormat;
234
235 /* associate object with window */
236 IntSetProp(Window, AtomWndObj, WndObjInt);
237 ++gcountPWO;
238
239 TRACE("EngCreateWnd: SUCCESS!\n");
240
241 RETURN( WndObjUser);
242
243 CLEANUP:
244
245 if (!calledFromUser) {
246 UserLeave();
247 }
248
249 END_CLEANUP;
250 }
251
252
253 /*
254 * @implemented
255 */
256 VOID
257 APIENTRY
258 EngDeleteWnd(
259 IN WNDOBJ *pwo)
260 {
261 WNDGDI *WndObjInt = ObjToGDI(pwo, WND);
262 PWND Window;
263 BOOL calledFromUser;
264
265 TRACE("EngDeleteWnd: pwo = 0x%p\n", pwo);
266
267 calledFromUser = UserIsEntered();
268 if (!calledFromUser) {
269 UserEnterExclusive();
270 }
271
272 /* Get window object */
273 Window = UserGetWindowObject(WndObjInt->Hwnd);
274 if (Window == NULL)
275 {
276 ERR("Couldnt get window object for WndObjInt->Hwnd!!!\n");
277 }
278 else
279 {
280 /* Remove object from window */
281 IntRemoveProp(Window, AtomWndObj);
282 --gcountPWO;
283 }
284
285 if (!calledFromUser) {
286 UserLeave();
287 }
288
289 /* Free resources */
290 IntEngDeleteClipRegion(WndObjInt->ClientClipObj);
291 EngFreeMem(WndObjInt);
292 }
293
294
295 /*
296 * @implemented
297 */
298 BOOL
299 APIENTRY
300 WNDOBJ_bEnum(
301 IN WNDOBJ *pwo,
302 IN ULONG cj,
303 OUT ULONG *pul)
304 {
305 WNDGDI *WndObjInt = ObjToGDI(pwo, WND);
306 BOOL Ret;
307
308 TRACE("WNDOBJ_bEnum: pwo = 0x%p, cj = %lu, pul = 0x%p\n", pwo, cj, pul);
309 Ret = CLIPOBJ_bEnum(WndObjInt->ClientClipObj, cj, pul);
310
311 TRACE("WNDOBJ_bEnum: Returning %s\n", Ret ? "True" : "False");
312 return Ret;
313 }
314
315
316 /*
317 * @implemented
318 */
319 ULONG
320 APIENTRY
321 WNDOBJ_cEnumStart(
322 IN WNDOBJ *pwo,
323 IN ULONG iType,
324 IN ULONG iDirection,
325 IN ULONG cLimit)
326 {
327 WNDGDI *WndObjInt = ObjToGDI(pwo, WND);
328 ULONG Ret;
329
330 TRACE("WNDOBJ_cEnumStart: pwo = 0x%p, iType = %lu, iDirection = %lu, cLimit = %lu\n",
331 pwo, iType, iDirection, cLimit);
332
333 /* FIXME: Should we enumerate all rectangles or not? */
334 Ret = CLIPOBJ_cEnumStart(WndObjInt->ClientClipObj, FALSE, iType, iDirection, cLimit);
335
336 TRACE("WNDOBJ_cEnumStart: Returning 0x%lx\n", Ret);
337 return Ret;
338 }
339
340
341 /*
342 * @implemented
343 */
344 VOID
345 APIENTRY
346 WNDOBJ_vSetConsumer(
347 IN WNDOBJ *pwo,
348 IN PVOID pvConsumer)
349 {
350 BOOL Hack;
351
352 TRACE("WNDOBJ_vSetConsumer: pwo = 0x%p, pvConsumer = 0x%p\n", pwo, pvConsumer);
353
354 Hack = (pwo->pvConsumer == NULL);
355 pwo->pvConsumer = pvConsumer;
356
357 /* HACKHACKHACK
358 *
359 * MSDN says that the WNDOBJCHANGEPROC will be called with the most recent state
360 * when a WNDOBJ is created - we do it here because most drivers will need pvConsumer
361 * in the callback to identify the WNDOBJ I think.
362 *
363 * - blight
364 */
365 if (Hack)
366 {
367 FIXME("Is this hack really needed?\n");
368 IntEngWndCallChangeProc(pwo, WOC_RGN_CLIENT);
369 IntEngWndCallChangeProc(pwo, WOC_CHANGED);
370 IntEngWndCallChangeProc(pwo, WOC_DRAWN);
371 }
372 }
373
374 /* EOF */
375