[WIN32SS]
[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: 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_ EWNDOBJ *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((WNDOBJ *)Clip, 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 EWNDOBJ* 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((XCLIPOBJ*)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((XCLIPOBJ*)Clip, 1, &Window->rcClient, &Window->rcClient);
85 }
86
87 /* Update the WNDOBJ */
88 Clip->rclClient = Window->rcClient;
89 Clip->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 EWNDOBJ *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->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 EWNDOBJ *Clip = NULL;
153 WNDOBJ *WndObjUser = NULL;
154 PWND Window;
155
156 TRACE("EngCreateWnd: pso = 0x%p, hwnd = 0x%p, pfn = 0x%p, fl = 0x%lx, pixfmt = %d\n",
157 pso, hWnd, pfn, fl, iPixelFormat);
158
159 UserEnterExclusive();
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 /* Get window object */
167 Window = UserGetWindowObject(hWnd);
168 if (Window == NULL)
169 {
170 goto Exit;
171 }
172
173 /* Create WNDOBJ */
174 Clip = EngAllocMem(FL_ZERO_MEMORY, sizeof(EWNDOBJ), GDITAG_WNDOBJ);
175 if (Clip == NULL)
176 {
177 ERR("Failed to allocate memory for a WND structure!\n");
178 goto Exit;
179 }
180 IntEngInitClipObj((XCLIPOBJ*)Clip);
181
182 /* Fill the clipobj */
183 if (!IntEngWndUpdateClipObj(Clip, Window))
184 {
185 EngFreeMem(Clip);
186 goto Exit;
187 }
188
189 /* Fill user object */
190 WndObjUser = (WNDOBJ *)Clip;
191 WndObjUser->psoOwner = pso;
192 WndObjUser->pvConsumer = NULL;
193
194 /* Fill internal object */
195 Clip->Hwnd = hWnd;
196 Clip->ChangeProc = pfn;
197 /* Keep track of relevant flags */
198 Clip->Flags = fl & (WO_RGN_CLIENT_DELTA | WO_RGN_CLIENT | WO_RGN_SURFACE_DELTA | WO_RGN_SURFACE | WO_DRAW_NOTIFY);
199 if (fl & WO_SPRITE_NOTIFY)
200 Clip->Flags |= WOC_SPRITE_OVERLAP | WOC_SPRITE_NO_OVERLAP;
201 /* Those should always be sent */
202 Clip->Flags |= WOC_CHANGED | WOC_DELETE;
203 Clip->PixelFormat = iPixelFormat;
204
205 /* associate object with window */
206 UserSetProp(Window, AtomWndObj, Clip, TRUE);
207 ++gcountPWO;
208
209 TRACE("EngCreateWnd: SUCCESS: %p!\n", WndObjUser);
210
211 Exit:
212 UserLeave();
213 return WndObjUser;
214 }
215
216
217 /*
218 * @implemented
219 */
220 VOID
221 APIENTRY
222 EngDeleteWnd(
223 IN WNDOBJ *pwo)
224 {
225 EWNDOBJ* Clip = (EWNDOBJ *)pwo;//CONTAINING_RECORD(pwo, XCLIPOBJ, WndObj);
226 PWND Window;
227
228 TRACE("EngDeleteWnd: pwo = 0x%p\n", pwo);
229
230 UserEnterExclusive();
231
232 /* Get window object */
233 Window = UserGetWindowObject(Clip->Hwnd);
234 if (Window == NULL)
235 {
236 ERR("Couldnt get window object for WndObjInt->Hwnd!!!\n");
237 }
238 else
239 {
240 /* Remove object from window */
241 UserRemoveProp(Window, AtomWndObj, TRUE);
242 }
243 --gcountPWO;
244
245 UserLeave();
246
247 /* Free resources */
248 IntEngFreeClipResources((XCLIPOBJ*)Clip);
249 EngFreeMem(Clip);
250 }
251
252
253 /*
254 * @implemented
255 */
256 BOOL
257 APIENTRY
258 WNDOBJ_bEnum(
259 IN WNDOBJ *pwo,
260 IN ULONG cj,
261 OUT ULONG *pul)
262 {
263 /* Relay */
264 return CLIPOBJ_bEnum(&pwo->coClient, cj, pul);
265 }
266
267
268 /*
269 * @implemented
270 */
271 ULONG
272 APIENTRY
273 WNDOBJ_cEnumStart(
274 IN WNDOBJ *pwo,
275 IN ULONG iType,
276 IN ULONG iDirection,
277 IN ULONG cLimit)
278 {
279 /* Relay */
280 // FIXME: Should we enumerate all rectangles or not?
281 return CLIPOBJ_cEnumStart(&pwo->coClient, FALSE, iType, iDirection, cLimit);
282 }
283
284
285 /*
286 * @implemented
287 */
288 VOID
289 APIENTRY
290 WNDOBJ_vSetConsumer(
291 IN WNDOBJ *pwo,
292 IN PVOID pvConsumer)
293 {
294 EWNDOBJ* Clip = (EWNDOBJ *)pwo;//CONTAINING_RECORD(pwo, XCLIPOBJ, WndObj);
295 BOOL Hack;
296
297 TRACE("WNDOBJ_vSetConsumer: pwo = 0x%p, pvConsumer = 0x%p\n", pwo, pvConsumer);
298
299 Hack = (pwo->pvConsumer == NULL);
300 pwo->pvConsumer = pvConsumer;
301
302 /* HACKHACKHACK
303 *
304 * MSDN says that the WNDOBJCHANGEPROC will be called with the most recent state
305 * when a WNDOBJ is created - we do it here because most drivers will need pvConsumer
306 * in the callback to identify the WNDOBJ I think.
307 *
308 * - blight
309 */
310 if (Hack)
311 {
312 FIXME("Is this hack really needed?\n");
313 IntEngWndCallChangeProc(Clip, WOC_RGN_CLIENT);
314 IntEngWndCallChangeProc(Clip, WOC_CHANGED);
315 IntEngWndCallChangeProc(Clip, WOC_DRAWN);
316 }
317 }
318
319 /* EOF */
320