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