- Less STDCALL, more WINAPI/NTAPI/APIENTRY
[reactos.git] / reactos / subsystems / win32 / win32k / eng / engwindow.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: GDI WNDOBJ Functions
24 * FILE: subsys/win32k/eng/window.c
25 * PROGRAMER: Gregor Anich
26 * REVISION HISTORY:
27 * 16/11/2004: Created
28 */
29
30 /* TODO: Check how the WNDOBJ implementation should behave with a driver on windows. */
31
32 #include <w32k.h>
33
34 #define NDEBUG
35 #include <debug.h>
36
37 /*
38 * Calls the WNDOBJCHANGEPROC of the given WNDOBJ
39 */
40 VOID
41 FASTCALL
42 IntEngWndCallChangeProc(
43 IN WNDOBJ *pwo,
44 IN FLONG flChanged)
45 {
46 WNDGDI *WndObjInt = ObjToGDI(pwo, WND);
47
48 if (WndObjInt->ChangeProc == NULL)
49 {
50 return;
51 }
52
53 /* check flags of the WNDOBJ */
54 flChanged &= WndObjInt->Flags;
55 if (flChanged == 0)
56 {
57 return;
58 }
59
60 /* Call the WNDOBJCHANGEPROC */
61 if (flChanged == WOC_CHANGED)
62 {
63 pwo = NULL;
64 }
65
66 DPRINT("Calling WNDOBJCHANGEPROC (0x%x), Changed = 0x%x\n",
67 WndObjInt->ChangeProc, flChanged);
68 WndObjInt->ChangeProc(pwo, flChanged);
69 }
70
71 /*
72 * Fills the CLIPOBJ and client rect of the WNDOBJ with the data from the given WINDOW_OBJECT
73 */
74 BOOLEAN
75 FASTCALL
76 IntEngWndUpdateClipObj(
77 WNDGDI *WndObjInt,
78 PWINDOW_OBJECT Window)
79 {
80 HRGN hVisRgn;
81 PROSRGNDATA visRgn;
82 CLIPOBJ *ClipObj = NULL;
83 CLIPOBJ *OldClipObj;
84
85 hVisRgn = VIS_ComputeVisibleRegion(Window, TRUE, TRUE, TRUE);
86 if (hVisRgn != NULL)
87 {
88 NtGdiOffsetRgn(hVisRgn, Window->Wnd->ClientRect.left, Window->Wnd->ClientRect.top);
89 visRgn = REGION_LockRgn(hVisRgn);
90 if (visRgn != NULL)
91 {
92 if (visRgn->rdh.nCount > 0)
93 {
94 ClipObj = IntEngCreateClipRegion(visRgn->rdh.nCount, (PRECTL)visRgn->Buffer,
95 (PRECTL)&visRgn->rdh.rcBound);
96 DPRINT("Created visible region with %d rects\n", visRgn->rdh.nCount);
97 DPRINT(" BoundingRect: %d, %d %d, %d\n",
98 visRgn->rdh.rcBound.left, visRgn->rdh.rcBound.top,
99 visRgn->rdh.rcBound.right, visRgn->rdh.rcBound.bottom);
100 {
101 INT i;
102 for (i = 0; i < visRgn->rdh.nCount; i++)
103 {
104 DPRINT(" Rect #%d: %d,%d %d,%d\n", i+1,
105 visRgn->Buffer[i].left, visRgn->Buffer[i].top,
106 visRgn->Buffer[i].right, visRgn->Buffer[i].bottom);
107 }
108 }
109 }
110 REGION_UnlockRgn(visRgn);
111 }
112 else
113 {
114 DPRINT1("Warning: Couldn't lock visible region of window DC\n");
115 }
116 }
117 else
118 {
119 DPRINT1("Warning: VIS_ComputeVisibleRegion failed!\n");
120 }
121
122 if (ClipObj == NULL)
123 {
124 /* Fall back to client rect */
125 ClipObj = IntEngCreateClipRegion(1, (PRECTL)&Window->Wnd->ClientRect,
126 (PRECTL)&Window->Wnd->ClientRect);
127 }
128
129 if (ClipObj == NULL)
130 {
131 DPRINT1("Warning: IntEngCreateClipRegion() failed!\n");
132 return FALSE;
133 }
134
135 RtlCopyMemory(&WndObjInt->WndObj.coClient, ClipObj, sizeof (CLIPOBJ));
136 RtlCopyMemory(&WndObjInt->WndObj.rclClient, &Window->Wnd->ClientRect, sizeof (RECT));
137 OldClipObj = InterlockedExchangePointer(&WndObjInt->ClientClipObj, ClipObj);
138 if (OldClipObj != NULL)
139 IntEngDeleteClipRegion(OldClipObj);
140
141 return TRUE;
142 }
143
144 /*
145 * Updates all WNDOBJs of the given WINDOW_OBJECT and calls the change-procs.
146 */
147 VOID
148 FASTCALL
149 IntEngWindowChanged(
150 PWINDOW_OBJECT Window,
151 FLONG flChanged)
152 {
153 PLIST_ENTRY CurrentEntry;
154 WNDGDI *Current;
155
156 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL);
157
158 CurrentEntry = Window->WndObjListHead.Flink;
159 while (CurrentEntry != &Window->WndObjListHead)
160 {
161 Current = CONTAINING_RECORD(CurrentEntry, WNDGDI, ListEntry);
162
163 if (Current->WndObj.pvConsumer != NULL)
164 {
165 /* Update the WNDOBJ */
166 switch (flChanged)
167 {
168 case WOC_RGN_CLIENT:
169 /* Update the clipobj and client rect of the WNDOBJ */
170 IntEngWndUpdateClipObj(Current, Window);
171 break;
172
173 case WOC_DELETE:
174 /* FIXME: Should the WNDOBJs be deleted by win32k or by the driver? */
175 break;
176 }
177
178 /* Call the change proc */
179 IntEngWndCallChangeProc(&Current->WndObj, flChanged);
180
181 /* HACK: Send WOC_CHANGED after WOC_RGN_CLIENT */
182 if (flChanged == WOC_RGN_CLIENT)
183 {
184 IntEngWndCallChangeProc(&Current->WndObj, WOC_CHANGED);
185 }
186
187 CurrentEntry = CurrentEntry->Flink;
188 }
189 }
190
191 }
192
193 /*
194 * @implemented
195 */
196 WNDOBJ*
197 APIENTRY
198 EngCreateWnd(
199 SURFOBJ *pso,
200 HWND hWnd,
201 WNDOBJCHANGEPROC pfn,
202 FLONG fl,
203 int iPixelFormat)
204 {
205 WNDGDI *WndObjInt = NULL;
206 WNDOBJ *WndObjUser = NULL;
207 PWINDOW_OBJECT Window;
208 BOOL calledFromUser;
209 DECLARE_RETURN(WNDOBJ*);
210
211 DPRINT("EngCreateWnd: pso = 0x%x, hwnd = 0x%x, pfn = 0x%x, fl = 0x%x, pixfmt = %d\n",
212 pso, hWnd, pfn, fl, iPixelFormat);
213
214 calledFromUser = UserIsEntered();
215 if (!calledFromUser){
216 UserEnterShared();
217 }
218
219 /* Get window object */
220 Window = UserGetWindowObject(hWnd);
221 if (Window == NULL)
222 {
223 RETURN( NULL);
224 }
225
226 /* Create WNDOBJ */
227 WndObjInt = EngAllocMem(0, sizeof (WNDGDI), TAG_WNDOBJ);
228 if (WndObjInt == NULL)
229 {
230 DPRINT1("Failed to allocate memory for a WND structure!\n");
231 RETURN( NULL);
232 }
233
234 /* Fill the clipobj */
235 WndObjInt->ClientClipObj = NULL;
236 if (!IntEngWndUpdateClipObj(WndObjInt, Window))
237 {
238 EngFreeMem(WndObjInt);
239 RETURN( NULL);
240 }
241
242 /* Fill user object */
243 WndObjUser = GDIToObj(WndObjInt, WND);
244 WndObjUser->psoOwner = pso;
245 WndObjUser->pvConsumer = NULL;
246
247 /* Fill internal object */
248 WndObjInt->Hwnd = hWnd;
249 WndObjInt->ChangeProc = pfn;
250 WndObjInt->Flags = fl;
251 WndObjInt->PixelFormat = iPixelFormat;
252
253 /* associate object with window */
254 InsertTailList(&Window->WndObjListHead, &WndObjInt->ListEntry);
255
256 DPRINT("EngCreateWnd: SUCCESS!\n");
257
258 RETURN( WndObjUser);
259
260 CLEANUP:
261
262 if (!calledFromUser){
263 UserLeave();
264 }
265
266 END_CLEANUP;
267 }
268
269
270 /*
271 * @implemented
272 */
273 VOID
274 APIENTRY
275 EngDeleteWnd(
276 IN WNDOBJ *pwo)
277 {
278 WNDGDI *WndObjInt = ObjToGDI(pwo, WND);
279 PWINDOW_OBJECT Window;
280 BOOL calledFromUser;
281
282 DPRINT("EngDeleteWnd: pwo = 0x%x\n", pwo);
283
284 calledFromUser = UserIsEntered();
285 if (!calledFromUser){
286 UserEnterExclusive();
287 }
288
289 /* Get window object */
290 Window = UserGetWindowObject(WndObjInt->Hwnd);
291 if (Window == NULL)
292 {
293 DPRINT1("Warning: Couldnt get window object for WndObjInt->Hwnd!!!\n");
294 RemoveEntryList(&WndObjInt->ListEntry);
295 }
296 else
297 {
298 /* Remove object from window */
299 RemoveEntryList(&WndObjInt->ListEntry);
300 }
301
302 if (!calledFromUser){
303 UserLeave();
304 }
305
306 /* Free resources */
307 IntEngDeleteClipRegion(WndObjInt->ClientClipObj);
308 EngFreeMem(WndObjInt);
309 }
310
311
312 /*
313 * @implemented
314 */
315 BOOL
316 APIENTRY
317 WNDOBJ_bEnum(
318 IN WNDOBJ *pwo,
319 IN ULONG cj,
320 OUT ULONG *pul)
321 {
322 WNDGDI *WndObjInt = ObjToGDI(pwo, WND);
323 BOOL Ret;
324
325 DPRINT("WNDOBJ_bEnum: pwo = 0x%x, cj = %d, pul = 0x%x\n", pwo, cj, pul);
326 Ret = CLIPOBJ_bEnum(WndObjInt->ClientClipObj, cj, pul);
327
328 DPRINT("WNDOBJ_bEnum: Returning %s\n", Ret ? "True" : "False");
329 return Ret;
330 }
331
332
333 /*
334 * @implemented
335 */
336 ULONG
337 APIENTRY
338 WNDOBJ_cEnumStart(
339 IN WNDOBJ *pwo,
340 IN ULONG iType,
341 IN ULONG iDirection,
342 IN ULONG cLimit)
343 {
344 WNDGDI *WndObjInt = ObjToGDI(pwo, WND);
345 ULONG Ret;
346
347 DPRINT("WNDOBJ_cEnumStart: pwo = 0x%x, iType = %d, iDirection = %d, cLimit = %d\n",
348 pwo, iType, iDirection, cLimit);
349
350 /* FIXME: Should we enumerate all rectangles or not? */
351 Ret = CLIPOBJ_cEnumStart(WndObjInt->ClientClipObj, FALSE, iType, iDirection, cLimit);
352
353 DPRINT("WNDOBJ_cEnumStart: Returning 0x%x\n", Ret);
354 return Ret;
355 }
356
357
358 /*
359 * @implemented
360 */
361 VOID
362 APIENTRY
363 WNDOBJ_vSetConsumer(
364 IN WNDOBJ *pwo,
365 IN PVOID pvConsumer)
366 {
367 BOOL Hack;
368
369 DPRINT("WNDOBJ_vSetConsumer: pwo = 0x%x, pvConsumer = 0x%x\n", pwo, pvConsumer);
370
371 Hack = (pwo->pvConsumer == NULL);
372 pwo->pvConsumer = pvConsumer;
373
374 /* HACKHACKHACK
375 *
376 * MSDN says that the WNDOBJCHANGEPROC will be called with the most recent state
377 * when a WNDOBJ is created - we do it here because most drivers will need pvConsumer
378 * in the callback to identify the WNDOBJ I think.
379 *
380 * - blight
381 */
382 if (Hack)
383 {
384 IntEngWndCallChangeProc(pwo, WOC_RGN_CLIENT);
385 IntEngWndCallChangeProc(pwo, WOC_CHANGED);
386 IntEngWndCallChangeProc(pwo, WOC_DRAWN);
387 }
388 }
389
390 /* EOF */
391