xref: /reactos/win32ss/gdi/eng/engwindow.c (revision 8a978a17)
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 
321