2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 ReactOS Team
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.
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.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * PURPOSE: GDI WNDOBJ Functions
23 * FILE: subsystems/win32/win32k/eng/engwindow.c
24 * PROGRAMER: Gregor Anich
29 /* TODO: Check how the WNDOBJ implementation should behave with a driver on windows.
40 * Calls the WNDOBJCHANGEPROC of the given WNDOBJ
44 IntEngWndCallChangeProc(
48 WNDGDI
*WndObjInt
= ObjToGDI(pwo
, WND
);
50 if (WndObjInt
->ChangeProc
== NULL
)
55 /* check flags of the WNDOBJ */
56 flChanged
&= WndObjInt
->Flags
;
62 /* Call the WNDOBJCHANGEPROC */
63 if (flChanged
== WOC_CHANGED
)
68 DPRINT("Calling WNDOBJCHANGEPROC (0x%x), Changed = 0x%x\n",
69 WndObjInt
->ChangeProc
, flChanged
);
70 WndObjInt
->ChangeProc(pwo
, flChanged
);
74 * Fills the CLIPOBJ and client rect of the WNDOBJ with the data from the given WINDOW_OBJECT
78 IntEngWndUpdateClipObj(
80 PWINDOW_OBJECT Window
)
84 CLIPOBJ
*ClipObj
= NULL
;
87 DPRINT("IntEngWndUpdateClipObj\n");
89 hVisRgn
= VIS_ComputeVisibleRegion(Window
, TRUE
, TRUE
, TRUE
);
92 NtGdiOffsetRgn(hVisRgn
, Window
->Wnd
->rcClient
.left
, Window
->Wnd
->rcClient
.top
);
93 visRgn
= RGNOBJAPI_Lock(hVisRgn
, NULL
);
96 if (visRgn
->rdh
.nCount
> 0)
98 ClipObj
= IntEngCreateClipRegion(visRgn
->rdh
.nCount
, visRgn
->Buffer
,
99 &visRgn
->rdh
.rcBound
);
100 DPRINT("Created visible region with %d rects\n", visRgn
->rdh
.nCount
);
101 DPRINT(" BoundingRect: %d, %d %d, %d\n",
102 visRgn
->rdh
.rcBound
.left
, visRgn
->rdh
.rcBound
.top
,
103 visRgn
->rdh
.rcBound
.right
, visRgn
->rdh
.rcBound
.bottom
);
106 for (i
= 0; i
< visRgn
->rdh
.nCount
; i
++)
108 DPRINT(" Rect #%d: %d,%d %d,%d\n", i
+1,
109 visRgn
->Buffer
[i
].left
, visRgn
->Buffer
[i
].top
,
110 visRgn
->Buffer
[i
].right
, visRgn
->Buffer
[i
].bottom
);
114 RGNOBJAPI_Unlock(visRgn
);
118 DPRINT1("Warning: Couldn't lock visible region of window DC\n");
120 REGION_FreeRgnByHandle(hVisRgn
);
124 DPRINT1("Warning: VIS_ComputeVisibleRegion failed!\n");
129 /* Fall back to client rect */
130 ClipObj
= IntEngCreateClipRegion(1, &Window
->Wnd
->rcClient
,
131 &Window
->Wnd
->rcClient
);
136 DPRINT1("Warning: IntEngCreateClipRegion() failed!\n");
140 RtlCopyMemory(&WndObjInt
->WndObj
.coClient
, ClipObj
, sizeof (CLIPOBJ
));
141 RtlCopyMemory(&WndObjInt
->WndObj
.rclClient
, &Window
->Wnd
->rcClient
, sizeof (RECT
));
142 OldClipObj
= InterlockedExchangePointer((PVOID
*)&WndObjInt
->ClientClipObj
, ClipObj
);
143 if (OldClipObj
!= NULL
)
144 IntEngDeleteClipRegion(OldClipObj
);
150 * Updates all WNDOBJs of the given WINDOW_OBJECT and calls the change-procs.
155 PWINDOW_OBJECT Window
,
161 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL
);
163 hWnd
= Window
->hSelf
; // pWnd->head.h;
164 Current
= (WNDGDI
*)IntGetProp(Window
, AtomWndObj
);
168 Current
->Hwnd
== hWnd
&&
169 Current
->WndObj
.pvConsumer
!= NULL
)
171 /* Update the WNDOBJ */
175 /* Update the clipobj and client rect of the WNDOBJ */
176 IntEngWndUpdateClipObj(Current
, Window
);
180 /* FIXME: Should the WNDOBJs be deleted by win32k or by the driver? */
184 /* Call the change proc */
185 IntEngWndCallChangeProc(&Current
->WndObj
, flChanged
);
187 /* HACK: Send WOC_CHANGED after WOC_RGN_CLIENT */
188 if (flChanged
== WOC_RGN_CLIENT
)
190 IntEngWndCallChangeProc(&Current
->WndObj
, WOC_CHANGED
);
203 WNDOBJCHANGEPROC pfn
,
207 WNDGDI
*WndObjInt
= NULL
;
208 WNDOBJ
*WndObjUser
= NULL
;
209 PWINDOW_OBJECT Window
;
211 DECLARE_RETURN(WNDOBJ
*);
213 DPRINT("EngCreateWnd: pso = 0x%x, hwnd = 0x%x, pfn = 0x%x, fl = 0x%x, pixfmt = %d\n",
214 pso
, hWnd
, pfn
, fl
, iPixelFormat
);
216 calledFromUser
= UserIsEntered();
217 if (!calledFromUser
){
221 /* Get window object */
222 Window
= UserGetWindowObject(hWnd
);
229 WndObjInt
= EngAllocMem(0, sizeof (WNDGDI
), TAG_WNDOBJ
);
230 if (WndObjInt
== NULL
)
232 DPRINT1("Failed to allocate memory for a WND structure!\n");
236 /* Fill the clipobj */
237 WndObjInt
->ClientClipObj
= NULL
;
238 if (!IntEngWndUpdateClipObj(WndObjInt
, Window
))
240 EngFreeMem(WndObjInt
);
244 /* Fill user object */
245 WndObjUser
= GDIToObj(WndObjInt
, WND
);
246 WndObjUser
->psoOwner
= pso
;
247 WndObjUser
->pvConsumer
= NULL
;
249 /* Fill internal object */
250 WndObjInt
->Hwnd
= hWnd
;
251 WndObjInt
->ChangeProc
= pfn
;
252 WndObjInt
->Flags
= fl
;
253 WndObjInt
->PixelFormat
= iPixelFormat
;
255 /* associate object with window */
256 IntSetProp(Window
, AtomWndObj
, WndObjInt
);
259 DPRINT("EngCreateWnd: SUCCESS!\n");
265 if (!calledFromUser
){
281 WNDGDI
*WndObjInt
= ObjToGDI(pwo
, WND
);
282 PWINDOW_OBJECT Window
;
285 DPRINT("EngDeleteWnd: pwo = 0x%x\n", pwo
);
287 calledFromUser
= UserIsEntered();
288 if (!calledFromUser
){
289 UserEnterExclusive();
292 /* Get window object */
293 Window
= UserGetWindowObject(WndObjInt
->Hwnd
);
296 DPRINT1("Warning: Couldnt get window object for WndObjInt->Hwnd!!!\n");
300 /* Remove object from window */
301 IntRemoveProp(Window
, AtomWndObj
);
305 if (!calledFromUser
){
310 IntEngDeleteClipRegion(WndObjInt
->ClientClipObj
);
311 EngFreeMem(WndObjInt
);
325 WNDGDI
*WndObjInt
= ObjToGDI(pwo
, WND
);
328 DPRINT("WNDOBJ_bEnum: pwo = 0x%x, cj = %d, pul = 0x%x\n", pwo
, cj
, pul
);
329 Ret
= CLIPOBJ_bEnum(WndObjInt
->ClientClipObj
, cj
, pul
);
331 DPRINT("WNDOBJ_bEnum: Returning %s\n", Ret
? "True" : "False");
347 WNDGDI
*WndObjInt
= ObjToGDI(pwo
, WND
);
350 DPRINT("WNDOBJ_cEnumStart: pwo = 0x%x, iType = %d, iDirection = %d, cLimit = %d\n",
351 pwo
, iType
, iDirection
, cLimit
);
353 /* FIXME: Should we enumerate all rectangles or not? */
354 Ret
= CLIPOBJ_cEnumStart(WndObjInt
->ClientClipObj
, FALSE
, iType
, iDirection
, cLimit
);
356 DPRINT("WNDOBJ_cEnumStart: Returning 0x%x\n", Ret
);
372 DPRINT("WNDOBJ_vSetConsumer: pwo = 0x%x, pvConsumer = 0x%x\n", pwo
, pvConsumer
);
374 Hack
= (pwo
->pvConsumer
== NULL
);
375 pwo
->pvConsumer
= pvConsumer
;
379 * MSDN says that the WNDOBJCHANGEPROC will be called with the most recent state
380 * when a WNDOBJ is created - we do it here because most drivers will need pvConsumer
381 * in the callback to identify the WNDOBJ I think.
387 IntEngWndCallChangeProc(pwo
, WOC_RGN_CLIENT
);
388 IntEngWndCallChangeProc(pwo
, WOC_CHANGED
);
389 IntEngWndCallChangeProc(pwo
, WOC_DRAWN
);