486ac4a56221b921837cde5dfbad657576e800d3
[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 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL);
115
116 Clip = UserGetProp(Window, AtomWndObj);
117 if (!Clip)
118 {
119 return;
120 }
121
122 ASSERT(Clip->Hwnd == Window->head.h);
123 if (Clip->WndObj.pvConsumer != NULL)
124 {
125 /* Update the WNDOBJ */
126 switch (flChanged)
127 {
128 case WOC_RGN_CLIENT:
129 /* Update the clipobj and client rect of the WNDOBJ */
130 IntEngWndUpdateClipObj(Clip, Window);
131 break;
132
133 case WOC_DELETE:
134 /* FIXME: Should the WNDOBJs be deleted by win32k or by the driver? */
135 break;
136 }
137
138 /* Call the change proc */
139 IntEngWndCallChangeProc(Clip, flChanged);
140
141 /* HACK: Send WOC_CHANGED after WOC_RGN_CLIENT */
142 if (flChanged == WOC_RGN_CLIENT)
143 {
144 IntEngWndCallChangeProc(Clip, WOC_CHANGED);
145 }
146 }
147 }
148
149 /*
150 * @implemented
151 */
152 WNDOBJ*
153 APIENTRY
154 EngCreateWnd(
155 SURFOBJ *pso,
156 HWND hWnd,
157 WNDOBJCHANGEPROC pfn,
158 FLONG fl,
159 int iPixelFormat)
160 {
161 XCLIPOBJ *Clip = NULL;
162 WNDOBJ *WndObjUser = NULL;
163 PWND Window;
164 BOOL calledFromUser;
165 DECLARE_RETURN(WNDOBJ*);
166
167 TRACE("EngCreateWnd: pso = 0x%p, hwnd = 0x%p, pfn = 0x%p, fl = 0x%lx, pixfmt = %d\n",
168 pso, hWnd, pfn, fl, iPixelFormat);
169
170 calledFromUser = UserIsEntered();
171 if (!calledFromUser) {
172 UserEnterShared();
173 }
174
175 /* Get window object */
176 Window = UserGetWindowObject(hWnd);
177 if (Window == NULL)
178 {
179 RETURN( NULL);
180 }
181
182 /* Create WNDOBJ */
183 Clip = EngAllocMem(FL_ZERO_MEMORY, sizeof (XCLIPOBJ), GDITAG_WNDOBJ);
184 if (Clip == NULL)
185 {
186 ERR("Failed to allocate memory for a WND structure!\n");
187 RETURN( NULL);
188 }
189 IntEngInitClipObj(Clip);
190
191 /* Fill the clipobj */
192 if (!IntEngWndUpdateClipObj(Clip, Window))
193 {
194 EngFreeMem(Clip);
195 RETURN( NULL);
196 }
197
198 /* Fill user object */
199 WndObjUser = &Clip->WndObj;
200 WndObjUser->psoOwner = pso;
201 WndObjUser->pvConsumer = NULL;
202
203 /* Fill internal object */
204 Clip->Hwnd = hWnd;
205 Clip->ChangeProc = pfn;
206 Clip->Flags = fl;
207 Clip->PixelFormat = iPixelFormat;
208
209 /* associate object with window */
210 IntSetProp(Window, AtomWndObj, Clip);
211 ++gcountPWO;
212
213 TRACE("EngCreateWnd: SUCCESS: %p!\n", WndObjUser);
214
215 RETURN( WndObjUser);
216
217 CLEANUP:
218
219 if (!calledFromUser) {
220 UserLeave();
221 }
222
223 END_CLEANUP;
224 }
225
226
227 /*
228 * @implemented
229 */
230 VOID
231 APIENTRY
232 EngDeleteWnd(
233 IN WNDOBJ *pwo)
234 {
235 XCLIPOBJ* Clip = CONTAINING_RECORD(pwo, XCLIPOBJ, WndObj);
236 PWND Window;
237 BOOL calledFromUser;
238
239 TRACE("EngDeleteWnd: pwo = 0x%p\n", pwo);
240
241 calledFromUser = UserIsEntered();
242 if (!calledFromUser) {
243 UserEnterExclusive();
244 }
245
246 /* Get window object */
247 Window = UserGetWindowObject(Clip->Hwnd);
248 if (Window == NULL)
249 {
250 ERR("Couldnt get window object for WndObjInt->Hwnd!!!\n");
251 }
252 else
253 {
254 /* Remove object from window */
255 IntRemoveProp(Window, AtomWndObj);
256 --gcountPWO;
257 }
258
259 if (!calledFromUser) {
260 UserLeave();
261 }
262
263 /* Free resources */
264 IntEngFreeClipResources(Clip);
265 EngFreeMem(Clip);
266 }
267
268
269 /*
270 * @implemented
271 */
272 BOOL
273 APIENTRY
274 WNDOBJ_bEnum(
275 IN WNDOBJ *pwo,
276 IN ULONG cj,
277 OUT ULONG *pul)
278 {
279 /* Relay */
280 return CLIPOBJ_bEnum(&pwo->coClient, cj, pul);
281 }
282
283
284 /*
285 * @implemented
286 */
287 ULONG
288 APIENTRY
289 WNDOBJ_cEnumStart(
290 IN WNDOBJ *pwo,
291 IN ULONG iType,
292 IN ULONG iDirection,
293 IN ULONG cLimit)
294 {
295 /* Relay */
296 // FIXME: Should we enumerate all rectangles or not?
297 return CLIPOBJ_cEnumStart(&pwo->coClient, FALSE, iType, iDirection, cLimit);
298 }
299
300
301 /*
302 * @implemented
303 */
304 VOID
305 APIENTRY
306 WNDOBJ_vSetConsumer(
307 IN WNDOBJ *pwo,
308 IN PVOID pvConsumer)
309 {
310 XCLIPOBJ* Clip = CONTAINING_RECORD(pwo, XCLIPOBJ, WndObj);
311 BOOL Hack;
312
313 TRACE("WNDOBJ_vSetConsumer: pwo = 0x%p, pvConsumer = 0x%p\n", pwo, pvConsumer);
314
315 Hack = (pwo->pvConsumer == NULL);
316 pwo->pvConsumer = pvConsumer;
317
318 /* HACKHACKHACK
319 *
320 * MSDN says that the WNDOBJCHANGEPROC will be called with the most recent state
321 * when a WNDOBJ is created - we do it here because most drivers will need pvConsumer
322 * in the callback to identify the WNDOBJ I think.
323 *
324 * - blight
325 */
326 if (Hack)
327 {
328 FIXME("Is this hack really needed?\n");
329 IntEngWndCallChangeProc(Clip, WOC_RGN_CLIENT);
330 IntEngWndCallChangeProc(Clip, WOC_CHANGED);
331 IntEngWndCallChangeProc(Clip, WOC_DRAWN);
332 }
333 }
334
335 /* EOF */
336