2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 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: Window classes
24 * FILE: subsys/win32k/ntuser/class.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
27 * 06-06-2001 CSH Created
30 /* INCLUDES ******************************************************************/
32 #include <ddk/ntddk.h>
33 #include <win32k/win32k.h>
34 #include <win32k/region.h>
35 #include <win32k/userobj.h>
36 #include <include/class.h>
37 #include <include/error.h>
38 #include <include/winsta.h>
39 #include <include/msgqueue.h>
40 #include <include/window.h>
41 #include <include/rect.h>
42 #include <include/dce.h>
43 #include <include/vis.h>
48 /* GLOBALS *******************************************************************/
50 static PDCE FirstDce = NULL;
52 #define DCX_CACHECOMPAREMASK (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | \
53 DCX_CACHE | DCX_WINDOW | DCX_PARENTCLIP)
55 /* FUNCTIONS *****************************************************************/
58 DceGetVisRgn(HWND hWnd, ULONG Flags, HWND hWndChild, ULONG CFlags)
60 PWINDOW_OBJECT Window;
67 Window = IntGetWindowObject(hWnd);
74 VisRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, Window,
75 0 == (Flags & DCX_WINDOW),
76 0 != (Flags & DCX_CLIPCHILDREN),
77 0 != (Flags & DCX_CLIPSIBLINGS));
78 if (NULL != hWndChild && 0 != (CFlags & DCX_CLIPCHILDREN))
80 /* We need to filter out the child windows of hWndChild */
81 Child = IntGetWindowObject(hWnd);
84 if (Child->FirstChild)
86 /* Compute the visible region of the child */
87 VisChild = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
88 Child, FALSE, TRUE, FALSE);
89 /* If the child doesn't obscure the whole window, we need to
90 extend it. First compute the difference between window and child */
91 ChildRect = UnsafeIntCreateRectRgnIndirect(&(Child->ClientRect));
92 if (0 == (Flags & DCX_WINDOW))
94 ParentRect = UnsafeIntCreateRectRgnIndirect(&(Window->ClientRect));
98 ParentRect = UnsafeIntCreateRectRgnIndirect(&(Window->WindowRect));
100 NtGdiCombineRgn(ChildRect, ParentRect, ChildRect, RGN_DIFF);
102 /* Now actually extend the child by adding the difference */
103 NtGdiCombineRgn(VisChild, VisChild, ChildRect, RGN_OR);
105 /* Clip the childs children */
106 NtGdiCombineRgn(VisRgn, VisRgn, VisChild, RGN_AND);
108 IntReleaseWindowObject(Child);
112 IntReleaseWindowObject(Window);
118 NtUserReleaseDC(HWND hWnd, HDC hDc)
124 NtUserGetDC(HWND hWnd)
126 return NtUserGetDCEx(hWnd, NULL, NULL == hWnd ? DCX_CACHE | DCX_WINDOW : DCX_USESTYLE);
129 PDCE FASTCALL DceAllocDCE(HWND hWnd, DCE_TYPE Type)
134 DceHandle = DCEOBJ_AllocDCE();
135 Dce = DCEOBJ_LockDCE(DceHandle);
136 Dce->hDC = NtGdiCreateDC(L"DISPLAY", NULL, NULL, NULL);
137 Dce->hwndCurrent = hWnd;
138 Dce->hClipRgn = NULL;
139 Dce->next = FirstDce;
142 if (Type != DCE_CACHE_DC)
144 Dce->DCXFlags = DCX_DCEBUSY;
147 PWINDOW_OBJECT WindowObject;
149 WindowObject = IntGetWindowObject(hWnd);
150 if (WindowObject->Style & WS_CLIPCHILDREN)
152 Dce->DCXFlags |= DCX_CLIPCHILDREN;
154 if (WindowObject->Style & WS_CLIPSIBLINGS)
156 Dce->DCXFlags |= DCX_CLIPSIBLINGS;
158 IntReleaseWindowObject(WindowObject);
163 Dce->DCXFlags = DCX_CACHE | DCX_DCEEMPTY;
170 DceSetDrawable(PWINDOW_OBJECT WindowObject, HDC hDC, ULONG Flags,
173 DC *dc = DC_LockDc(hDC);
174 if (WindowObject == NULL)
181 if (Flags & DCX_WINDOW)
183 dc->w.DCOrgX = WindowObject->WindowRect.left;
184 dc->w.DCOrgY = WindowObject->WindowRect.top;
188 dc->w.DCOrgX = WindowObject->ClientRect.left;
189 dc->w.DCOrgY = WindowObject->ClientRect.top;
197 DceDeleteClipRgn(DCE* Dce)
199 Dce->DCXFlags &= ~(DCX_EXCLUDERGN | DCX_INTERSECTRGN | DCX_WINDOWPAINT);
201 if (Dce->DCXFlags & DCX_KEEPCLIPRGN )
203 Dce->DCXFlags &= ~DCX_KEEPCLIPRGN;
205 else if (Dce->hClipRgn > (HRGN) 1)
207 NtGdiDeleteObject(Dce->hClipRgn);
210 Dce->hClipRgn = NULL;
212 /* make it dirty so that the vis rgn gets recomputed next time */
213 Dce->DCXFlags |= DCX_DCEDIRTY;
217 NtUserGetDCEx(HWND hWnd, HANDLE ClipRegion, ULONG Flags)
219 PWINDOW_OBJECT Window;
222 BOOL UpdateVisRgn = TRUE;
223 BOOL UpdateClipOrigin = FALSE;
224 HANDLE hRgnVisible = NULL;
228 Flags &= ~DCX_USESTYLE;
231 else if (NULL == (Window = IntGetWindowObject(hWnd)))
236 if (NULL == Window || NULL == Window->Dce)
242 if (Flags & DCX_USESTYLE)
244 Flags &= ~(DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS | DCX_PARENTCLIP);
246 if (Window->Style & WS_CLIPSIBLINGS)
248 Flags |= DCX_CLIPSIBLINGS;
251 if (!(Flags & DCX_WINDOW))
253 if (Window->Class->style & CS_PARENTDC)
255 Flags |= DCX_PARENTCLIP;
258 if (Window->Style & WS_CLIPCHILDREN &&
259 !(Window->Style & WS_MINIMIZE))
261 Flags |= DCX_CLIPCHILDREN;
270 if (Flags & DCX_NOCLIPCHILDREN)
273 Flags |= ~(DCX_PARENTCLIP | DCX_CLIPCHILDREN);
276 if (Flags & DCX_WINDOW)
278 Flags = (Flags & ~DCX_CLIPCHILDREN) | DCX_CACHE;
281 if (NULL == Window || !(Window->Style & WS_CHILD) || NULL == Window->Parent)
283 Flags &= ~DCX_PARENTCLIP;
285 else if (Flags & DCX_PARENTCLIP)
288 if (!(Flags & (DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS)))
290 if ((Window->Style & WS_VISIBLE) &&
291 (Window->Parent->Style & WS_VISIBLE))
293 Flags &= ~DCX_CLIPCHILDREN;
294 if (Window->Parent->Style & WS_CLIPSIBLINGS)
296 Flags |= DCX_CLIPSIBLINGS;
302 DcxFlags = Flags & DCX_CACHECOMPAREMASK;
304 if (Flags & DCX_CACHE)
306 DCE* DceEmpty = NULL;
307 DCE* DceUnused = NULL;
309 for (Dce = FirstDce; Dce != NULL; Dce = Dce->next)
311 if ((Dce->DCXFlags & (DCX_CACHE | DCX_DCEBUSY)) == DCX_CACHE)
314 if (Dce->DCXFlags & DCX_DCEEMPTY)
318 else if (Dce->hwndCurrent == hWnd &&
319 ((Dce->DCXFlags & DCX_CACHECOMPAREMASK) == DcxFlags))
321 UpdateVisRgn = FALSE;
322 UpdateClipOrigin = TRUE;
330 Dce = (DceEmpty == NULL) ? DceEmpty : DceUnused;
335 Dce = DceAllocDCE(NULL, DCE_CACHE_DC);
341 /* FIXME: Implement this. */
345 if (NULL == Dce && NULL != Window)
347 IntReleaseWindowObject(Window);
351 Dce->hwndCurrent = hWnd;
352 Dce->hClipRgn = NULL;
353 Dce->DCXFlags = DcxFlags | (Flags & DCX_WINDOWPAINT) | DCX_DCEBUSY;
355 if (0 == (Flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN)) && NULL != ClipRegion)
357 NtGdiDeleteObject(ClipRegion);
361 if (NULL != Dce->hClipRgn)
363 DceDeleteClipRgn(Dce);
366 if (NULL != ClipRegion)
368 Dce->hClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
369 NtGdiCombineRgn(Dce->hClipRgn, ClipRegion, NULL, RGN_COPY);
370 NtGdiDeleteObject(ClipRegion);
373 DceSetDrawable(Window, Dce->hDC, Flags, UpdateClipOrigin);
377 if (Flags & DCX_PARENTCLIP)
379 PWINDOW_OBJECT Parent;
381 Parent = Window->Parent;
383 if (Window->Style & WS_VISIBLE &&
384 !(Parent->Style & WS_MINIMIZE))
386 if (Parent->Style & WS_CLIPSIBLINGS)
388 DcxFlags = DCX_CLIPSIBLINGS |
389 (Flags & ~(DCX_CLIPCHILDREN | DCX_WINDOW));
394 ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW);
396 hRgnVisible = DceGetVisRgn(Parent->Self, DcxFlags,
397 Window->Self, Flags);
401 hRgnVisible = NtGdiCreateRectRgn(0, 0, 0, 0);
406 if (hWnd == IntGetDesktopWindow())
409 NtGdiCreateRectRgn(0, 0,
410 NtUserGetSystemMetrics(SM_CXSCREEN),
411 NtUserGetSystemMetrics(SM_CYSCREEN));
415 hRgnVisible = DceGetVisRgn(hWnd, Flags, 0, 0);
419 if (0 != (Flags & DCX_INTERSECTRGN))
421 NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hClipRgn, RGN_AND);
424 if (0 != (Flags & DCX_EXCLUDERGN))
426 NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hClipRgn, RGN_DIFF);
429 Dce->DCXFlags &= ~DCX_DCEDIRTY;
430 NtGdiSelectVisRgn(Dce->hDC, hRgnVisible);
433 if (hRgnVisible != NULL)
435 NtGdiDeleteObject(hRgnVisible);
439 IntReleaseWindowObject(Window);
446 DCE_InternalDelete(PDCE Dce)
452 FirstDce = Dce->next;
457 for (PrevInList = FirstDce; NULL != PrevInList; PrevInList = PrevInList->next)
459 if (Dce == PrevInList->next)
461 PrevInList->next = Dce->next;
465 assert(NULL != PrevInList);
468 return NULL != PrevInList;
472 IntWindowFromDC(HDC hDc)
475 for (Dce = FirstDce; Dce != NULL; Dce = Dce->next)
479 return Dce->hwndCurrent;