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