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
9 /* TODO: Check how the WNDOBJ implementation should behave with a driver on windows.
20 * Calls the WNDOBJCHANGEPROC of the given WNDOBJ
24 IntEngWndCallChangeProc(
28 WNDGDI
*WndObjInt
= ObjToGDI(pwo
, WND
);
30 if (WndObjInt
->ChangeProc
== NULL
)
35 /* check flags of the WNDOBJ */
36 flChanged
&= WndObjInt
->Flags
;
42 /* Call the WNDOBJCHANGEPROC */
43 if (flChanged
== WOC_CHANGED
)
48 DPRINT("Calling WNDOBJCHANGEPROC (0x%x), Changed = 0x%x\n",
49 WndObjInt
->ChangeProc
, flChanged
);
50 WndObjInt
->ChangeProc(pwo
, flChanged
);
54 * Fills the CLIPOBJ and client rect of the WNDOBJ with the data from the given WND
58 IntEngWndUpdateClipObj(
64 CLIPOBJ
*ClipObj
= NULL
;
67 DPRINT("IntEngWndUpdateClipObj\n");
69 hVisRgn
= VIS_ComputeVisibleRegion(Window
, TRUE
, TRUE
, TRUE
);
72 NtGdiOffsetRgn(hVisRgn
, Window
->rcClient
.left
, Window
->rcClient
.top
);
73 visRgn
= RGNOBJAPI_Lock(hVisRgn
, NULL
);
76 if (visRgn
->rdh
.nCount
> 0)
78 ClipObj
= IntEngCreateClipRegion(visRgn
->rdh
.nCount
, visRgn
->Buffer
,
79 &visRgn
->rdh
.rcBound
);
80 DPRINT("Created visible region with %d rects\n", visRgn
->rdh
.nCount
);
81 DPRINT(" BoundingRect: %d, %d %d, %d\n",
82 visRgn
->rdh
.rcBound
.left
, visRgn
->rdh
.rcBound
.top
,
83 visRgn
->rdh
.rcBound
.right
, visRgn
->rdh
.rcBound
.bottom
);
86 for (i
= 0; i
< visRgn
->rdh
.nCount
; i
++)
88 DPRINT(" Rect #%d: %d,%d %d,%d\n", i
+1,
89 visRgn
->Buffer
[i
].left
, visRgn
->Buffer
[i
].top
,
90 visRgn
->Buffer
[i
].right
, visRgn
->Buffer
[i
].bottom
);
94 RGNOBJAPI_Unlock(visRgn
);
98 DPRINT1("Warning: Couldn't lock visible region of window DC\n");
100 GreDeleteObject(hVisRgn
);
104 DPRINT1("Warning: VIS_ComputeVisibleRegion failed!\n");
109 /* Fall back to client rect */
110 ClipObj
= IntEngCreateClipRegion(1, &Window
->rcClient
,
116 DPRINT1("Warning: IntEngCreateClipRegion() failed!\n");
120 RtlCopyMemory(&WndObjInt
->WndObj
.coClient
, ClipObj
, sizeof (CLIPOBJ
));
121 RtlCopyMemory(&WndObjInt
->WndObj
.rclClient
, &Window
->rcClient
, sizeof (RECT
));
122 OldClipObj
= InterlockedExchangePointer((PVOID
*)&WndObjInt
->ClientClipObj
, ClipObj
);
123 if (OldClipObj
!= NULL
)
124 IntEngDeleteClipRegion(OldClipObj
);
130 * Updates all WNDOBJs of the given WND and calls the change-procs.
142 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL
);
144 hWnd
= Window
->head
.h
;
145 pprop
= IntGetProp(Window
, AtomWndObj
);
150 Current
= (WNDGDI
*)pprop
->Data
;
153 Current
->Hwnd
== hWnd
&&
154 Current
->WndObj
.pvConsumer
!= NULL
)
156 /* Update the WNDOBJ */
160 /* Update the clipobj and client rect of the WNDOBJ */
161 IntEngWndUpdateClipObj(Current
, Window
);
165 /* FIXME: Should the WNDOBJs be deleted by win32k or by the driver? */
169 /* Call the change proc */
170 IntEngWndCallChangeProc(&Current
->WndObj
, flChanged
);
172 /* HACK: Send WOC_CHANGED after WOC_RGN_CLIENT */
173 if (flChanged
== WOC_RGN_CLIENT
)
175 IntEngWndCallChangeProc(&Current
->WndObj
, WOC_CHANGED
);
188 WNDOBJCHANGEPROC pfn
,
192 WNDGDI
*WndObjInt
= NULL
;
193 WNDOBJ
*WndObjUser
= NULL
;
196 DECLARE_RETURN(WNDOBJ
*);
198 DPRINT("EngCreateWnd: pso = 0x%x, hwnd = 0x%x, pfn = 0x%x, fl = 0x%x, pixfmt = %d\n",
199 pso
, hWnd
, pfn
, fl
, iPixelFormat
);
201 calledFromUser
= UserIsEntered();
202 if (!calledFromUser
){
206 /* Get window object */
207 Window
= UserGetWindowObject(hWnd
);
214 WndObjInt
= EngAllocMem(0, sizeof (WNDGDI
), GDITAG_WNDOBJ
);
215 if (WndObjInt
== NULL
)
217 DPRINT1("Failed to allocate memory for a WND structure!\n");
221 /* Fill the clipobj */
222 WndObjInt
->ClientClipObj
= NULL
;
223 if (!IntEngWndUpdateClipObj(WndObjInt
, Window
))
225 EngFreeMem(WndObjInt
);
229 /* Fill user object */
230 WndObjUser
= GDIToObj(WndObjInt
, WND
);
231 WndObjUser
->psoOwner
= pso
;
232 WndObjUser
->pvConsumer
= NULL
;
234 /* Fill internal object */
235 WndObjInt
->Hwnd
= hWnd
;
236 WndObjInt
->ChangeProc
= pfn
;
237 WndObjInt
->Flags
= fl
;
238 WndObjInt
->PixelFormat
= iPixelFormat
;
240 /* associate object with window */
241 IntSetProp(Window
, AtomWndObj
, WndObjInt
);
244 DPRINT("EngCreateWnd: SUCCESS!\n");
250 if (!calledFromUser
){
266 WNDGDI
*WndObjInt
= ObjToGDI(pwo
, WND
);
270 DPRINT("EngDeleteWnd: pwo = 0x%x\n", pwo
);
272 calledFromUser
= UserIsEntered();
273 if (!calledFromUser
){
274 UserEnterExclusive();
277 /* Get window object */
278 Window
= UserGetWindowObject(WndObjInt
->Hwnd
);
281 DPRINT1("Warning: Couldnt get window object for WndObjInt->Hwnd!!!\n");
285 /* Remove object from window */
286 IntRemoveProp(Window
, AtomWndObj
);
290 if (!calledFromUser
){
295 IntEngDeleteClipRegion(WndObjInt
->ClientClipObj
);
296 EngFreeMem(WndObjInt
);
310 WNDGDI
*WndObjInt
= ObjToGDI(pwo
, WND
);
313 DPRINT("WNDOBJ_bEnum: pwo = 0x%x, cj = %d, pul = 0x%x\n", pwo
, cj
, pul
);
314 Ret
= CLIPOBJ_bEnum(WndObjInt
->ClientClipObj
, cj
, pul
);
316 DPRINT("WNDOBJ_bEnum: Returning %s\n", Ret
? "True" : "False");
332 WNDGDI
*WndObjInt
= ObjToGDI(pwo
, WND
);
335 DPRINT("WNDOBJ_cEnumStart: pwo = 0x%x, iType = %d, iDirection = %d, cLimit = %d\n",
336 pwo
, iType
, iDirection
, cLimit
);
338 /* FIXME: Should we enumerate all rectangles or not? */
339 Ret
= CLIPOBJ_cEnumStart(WndObjInt
->ClientClipObj
, FALSE
, iType
, iDirection
, cLimit
);
341 DPRINT("WNDOBJ_cEnumStart: Returning 0x%x\n", Ret
);
357 DPRINT("WNDOBJ_vSetConsumer: pwo = 0x%x, pvConsumer = 0x%x\n", pwo
, pvConsumer
);
359 Hack
= (pwo
->pvConsumer
== NULL
);
360 pwo
->pvConsumer
= pvConsumer
;
364 * MSDN says that the WNDOBJCHANGEPROC will be called with the most recent state
365 * when a WNDOBJ is created - we do it here because most drivers will need pvConsumer
366 * in the callback to identify the WNDOBJ I think.
372 IntEngWndCallChangeProc(pwo
, WOC_RGN_CLIENT
);
373 IntEngWndCallChangeProc(pwo
, WOC_CHANGED
);
374 IntEngWndCallChangeProc(pwo
, WOC_DRAWN
);