[SHELL-EXPERIMENTS]
[reactos.git] / 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 Clip->WndObj.coClient.iUniq++;
100
101 return TRUE;
102 }
103
104 /*
105 * Updates all WNDOBJs of the given WND and calls the change-procs.
106 */
107 VOID
108 FASTCALL
109 IntEngWindowChanged(
110 _In_ PWND Window,
111 _In_ FLONG flChanged)
112 {
113 XCLIPOBJ *Clip;
114
115 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL);
116
117 Clip = UserGetProp(Window, AtomWndObj);
118 if (!Clip)
119 {
120 return;
121 }
122
123 ASSERT(Clip->Hwnd == Window->head.h);
124 // if (Clip->WndObj.pvConsumer != NULL)
125 {
126 /* Update the WNDOBJ */
127 switch (flChanged)
128 {
129 case WOC_RGN_CLIENT:
130 /* Update the clipobj and client rect of the WNDOBJ */
131 IntEngWndUpdateClipObj(Clip, Window);
132 break;
133
134 case WOC_DELETE:
135 /* FIXME: Should the WNDOBJs be deleted by win32k or by the driver? */
136 break;
137 }
138
139 /* Call the change proc */
140 IntEngWndCallChangeProc(Clip, flChanged);
141
142 /* HACK: Send WOC_CHANGED after WOC_RGN_CLIENT */
143 if (flChanged == WOC_RGN_CLIENT)
144 {
145 IntEngWndCallChangeProc(Clip, WOC_CHANGED);
146 }
147 }
148 }
149
150 /*
151 * @implemented
152 */
153 WNDOBJ*
154 APIENTRY
155 EngCreateWnd(
156 SURFOBJ *pso,
157 HWND hWnd,
158 WNDOBJCHANGEPROC pfn,
159 FLONG fl,
160 int iPixelFormat)
161 {
162 XCLIPOBJ *Clip = NULL;
163 WNDOBJ *WndObjUser = NULL;
164 PWND Window;
165 BOOL calledFromUser;
166 DECLARE_RETURN(WNDOBJ*);
167
168 TRACE("EngCreateWnd: pso = 0x%p, hwnd = 0x%p, pfn = 0x%p, fl = 0x%lx, pixfmt = %d\n",
169 pso, hWnd, pfn, fl, iPixelFormat);
170
171 if (fl & (WO_RGN_WINDOW | WO_RGN_DESKTOP_COORD | WO_RGN_UPDATE_ALL))
172 {
173 FIXME("Unsupported flags: 0x%lx\n", fl & ~(WO_RGN_CLIENT_DELTA | WO_RGN_CLIENT | WO_RGN_SURFACE_DELTA | WO_RGN_SURFACE));
174 }
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 /* Keep track of relevant flags */
213 Clip->Flags = fl & (WO_RGN_CLIENT_DELTA | WO_RGN_CLIENT | WO_RGN_SURFACE_DELTA | WO_RGN_SURFACE | WO_DRAW_NOTIFY);
214 if (fl & WO_SPRITE_NOTIFY)
215 Clip->Flags |= WOC_SPRITE_OVERLAP | WOC_SPRITE_NO_OVERLAP;
216 /* Those should always be sent */
217 Clip->Flags |= WOC_CHANGED | WOC_DELETE;
218 Clip->PixelFormat = iPixelFormat;
219
220 /* associate object with window */
221 IntSetProp(Window, AtomWndObj, Clip);
222 ++gcountPWO;
223
224 TRACE("EngCreateWnd: SUCCESS: %p!\n", WndObjUser);
225
226 RETURN( WndObjUser);
227
228 CLEANUP:
229
230 if (!calledFromUser) {
231 UserLeave();
232 }
233
234 END_CLEANUP;
235 }
236
237
238 /*
239 * @implemented
240 */
241 VOID
242 APIENTRY
243 EngDeleteWnd(
244 IN WNDOBJ *pwo)
245 {
246 XCLIPOBJ* Clip = CONTAINING_RECORD(pwo, XCLIPOBJ, WndObj);
247 PWND Window;
248 BOOL calledFromUser;
249
250 TRACE("EngDeleteWnd: pwo = 0x%p\n", pwo);
251
252 calledFromUser = UserIsEntered();
253 if (!calledFromUser) {
254 UserEnterExclusive();
255 }
256
257 /* Get window object */
258 Window = UserGetWindowObject(Clip->Hwnd);
259 if (Window == NULL)
260 {
261 ERR("Couldnt get window object for WndObjInt->Hwnd!!!\n");
262 }
263 else
264 {
265 /* Remove object from window */
266 IntRemoveProp(Window, AtomWndObj);
267 }
268 --gcountPWO;
269
270 if (!calledFromUser) {
271 UserLeave();
272 }
273
274 /* Free resources */
275 IntEngFreeClipResources(Clip);
276 EngFreeMem(Clip);
277 }
278
279
280 /*
281 * @implemented
282 */
283 BOOL
284 APIENTRY
285 WNDOBJ_bEnum(
286 IN WNDOBJ *pwo,
287 IN ULONG cj,
288 OUT ULONG *pul)
289 {
290 /* Relay */
291 return CLIPOBJ_bEnum(&pwo->coClient, cj, pul);
292 }
293
294
295 /*
296 * @implemented
297 */
298 ULONG
299 APIENTRY
300 WNDOBJ_cEnumStart(
301 IN WNDOBJ *pwo,
302 IN ULONG iType,
303 IN ULONG iDirection,
304 IN ULONG cLimit)
305 {
306 /* Relay */
307 // FIXME: Should we enumerate all rectangles or not?
308 return CLIPOBJ_cEnumStart(&pwo->coClient, FALSE, iType, iDirection, cLimit);
309 }
310
311
312 /*
313 * @implemented
314 */
315 VOID
316 APIENTRY
317 WNDOBJ_vSetConsumer(
318 IN WNDOBJ *pwo,
319 IN PVOID pvConsumer)
320 {
321 XCLIPOBJ* Clip = CONTAINING_RECORD(pwo, XCLIPOBJ, WndObj);
322 BOOL Hack;
323
324 TRACE("WNDOBJ_vSetConsumer: pwo = 0x%p, pvConsumer = 0x%p\n", pwo, pvConsumer);
325
326 Hack = (pwo->pvConsumer == NULL);
327 pwo->pvConsumer = pvConsumer;
328
329 /* HACKHACKHACK
330 *
331 * MSDN says that the WNDOBJCHANGEPROC will be called with the most recent state
332 * when a WNDOBJ is created - we do it here because most drivers will need pvConsumer
333 * in the callback to identify the WNDOBJ I think.
334 *
335 * - blight
336 */
337 if (Hack)
338 {
339 FIXME("Is this hack really needed?\n");
340 IntEngWndCallChangeProc(Clip, WOC_RGN_CLIENT);
341 IntEngWndCallChangeProc(Clip, WOC_CHANGED);
342 IntEngWndCallChangeProc(Clip, WOC_DRAWN);
343 }
344 }
345
346 /* EOF */
347