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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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
30 /* TODO: Check how the WNDOBJ implementation should behave with a driver on windows. */
38 * Calls the WNDOBJCHANGEPROC of the given WNDOBJ
42 IntEngWndCallChangeProc(
46 WNDGDI
*WndObjInt
= ObjToGDI(pwo
, WND
);
48 if (WndObjInt
->ChangeProc
== NULL
)
53 /* check flags of the WNDOBJ */
54 flChanged
&= WndObjInt
->Flags
;
60 /* Call the WNDOBJCHANGEPROC */
61 if (flChanged
== WOC_CHANGED
)
66 DPRINT("Calling WNDOBJCHANGEPROC (0x%x), Changed = 0x%x\n",
67 WndObjInt
->ChangeProc
, flChanged
);
68 WndObjInt
->ChangeProc(pwo
, flChanged
);
72 * Fills the CLIPOBJ and client rect of the WNDOBJ with the data from the given WINDOW_OBJECT
76 IntEngWndUpdateClipObj(
78 PWINDOW_OBJECT Window
)
82 CLIPOBJ
*ClipObj
= NULL
;
85 hVisRgn
= VIS_ComputeVisibleRegion(Window
, TRUE
, TRUE
, TRUE
);
88 NtGdiOffsetRgn(hVisRgn
, Window
->Wnd
->ClientRect
.left
, Window
->Wnd
->ClientRect
.top
);
89 visRgn
= REGION_LockRgn(hVisRgn
);
92 if (visRgn
->rdh
.nCount
> 0)
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
);
102 for (i
= 0; i
< visRgn
->rdh
.nCount
; i
++)
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
);
110 REGION_UnlockRgn(visRgn
);
114 DPRINT1("Warning: Couldn't lock visible region of window DC\n");
119 DPRINT1("Warning: VIS_ComputeVisibleRegion failed!\n");
124 /* Fall back to client rect */
125 ClipObj
= IntEngCreateClipRegion(1, (PRECTL
)&Window
->Wnd
->ClientRect
,
126 (PRECTL
)&Window
->Wnd
->ClientRect
);
131 DPRINT1("Warning: IntEngCreateClipRegion() failed!\n");
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
);
145 * Updates all WNDOBJs of the given WINDOW_OBJECT and calls the change-procs.
150 PWINDOW_OBJECT Window
,
153 PLIST_ENTRY CurrentEntry
;
156 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL
);
158 CurrentEntry
= Window
->WndObjListHead
.Flink
;
159 while (CurrentEntry
!= &Window
->WndObjListHead
)
161 Current
= CONTAINING_RECORD(CurrentEntry
, WNDGDI
, ListEntry
);
163 if (Current
->WndObj
.pvConsumer
!= NULL
)
165 /* Update the WNDOBJ */
169 /* Update the clipobj and client rect of the WNDOBJ */
170 IntEngWndUpdateClipObj(Current
, Window
);
174 /* FIXME: Should the WNDOBJs be deleted by win32k or by the driver? */
178 /* Call the change proc */
179 IntEngWndCallChangeProc(&Current
->WndObj
, flChanged
);
181 /* HACK: Send WOC_CHANGED after WOC_RGN_CLIENT */
182 if (flChanged
== WOC_RGN_CLIENT
)
184 IntEngWndCallChangeProc(&Current
->WndObj
, WOC_CHANGED
);
187 CurrentEntry
= CurrentEntry
->Flink
;
201 WNDOBJCHANGEPROC pfn
,
205 WNDGDI
*WndObjInt
= NULL
;
206 WNDOBJ
*WndObjUser
= NULL
;
207 PWINDOW_OBJECT Window
;
209 DECLARE_RETURN(WNDOBJ
*);
211 DPRINT("EngCreateWnd: pso = 0x%x, hwnd = 0x%x, pfn = 0x%x, fl = 0x%x, pixfmt = %d\n",
212 pso
, hWnd
, pfn
, fl
, iPixelFormat
);
214 calledFromUser
= UserIsEntered();
215 if (!calledFromUser
){
219 /* Get window object */
220 Window
= UserGetWindowObject(hWnd
);
227 WndObjInt
= EngAllocMem(0, sizeof (WNDGDI
), TAG_WNDOBJ
);
228 if (WndObjInt
== NULL
)
230 DPRINT1("Failed to allocate memory for a WND structure!\n");
234 /* Fill the clipobj */
235 WndObjInt
->ClientClipObj
= NULL
;
236 if (!IntEngWndUpdateClipObj(WndObjInt
, Window
))
238 EngFreeMem(WndObjInt
);
242 /* Fill user object */
243 WndObjUser
= GDIToObj(WndObjInt
, WND
);
244 WndObjUser
->psoOwner
= pso
;
245 WndObjUser
->pvConsumer
= NULL
;
247 /* Fill internal object */
248 WndObjInt
->Hwnd
= hWnd
;
249 WndObjInt
->ChangeProc
= pfn
;
250 WndObjInt
->Flags
= fl
;
251 WndObjInt
->PixelFormat
= iPixelFormat
;
253 /* associate object with window */
254 InsertTailList(&Window
->WndObjListHead
, &WndObjInt
->ListEntry
);
256 DPRINT("EngCreateWnd: SUCCESS!\n");
262 if (!calledFromUser
){
278 WNDGDI
*WndObjInt
= ObjToGDI(pwo
, WND
);
279 PWINDOW_OBJECT Window
;
282 DPRINT("EngDeleteWnd: pwo = 0x%x\n", pwo
);
284 calledFromUser
= UserIsEntered();
285 if (!calledFromUser
){
286 UserEnterExclusive();
289 /* Get window object */
290 Window
= UserGetWindowObject(WndObjInt
->Hwnd
);
293 DPRINT1("Warning: Couldnt get window object for WndObjInt->Hwnd!!!\n");
294 RemoveEntryList(&WndObjInt
->ListEntry
);
298 /* Remove object from window */
299 RemoveEntryList(&WndObjInt
->ListEntry
);
302 if (!calledFromUser
){
307 IntEngDeleteClipRegion(WndObjInt
->ClientClipObj
);
308 EngFreeMem(WndObjInt
);
322 WNDGDI
*WndObjInt
= ObjToGDI(pwo
, WND
);
325 DPRINT("WNDOBJ_bEnum: pwo = 0x%x, cj = %d, pul = 0x%x\n", pwo
, cj
, pul
);
326 Ret
= CLIPOBJ_bEnum(WndObjInt
->ClientClipObj
, cj
, pul
);
328 DPRINT("WNDOBJ_bEnum: Returning %s\n", Ret
? "True" : "False");
344 WNDGDI
*WndObjInt
= ObjToGDI(pwo
, WND
);
347 DPRINT("WNDOBJ_cEnumStart: pwo = 0x%x, iType = %d, iDirection = %d, cLimit = %d\n",
348 pwo
, iType
, iDirection
, cLimit
);
350 /* FIXME: Should we enumerate all rectangles or not? */
351 Ret
= CLIPOBJ_cEnumStart(WndObjInt
->ClientClipObj
, FALSE
, iType
, iDirection
, cLimit
);
353 DPRINT("WNDOBJ_cEnumStart: Returning 0x%x\n", Ret
);
369 DPRINT("WNDOBJ_vSetConsumer: pwo = 0x%x, pvConsumer = 0x%x\n", pwo
, pvConsumer
);
371 Hack
= (pwo
->pvConsumer
== NULL
);
372 pwo
->pvConsumer
= pvConsumer
;
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.
384 IntEngWndCallChangeProc(pwo
, WOC_RGN_CLIENT
);
385 IntEngWndCallChangeProc(pwo
, WOC_CHANGED
);
386 IntEngWndCallChangeProc(pwo
, WOC_DRAWN
);