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