- Modifed DceUpdateVisRgn to correctly handle situations when DceGetVisRgn returns NULL.

- Fixed the alternative version of VIS_ComputeVisibleRegion and made it the one and only, because it's smaller and faster than the original one.

svn path=/trunk/; revision=8305
This commit is contained in:
Filip Navara 2004-02-22 12:25:35 +00:00
parent 936dffea06
commit 9dacfa1b68
2 changed files with 89 additions and 259 deletions

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: vis.c,v 1.17 2004/02/04 22:55:21 gvg Exp $
* $Id: vis.c,v 1.18 2004/02/22 12:25:34 navaraf Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -34,183 +34,6 @@
#include <win32k/debug1.h>
#include <debug.h>
#if 1
BOOL STATIC FASTCALL
VIS_GetVisRect(PDESKTOP_OBJECT Desktop, PWINDOW_OBJECT Window,
BOOLEAN ClientArea, RECT* Rect)
{
PWINDOW_OBJECT DesktopWindow;
if (ClientArea)
{
*Rect = Window->ClientRect;
}
else
{
*Rect = Window->WindowRect;
}
if (0 == (Window->Style & WS_VISIBLE))
{
NtGdiSetEmptyRect(Rect);
return FALSE;
}
if (Window->Self == Desktop->DesktopWindow)
{
return TRUE;
}
if (0 != (Window->Style & WS_CHILD))
{
do
{
Window = Window->Parent;
if (WS_VISIBLE != (Window->Style & (WS_ICONIC | WS_VISIBLE)))
{
NtGdiSetEmptyRect(Rect);
return FALSE;
}
if (! NtGdiIntersectRect(Rect, Rect, &(Window->ClientRect)))
{
return FALSE;
}
}
while (0 != (Window->Style & WS_CHILD));
}
DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow);
if (NULL == DesktopWindow)
{
ASSERT(FALSE);
return FALSE;
}
if (! NtGdiIntersectRect(Rect, Rect, &(DesktopWindow->ClientRect)))
{
IntReleaseWindowObject(DesktopWindow);
return FALSE;
}
IntReleaseWindowObject(DesktopWindow);
return TRUE;
}
STATIC BOOL FASTCALL
VIS_AddClipRects(PWINDOW_OBJECT Parent, PWINDOW_OBJECT End,
HRGN ClipRgn, PRECT Rect)
{
PWINDOW_OBJECT Child;
RECT Intersect;
ExAcquireFastMutexUnsafe(&Parent->ChildrenListLock);
Child = Parent->FirstChild;
while (Child)
{
if (Child == End)
{
ExReleaseFastMutexUnsafe(&Parent->ChildrenListLock);
return TRUE;
}
if (Child->Style & WS_VISIBLE)
{
if (NtGdiIntersectRect(&Intersect, &Child->WindowRect, Rect))
{
UnsafeIntUnionRectWithRgn(ClipRgn, &Child->WindowRect);
}
}
Child = Child->NextSibling;
}
ExReleaseFastMutexUnsafe(&Parent->ChildrenListLock);
return FALSE;
}
HRGN FASTCALL
VIS_ComputeVisibleRegion(PWINDOW_OBJECT Window,
BOOLEAN ClientArea, BOOLEAN ClipChildren,
BOOLEAN ClipSiblings)
{
HRGN VisRgn;
RECT Rect;
HRGN ClipRgn;
PWINDOW_OBJECT DesktopWindow;
INT LeftOffset, TopOffset;
PDESKTOP_OBJECT Desktop = Window->OwnerThread->Win32Thread->Desktop;
DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow);
if (NULL == DesktopWindow)
{
ASSERT(FALSE);
return NULL;
}
if (VIS_GetVisRect(Desktop, Window, ClientArea, &Rect))
{
VisRgn = UnsafeIntCreateRectRgnIndirect(&Rect);
if (NULL != VisRgn)
{
if (ClientArea)
{
LeftOffset = Window->ClientRect.left;
TopOffset = Window->ClientRect.top;
}
else
{
LeftOffset = Window->WindowRect.left;
TopOffset = Window->WindowRect.top;
}
ClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
if (ClipRgn != NULL)
{
if (ClipChildren && Window->FirstChild)
{
VIS_AddClipRects(Window, NULL, ClipRgn, &Rect);
}
if (ClipSiblings && 0 != (Window->Style & WS_CHILD))
{
VIS_AddClipRects(Window->Parent, Window, ClipRgn, &Rect);
}
while (0 != (Window->Style & WS_CHILD))
{
if (0 != (Window->Style & WS_CLIPSIBLINGS))
{
VIS_AddClipRects(Window->Parent, Window, ClipRgn, &Rect);
}
Window = Window->Parent;
}
VIS_AddClipRects(DesktopWindow, Window, ClipRgn, &Rect);
NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
NtGdiDeleteObject(ClipRgn);
NtGdiOffsetRgn(VisRgn, -LeftOffset, -TopOffset);
}
else
{
NtGdiDeleteObject(VisRgn);
VisRgn = NULL;
}
}
}
else
{
VisRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
}
IntReleaseWindowObject(DesktopWindow);
return VisRgn;
}
#else
HRGN FASTCALL
VIS_ComputeVisibleRegion(
PWINDOW_OBJECT Window,
@ -220,7 +43,7 @@ VIS_ComputeVisibleRegion(
{
HRGN VisRgn, ClipRgn;
INT LeftOffset, TopOffset;
PWINDOW_OBJECT CurrentWindow;
PWINDOW_OBJECT PreviousWindow, CurrentWindow, CurrentSibling;
if (!(Window->Style & WS_VISIBLE))
{
@ -240,6 +63,13 @@ VIS_ComputeVisibleRegion(
TopOffset = Window->WindowRect.top;
}
/*
* Walk through all perent windows and for each clip the visble region
* to the parent's client area and exclude all siblings that are over
* our window.
*/
PreviousWindow = Window;
CurrentWindow = Window->Parent;
while (CurrentWindow)
{
@ -251,6 +81,25 @@ VIS_ComputeVisibleRegion(
ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentWindow->ClientRect);
NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
NtGdiDeleteObject(ClipRgn);
if (ClipSiblings)
{
ExAcquireFastMutexUnsafe(&CurrentWindow->ChildrenListLock);
CurrentSibling = CurrentWindow->FirstChild;
while (CurrentSibling != PreviousWindow)
{
if (CurrentSibling->Style & WS_VISIBLE)
{
ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentSibling->WindowRect);
NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
NtGdiDeleteObject(ClipRgn);
}
CurrentSibling = CurrentSibling->NextSibling;
}
ExReleaseFastMutexUnsafe(&CurrentWindow->ChildrenListLock);
}
PreviousWindow = CurrentWindow;
CurrentWindow = CurrentWindow->Parent;
}
@ -271,28 +120,10 @@ VIS_ComputeVisibleRegion(
ExReleaseFastMutexUnsafe(&Window->ChildrenListLock);
}
if (ClipSiblings && Window->Parent != NULL)
{
ExAcquireFastMutexUnsafe(&Window->Parent->ChildrenListLock);
CurrentWindow = Window->Parent->FirstChild;
while (CurrentWindow != Window)
{
if (CurrentWindow->Style & WS_VISIBLE)
{
ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentWindow->WindowRect);
NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
NtGdiDeleteObject(ClipRgn);
}
CurrentWindow = CurrentWindow->NextSibling;
}
ExReleaseFastMutexUnsafe(&Window->Parent->ChildrenListLock);
}
NtGdiOffsetRgn(VisRgn, -LeftOffset, -TopOffset);
return VisRgn;
}
#endif
VOID FASTCALL
VIS_WindowLayoutChanged(

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: windc.c,v 1.57 2004/02/21 13:13:27 navaraf Exp $
/* $Id: windc.c,v 1.58 2004/02/22 12:25:35 navaraf Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -230,83 +230,82 @@ DceReleaseDC(DCE* dce)
STATIC VOID FASTCALL
DceUpdateVisRgn(DCE *Dce, PWINDOW_OBJECT Window, ULONG Flags)
{
HANDLE hRgnVisible = NULL;
ULONG DcxFlags;
PWINDOW_OBJECT DesktopWindow;
HANDLE hRgnVisible = NULL;
ULONG DcxFlags;
PWINDOW_OBJECT DesktopWindow;
if (Flags & DCX_PARENTCLIP)
{
if (Flags & DCX_PARENTCLIP)
{
PWINDOW_OBJECT Parent;
Parent = Window->Parent;
if (Window->Style & WS_VISIBLE)
{
if (Parent->Style & WS_CLIPSIBLINGS)
{
DcxFlags = DCX_CLIPSIBLINGS |
(Flags & ~(DCX_CLIPCHILDREN | DCX_WINDOW));
}
else
{
DcxFlags = Flags &
~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW);
}
hRgnVisible = DceGetVisRgn(Parent->Self, DcxFlags,
Window->Self, Flags);
if (0 == (Flags & DCX_WINDOW))
{
NtGdiOffsetRgn(hRgnVisible,
Parent->ClientRect.left - Window->ClientRect.left,
Parent->ClientRect.top - Window->ClientRect.top);
}
else
{
NtGdiOffsetRgn(hRgnVisible,
Parent->WindowRect.left - Window->WindowRect.left,
Parent->WindowRect.top - Window->WindowRect.top);
}
}
if (Parent->Style & WS_CLIPSIBLINGS)
{
DcxFlags = DCX_CLIPSIBLINGS |
(Flags & ~(DCX_CLIPCHILDREN | DCX_WINDOW));
}
else
{
hRgnVisible = NtGdiCreateRectRgn(0, 0, 0, 0);
}
}
else if (NULL == Window)
{
{
DcxFlags = Flags & ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW);
}
hRgnVisible = DceGetVisRgn(Parent->Self, DcxFlags, Window->Self, Flags);
if (hRgnVisible == NULL)
{
hRgnVisible = NtGdiCreateRectRgn(0, 0, 0, 0);
}
else
{
if (0 == (Flags & DCX_WINDOW))
{
NtGdiOffsetRgn(
hRgnVisible,
Parent->ClientRect.left - Window->ClientRect.left,
Parent->ClientRect.top - Window->ClientRect.top);
}
else
{
NtGdiOffsetRgn(
hRgnVisible,
Parent->WindowRect.left - Window->WindowRect.left,
Parent->WindowRect.top - Window->WindowRect.top);
}
}
}
else if (Window == NULL)
{
DesktopWindow = IntGetWindowObject(IntGetDesktopWindow());
if (NULL != DesktopWindow)
{
hRgnVisible = UnsafeIntCreateRectRgnIndirect(&DesktopWindow->WindowRect);
IntReleaseWindowObject(DesktopWindow);
}
{
hRgnVisible = UnsafeIntCreateRectRgnIndirect(&DesktopWindow->WindowRect);
IntReleaseWindowObject(DesktopWindow);
}
else
{
hRgnVisible = NULL;
}
}
else
{
{
hRgnVisible = NULL;
}
}
else
{
hRgnVisible = DceGetVisRgn(Window->Self, Flags, 0, 0);
}
}
if (0 != (Flags & DCX_INTERSECTRGN))
{
if (Flags & DCX_INTERSECTRGN)
{
NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hClipRgn, RGN_AND);
}
}
if (0 != (Flags & DCX_EXCLUDERGN))
{
if (Flags & DCX_EXCLUDERGN)
{
NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hClipRgn, RGN_DIFF);
}
}
Dce->DCXFlags &= ~DCX_DCEDIRTY;
NtGdiSelectVisRgn(Dce->hDC, hRgnVisible);
Dce->DCXFlags &= ~DCX_DCEDIRTY;
NtGdiSelectVisRgn(Dce->hDC, hRgnVisible);
if (hRgnVisible != NULL)
{
if (hRgnVisible != NULL)
{
NtGdiDeleteObject(hRgnVisible);
}
}
}
HDC STDCALL