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