+/*
+ * ReactOS W32 Subsystem
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
#include <include/window.h>
#include <include/rect.h>
#include <include/dce.h>
+#include <include/vis.h>
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
-VOID STATIC
-DceOffsetVisRgn(HDC hDC, HRGN hVisRgn)
-{
- DC *dc = DC_HandleToPtr(hDC);
- if (dc == NULL)
- {
- return;
- }
- W32kOffsetRgn(hVisRgn, dc->w.DCOrgX, dc->w.DCOrgY);
- DC_ReleasePtr(hDC);
-}
-
-BOOL STATIC
-DceGetVisRect(PWINDOW_OBJECT Window, BOOL ClientArea, RECT* Rect)
-{
- if (ClientArea)
- {
- *Rect = Window->ClientRect;
- }
- else
- {
- *Rect = Window->WindowRect;
- }
-
- if (Window->Style & WS_VISIBLE)
- {
- INT XOffset = Rect->left;
- INT YOffset = Rect->top;
-
- while ((Window = Window->Parent) != NULL)
- {
- if ((Window->Style & (WS_ICONIC | WS_VISIBLE)) != WS_VISIBLE)
- {
- W32kSetEmptyRect(Rect);
- return(FALSE);
- }
- XOffset += Window->ClientRect.left;
- YOffset += Window->ClientRect.top;
- W32kOffsetRect(Rect, Window->ClientRect.left,
- Window->ClientRect.top);
- if (Window->ClientRect.left >= Window->ClientRect.right ||
- Window->ClientRect.top >= Window->ClientRect.bottom ||
- Rect->left >= Window->ClientRect.right ||
- Rect->right <= Window->ClientRect.left ||
- Rect->top >= Window->ClientRect.bottom ||
- Rect->bottom <= Window->ClientRect.top)
- {
- W32kSetEmptyRect(Rect);
- return(FALSE);
- }
- Rect->left = max(Rect->left, Window->ClientRect.left);
- Rect->right = min(Rect->right, Window->ClientRect.right);
- Rect->top = max(Rect->top, Window->ClientRect.top);
- Rect->bottom = min(Rect->bottom, Window->ClientRect.bottom);
- }
- W32kOffsetRect(Rect, -XOffset, -YOffset);
- return(TRUE);
- }
- W32kSetEmptyRect(Rect);
- return(FALSE);
-}
-
-BOOL
-DceAddClipRects(PWINDOW_OBJECT Parent, PWINDOW_OBJECT End,
- HRGN ClipRgn, PRECT Rect, INT XOffset, INT YOffset)
-{
- PLIST_ENTRY ChildListEntry;
- PWINDOW_OBJECT Child;
- RECT Rect1;
-
- ChildListEntry = Parent->ChildrenListHead.Flink;
- while (ChildListEntry != &Parent->ChildrenListHead)
- {
- Child = CONTAINING_RECORD(ChildListEntry, WINDOW_OBJECT,
- SiblingListEntry);
- if (Child == End)
- {
- return(TRUE);
- }
- if (Child->Style & WS_VISIBLE)
- {
- Rect1.left = Child->WindowRect.left + XOffset;
- Rect1.top = Child->WindowRect.top + YOffset;
- Rect1.right = Child->WindowRect.right + XOffset;
- Rect1.bottom = Child->WindowRect.bottom + YOffset;
-
- if (W32kIntersectRect(&Rect1, &Rect1, Rect))
- {
- W32kUnionRectWithRgn(ClipRgn, &Rect1);
- }
- }
- ChildListEntry = ChildListEntry->Flink;
- }
- return(FALSE);
-}
-
-HRGN
+HRGN STDCALL
DceGetVisRgn(HWND hWnd, ULONG Flags, HWND hWndChild, ULONG CFlags)
{
PWINDOW_OBJECT Window;
PWINDOW_OBJECT Child;
HRGN VisRgn;
- RECT Rect;
+ HRGN VisChild;
+ HRGN ChildRect;
+ HRGN ParentRect;
- Window = W32kGetWindowObject(hWnd);
- Child = W32kGetWindowObject(hWndChild);
+ Window = IntGetWindowObject(hWnd);
- if (Window != NULL && DceGetVisRect(Window, !(Flags & DCX_WINDOW), &Rect))
+ if (NULL == Window)
{
- if ((VisRgn = UnsafeW32kCreateRectRgnIndirect(&Rect)) != NULL)
- {
- HRGN ClipRgn = W32kCreateRectRgn(0, 0, 0, 0);
- INT XOffset, YOffset;
+ return NULL;
+ }
- if (ClipRgn != NULL)
+ VisRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, Window,
+ 0 == (Flags & DCX_WINDOW),
+ 0 != (Flags & DCX_CLIPCHILDREN),
+ 0 != (Flags & DCX_CLIPSIBLINGS));
+ if (NULL != hWndChild && 0 != (CFlags & DCX_CLIPCHILDREN))
+ {
+ /* We need to filter out the child windows of hWndChild */
+ Child = IntGetWindowObject(hWnd);
+ if (NULL != Child)
+ {
+ if (Child->FirstChild)
{
- if (Flags & DCX_CLIPCHILDREN &&
- !IsListEmpty(&Window->ChildrenListHead))
+ /* Compute the visible region of the child */
+ VisChild = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
+ Child, FALSE, TRUE, FALSE);
+ /* If the child doesn't obscure the whole window, we need to
+ extend it. First compute the difference between window and child */
+ ChildRect = UnsafeIntCreateRectRgnIndirect(&(Child->ClientRect));
+ if (0 == (Flags & DCX_WINDOW))
{
- if (Flags & DCX_WINDOW)
- {
- XOffset = Window->ClientRect.left -
- Window->WindowRect.left;
- YOffset = Window->ClientRect.top -
- Window->WindowRect.top;
- }
- else
- {
- XOffset = YOffset = 0;
- }
- DceAddClipRects(Window, NULL, ClipRgn, &Rect,
- XOffset, YOffset);
- }
-
- if (CFlags & DCX_CLIPCHILDREN && Child &&
- !IsListEmpty(&Child->ChildrenListHead))
- {
- if (Flags & DCX_WINDOW)
- {
- XOffset = Window->ClientRect.left -
- Window->WindowRect.left;
- YOffset = Window->ClientRect.top -
- Window->WindowRect.top;
- }
- else
- {
- XOffset = YOffset = 0;
- }
-
- XOffset += Child->ClientRect.left;
- YOffset += Child->ClientRect.top;
-
- DceAddClipRects(Child, NULL, ClipRgn, &Rect,
- XOffset, YOffset);
- }
-
- if (Flags & DCX_WINDOW)
- {
- XOffset = -Window->WindowRect.left;
- YOffset = -Window->WindowRect.top;
+ ParentRect = UnsafeIntCreateRectRgnIndirect(&(Window->ClientRect));
}
else
{
- XOffset = -Window->ClientRect.left;
- YOffset = -Window->ClientRect.top;
+ ParentRect = UnsafeIntCreateRectRgnIndirect(&(Window->WindowRect));
}
+ NtGdiCombineRgn(ChildRect, ParentRect, ChildRect, RGN_DIFF);
- if (Flags & DCX_CLIPSIBLINGS && Window->Parent != NULL)
- {
- DceAddClipRects(Window->Parent, Window, ClipRgn,
- &Rect, XOffset, YOffset);
- }
-
- while (Window->Style & WS_CHILD)
- {
- Window = Window->Parent;
- XOffset -= Window->ClientRect.left;
- YOffset -= Window->ClientRect.top;
- if (Window->Style & WS_CLIPSIBLINGS &&
- Window->Parent != NULL)
- {
- DceAddClipRects(Window->Parent, Window, ClipRgn,
- &Rect, XOffset, YOffset);
- }
- }
+ /* Now actually extend the child by adding the difference */
+ NtGdiCombineRgn(VisChild, VisChild, ChildRect, RGN_OR);
- W32kCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
- W32kDeleteObject(ClipRgn);
- }
- else
- {
- W32kDeleteObject(VisRgn);
- VisRgn = 0;
+ /* Clip the childs children */
+ NtGdiCombineRgn(VisRgn, VisRgn, VisChild, RGN_AND);
}
+ IntReleaseWindowObject(Child);
}
}
- else
- {
- VisRgn = W32kCreateRectRgn(0, 0, 0, 0);
- }
- W32kReleaseWindowObject(Window);
- W32kReleaseWindowObject(Child);
- return(VisRgn);
+
+ IntReleaseWindowObject(Window);
+
+ return VisRgn;
}
INT STDCALL
NtUserReleaseDC(HWND hWnd, HDC hDc)
{
-
+ return 1;
}
HDC STDCALL
NtUserGetDC(HWND hWnd)
{
- if (!hWnd)
- return NtUserGetDCEx(0, 0, DCX_CACHE | DCX_WINDOW);
- return NtUserGetDCEx(hWnd, 0, DCX_USESTYLE);
+ return NtUserGetDCEx(hWnd, NULL, NULL == hWnd ? DCX_CACHE | DCX_WINDOW : DCX_USESTYLE);
}
-DCE* DceAllocDCE(HWND hWnd, DCE_TYPE Type)
+PDCE FASTCALL DceAllocDCE(HWND hWnd, DCE_TYPE Type)
{
HDCE DceHandle;
DCE* Dce;
DceHandle = DCEOBJ_AllocDCE();
Dce = DCEOBJ_LockDCE(DceHandle);
- Dce->hDC = W32kCreateDC(L"DISPLAY", NULL, NULL, NULL);
+ Dce->hDC = NtGdiCreateDC(L"DISPLAY", NULL, NULL, NULL);
Dce->hwndCurrent = hWnd;
Dce->hClipRgn = NULL;
Dce->next = FirstDce;
{
PWINDOW_OBJECT WindowObject;
- WindowObject = W32kGetWindowObject(hWnd);
+ WindowObject = IntGetWindowObject(hWnd);
if (WindowObject->Style & WS_CLIPCHILDREN)
{
Dce->DCXFlags |= DCX_CLIPCHILDREN;
{
Dce->DCXFlags |= DCX_CLIPSIBLINGS;
}
- W32kReleaseWindowObject(WindowObject);
+ IntReleaseWindowObject(WindowObject);
}
}
else
return(Dce);
}
-VOID STATIC
+VOID STATIC STDCALL
DceSetDrawable(PWINDOW_OBJECT WindowObject, HDC hDC, ULONG Flags,
BOOL SetClipOrigin)
{
- DC *dc = DC_HandleToPtr(hDC);
+ DC *dc = DC_LockDc(hDC);
if (WindowObject == NULL)
{
dc->w.DCOrgX = 0;
dc->w.DCOrgX = WindowObject->ClientRect.left;
dc->w.DCOrgY = WindowObject->ClientRect.top;
}
- /* FIXME: Offset by parent's client rectangle. */
}
- DC_ReleasePtr(hDC);
+ DC_UnlockDc(hDC);
+}
+
+
+STATIC VOID FASTCALL
+DceDeleteClipRgn(DCE* Dce)
+{
+ Dce->DCXFlags &= ~(DCX_EXCLUDERGN | DCX_INTERSECTRGN | DCX_WINDOWPAINT);
+
+ if (Dce->DCXFlags & DCX_KEEPCLIPRGN )
+ {
+ Dce->DCXFlags &= ~DCX_KEEPCLIPRGN;
+ }
+ else if (Dce->hClipRgn > (HRGN) 1)
+ {
+ NtGdiDeleteObject(Dce->hClipRgn);
+ }
+
+ Dce->hClipRgn = NULL;
+
+ /* make it dirty so that the vis rgn gets recomputed next time */
+ Dce->DCXFlags |= DCX_DCEDIRTY;
}
HDC STDCALL
-NtUserGetDCEx(HWND hWnd, HANDLE hRegion, ULONG Flags)
+NtUserGetDCEx(HWND hWnd, HANDLE ClipRegion, ULONG Flags)
{
PWINDOW_OBJECT Window;
ULONG DcxFlags;
BOOL UpdateClipOrigin = FALSE;
HANDLE hRgnVisible = NULL;
- if ((Window = W32kGetWindowObject(hWnd)) == NULL)
+ if (NULL == hWnd)
+ {
+ Flags &= ~DCX_USESTYLE;
+ Window = NULL;
+ }
+ else if (NULL == (Window = IntGetWindowObject(hWnd)))
{
return(0);
}
- if (Window->Dce == NULL)
+ if (NULL == Window || NULL == Window->Dce)
{
Flags |= DCX_CACHE;
}
+
if (Flags & DCX_USESTYLE)
{
Flags &= ~(DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS | DCX_PARENTCLIP);
if (!(Flags & DCX_WINDOW))
{
- if (Window->Class->Class.style & CS_PARENTDC)
+ if (Window->Class->style & CS_PARENTDC)
{
Flags |= DCX_PARENTCLIP;
}
Flags = (Flags & ~DCX_CLIPCHILDREN) | DCX_CACHE;
}
- if (!(Window->Style & WS_CHILD) || Window->Parent == NULL)
+ if (NULL == Window || !(Window->Style & WS_CHILD) || NULL == Window->Parent)
{
Flags &= ~DCX_PARENTCLIP;
}
DbgBreakPoint();
}
- if (Dce == NULL)
+ if (NULL == Dce && NULL != Window)
{
- W32kReleaseWindowObject(Window);
+ IntReleaseWindowObject(Window);
return(NULL);
}
Dce->hClipRgn = NULL;
Dce->DCXFlags = DcxFlags | (Flags & DCX_WINDOWPAINT) | DCX_DCEBUSY;
+ if (0 == (Flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN)) && NULL != ClipRegion)
+ {
+ NtGdiDeleteObject(ClipRegion);
+ ClipRegion = NULL;
+ }
+
+ if (NULL != Dce->hClipRgn)
+ {
+ DceDeleteClipRgn(Dce);
+ }
+
+ if (NULL != ClipRegion)
+ {
+ Dce->hClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
+ NtGdiCombineRgn(Dce->hClipRgn, ClipRegion, NULL, RGN_COPY);
+ NtGdiDeleteObject(ClipRegion);
+ }
+
DceSetDrawable(Window, Dce->hDC, Flags, UpdateClipOrigin);
if (UpdateVisRgn)
}
hRgnVisible = DceGetVisRgn(Parent->Self, DcxFlags,
Window->Self, Flags);
- if (Flags & DCX_WINDOW)
- {
- W32kOffsetRgn(hRgnVisible, -Window->WindowRect.left,
- -Window->WindowRect.top);
- }
- else
- {
- W32kOffsetRgn(hRgnVisible, -Window->ClientRect.left,
- -Window->ClientRect.top);
- }
- DceOffsetVisRgn(Dce->hDC, hRgnVisible);
}
else
{
- hRgnVisible = W32kCreateRectRgn(0, 0, 0, 0);
+ hRgnVisible = NtGdiCreateRectRgn(0, 0, 0, 0);
}
}
else
{
- if (hWnd == W32kGetDesktopWindow())
+ if (hWnd == IntGetDesktopWindow())
{
hRgnVisible =
- W32kCreateRectRgn(0, 0,
+ NtGdiCreateRectRgn(0, 0,
NtUserGetSystemMetrics(SM_CXSCREEN),
NtUserGetSystemMetrics(SM_CYSCREEN));
}
else
{
hRgnVisible = DceGetVisRgn(hWnd, Flags, 0, 0);
- DceOffsetVisRgn(Dce->hDC, hRgnVisible);
}
+ }
+
+ if (0 != (Flags & DCX_INTERSECTRGN))
+ {
+ NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hClipRgn, RGN_AND);
+ }
- Dce->DCXFlags &= ~DCX_DCEDIRTY;
- W32kSelectVisRgn(Dce->hDC, hRgnVisible);
+ if (0 != (Flags & DCX_EXCLUDERGN))
+ {
+ NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hClipRgn, RGN_DIFF);
}
- }
- if (Flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN))
- {
- DPRINT1("FIXME.\n");
+ Dce->DCXFlags &= ~DCX_DCEDIRTY;
+ NtGdiSelectVisRgn(Dce->hDC, hRgnVisible);
}
if (hRgnVisible != NULL)
{
- W32kDeleteObject(hRgnVisible);
+ NtGdiDeleteObject(hRgnVisible);
+ }
+ if (NULL != Window)
+ {
+ IntReleaseWindowObject(Window);
}
- W32kReleaseWindowObject(Window);
+
return(Dce->hDC);
}
-BOOL
+BOOL FASTCALL
DCE_InternalDelete(PDCE Dce)
{
PDCE PrevInList;
return NULL != PrevInList;
}
+
+HWND FASTCALL
+IntWindowFromDC(HDC hDc)
+{
+ DCE *Dce;
+ for (Dce = FirstDce; Dce != NULL; Dce = Dce->next)
+ {
+ if(Dce->hDC == hDc)
+ {
+ return Dce->hwndCurrent;
+ }
+ }
+ return 0;
+}
/* EOF */