4ce9c8c362b4ed0d7e145184bbc9ae114f07e9dd
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.
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.
41 * Calls the WNDOBJCHANGEPROC of the given WNDOBJ
45 IntEngWndCallChangeProc(
49 WNDGDI
*WndObjInt
= ObjToGDI(pwo
, WND
);
51 if (WndObjInt
->ChangeProc
== NULL
)
56 /* check flags of the WNDOBJ */
57 flChanged
&= WndObjInt
->Flags
;
63 /* Call the WNDOBJCHANGEPROC */
64 if (flChanged
== WOC_CHANGED
)
69 DPRINT("Calling WNDOBJCHANGEPROC (0x%x), Changed = 0x%x\n",
70 WndObjInt
->ChangeProc
, flChanged
);
71 WndObjInt
->ChangeProc(pwo
, flChanged
);
75 * Fills the CLIPOBJ and client rect of the WNDOBJ with the data from the given WINDOW_OBJECT
79 IntEngWndUpdateClipObj(
81 PWINDOW_OBJECT Window
)
85 CLIPOBJ
*ClipObj
= NULL
;
88 hVisRgn
= VIS_ComputeVisibleRegion(Window
, TRUE
, TRUE
, TRUE
);
91 NtGdiOffsetRgn(hVisRgn
, Window
->Wnd
->rcClient
.left
, Window
->Wnd
->rcClient
.top
);
92 visRgn
= REGION_LockRgn(hVisRgn
);
95 if (visRgn
->rdh
.nCount
> 0)
97 ClipObj
= IntEngCreateClipRegion(visRgn
->rdh
.nCount
, visRgn
->Buffer
,
98 &visRgn
->rdh
.rcBound
);
99 DPRINT("Created visible region with %d rects\n", visRgn
->rdh
.nCount
);
100 DPRINT(" BoundingRect: %d, %d %d, %d\n",
101 visRgn
->rdh
.rcBound
.left
, visRgn
->rdh
.rcBound
.top
,
102 visRgn
->rdh
.rcBound
.right
, visRgn
->rdh
.rcBound
.bottom
);
105 for (i
= 0; i
< visRgn
->rdh
.nCount
; i
++)
107 DPRINT(" Rect #%d: %d,%d %d,%d\n", i
+1,
108 visRgn
->Buffer
[i
].left
, visRgn
->Buffer
[i
].top
,
109 visRgn
->Buffer
[i
].right
, visRgn
->Buffer
[i
].bottom
);
113 REGION_UnlockRgn(visRgn
);
117 DPRINT1("Warning: Couldn't lock visible region of window DC\n");
122 DPRINT1("Warning: VIS_ComputeVisibleRegion failed!\n");
127 /* Fall back to client rect */
128 ClipObj
= IntEngCreateClipRegion(1, &Window
->Wnd
->rcClient
,
129 &Window
->Wnd
->rcClient
);
134 DPRINT1("Warning: IntEngCreateClipRegion() failed!\n");
138 RtlCopyMemory(&WndObjInt
->WndObj
.coClient
, ClipObj
, sizeof (CLIPOBJ
));
139 RtlCopyMemory(&WndObjInt
->WndObj
.rclClient
, &Window
->Wnd
->rcClient
, sizeof (RECT
));
140 OldClipObj
= InterlockedExchangePointer(&WndObjInt
->ClientClipObj
, ClipObj
);
141 if (OldClipObj
!= NULL
)
142 IntEngDeleteClipRegion(OldClipObj
);
148 * Updates all WNDOBJs of the given WINDOW_OBJECT and calls the change-procs.
153 PWINDOW_OBJECT Window
,
156 PLIST_ENTRY CurrentEntry
;
159 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL
);
161 CurrentEntry
= Window
->WndObjListHead
.Flink
;
162 while (CurrentEntry
!= &Window
->WndObjListHead
)
164 Current
= CONTAINING_RECORD(CurrentEntry
, WNDGDI
, ListEntry
);
166 if (Current
->WndObj
.pvConsumer
!= NULL
)
168 /* Update the WNDOBJ */
172 /* Update the clipobj and client rect of the WNDOBJ */
173 IntEngWndUpdateClipObj(Current
, Window
);
177 /* FIXME: Should the WNDOBJs be deleted by win32k or by the driver? */
181 /* Call the change proc */
182 IntEngWndCallChangeProc(&Current
->WndObj
, flChanged
);
184 /* HACK: Send WOC_CHANGED after WOC_RGN_CLIENT */
185 if (flChanged
== WOC_RGN_CLIENT
)
187 IntEngWndCallChangeProc(&Current
->WndObj
, WOC_CHANGED
);
190 CurrentEntry
= CurrentEntry
->Flink
;
204 WNDOBJCHANGEPROC pfn
,
208 WNDGDI
*WndObjInt
= NULL
;
209 WNDOBJ
*WndObjUser
= NULL
;
210 PWINDOW_OBJECT Window
;
212 DECLARE_RETURN(WNDOBJ
*);
214 DPRINT("EngCreateWnd: pso = 0x%x, hwnd = 0x%x, pfn = 0x%x, fl = 0x%x, pixfmt = %d\n",
215 pso
, hWnd
, pfn
, fl
, iPixelFormat
);
217 calledFromUser
= UserIsEntered();
218 if (!calledFromUser
){
222 /* Get window object */
223 Window
= UserGetWindowObject(hWnd
);
230 WndObjInt
= EngAllocMem(0, sizeof (WNDGDI
), TAG_WNDOBJ
);
231 if (WndObjInt
== NULL
)
233 DPRINT1("Failed to allocate memory for a WND structure!\n");
237 /* Fill the clipobj */
238 WndObjInt
->ClientClipObj
= NULL
;
239 if (!IntEngWndUpdateClipObj(WndObjInt
, Window
))
241 EngFreeMem(WndObjInt
);
245 /* Fill user object */
246 WndObjUser
= GDIToObj(WndObjInt
, WND
);
247 WndObjUser
->psoOwner
= pso
;
248 WndObjUser
->pvConsumer
= NULL
;
250 /* Fill internal object */
251 WndObjInt
->Hwnd
= hWnd
;
252 WndObjInt
->ChangeProc
= pfn
;
253 WndObjInt
->Flags
= fl
;
254 WndObjInt
->PixelFormat
= iPixelFormat
;
256 /* associate object with window */
257 InsertTailList(&Window
->WndObjListHead
, &WndObjInt
->ListEntry
);
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");
297 RemoveEntryList(&WndObjInt
->ListEntry
);
301 /* Remove object from window */
302 RemoveEntryList(&WndObjInt
->ListEntry
);
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
);