mirror of
https://github.com/reactos/reactos.git
synced 2024-09-06 19:02:32 +00:00
160 lines
4.7 KiB
C
160 lines
4.7 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS kernel
|
|
* PURPOSE: Visibility computations
|
|
* FILE: subsys/win32k/ntuser/vis.c
|
|
* PROGRAMMER: Ge van Geldorp (ge@gse.nl)
|
|
*/
|
|
|
|
#include <win32k.h>
|
|
DBG_DEFAULT_CHANNEL(UserWinpos);
|
|
|
|
HRGN FASTCALL
|
|
VIS_ComputeVisibleRegion(
|
|
PWND Wnd,
|
|
BOOLEAN ClientArea,
|
|
BOOLEAN ClipChildren,
|
|
BOOLEAN ClipSiblings)
|
|
{
|
|
HRGN VisRgn, ClipRgn;
|
|
PWND PreviousWindow, CurrentWindow, CurrentSibling;
|
|
|
|
if (!Wnd || !(Wnd->style & WS_VISIBLE))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
VisRgn = NULL;
|
|
|
|
if (ClientArea)
|
|
{
|
|
VisRgn = IntSysCreateRectRgnIndirect(&Wnd->rcClient);
|
|
}
|
|
else
|
|
{
|
|
VisRgn = IntSysCreateRectRgnIndirect(&Wnd->rcWindow);
|
|
}
|
|
|
|
/*
|
|
* Walk through all parent windows and for each clip the visble region
|
|
* to the parent's client area and exclude all siblings that are over
|
|
* our window.
|
|
*/
|
|
|
|
PreviousWindow = Wnd;
|
|
CurrentWindow = Wnd->spwndParent;
|
|
while (CurrentWindow)
|
|
{
|
|
if ( CurrentWindow->state2 & WNDS2_INDESTROY ||
|
|
CurrentWindow->state & WNDS_DESTROYED )
|
|
{
|
|
ERR("ATM the Current Window or Parent is dead!\n");
|
|
if (VisRgn) GreDeleteObject(VisRgn);
|
|
return NULL;
|
|
}
|
|
|
|
if (!(CurrentWindow->style & WS_VISIBLE))
|
|
{
|
|
if (VisRgn) GreDeleteObject(VisRgn);
|
|
return NULL;
|
|
}
|
|
|
|
ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWindow->rcClient);
|
|
NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
|
|
GreDeleteObject(ClipRgn);
|
|
|
|
if ((PreviousWindow->style & WS_CLIPSIBLINGS) ||
|
|
(PreviousWindow == Wnd && ClipSiblings))
|
|
{
|
|
CurrentSibling = CurrentWindow->spwndChild;
|
|
while ( CurrentSibling != NULL &&
|
|
CurrentSibling != PreviousWindow )
|
|
{
|
|
if ((CurrentSibling->style & WS_VISIBLE) &&
|
|
!(CurrentSibling->ExStyle & WS_EX_TRANSPARENT))
|
|
{
|
|
ClipRgn = IntSysCreateRectRgnIndirect(&CurrentSibling->rcWindow);
|
|
/* Combine it with the window region if available */
|
|
if (CurrentSibling->hrgnClip && !(CurrentSibling->style & WS_MINIMIZE))
|
|
{
|
|
NtGdiOffsetRgn(ClipRgn, -CurrentSibling->rcWindow.left, -CurrentSibling->rcWindow.top);
|
|
NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentSibling->hrgnClip, RGN_AND);
|
|
NtGdiOffsetRgn(ClipRgn, CurrentSibling->rcWindow.left, CurrentSibling->rcWindow.top);
|
|
}
|
|
NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
|
|
GreDeleteObject(ClipRgn);
|
|
}
|
|
CurrentSibling = CurrentSibling->spwndNext;
|
|
}
|
|
}
|
|
|
|
PreviousWindow = CurrentWindow;
|
|
CurrentWindow = CurrentWindow->spwndParent;
|
|
}
|
|
|
|
if (ClipChildren)
|
|
{
|
|
CurrentWindow = Wnd->spwndChild;
|
|
while (CurrentWindow)
|
|
{
|
|
if ((CurrentWindow->style & WS_VISIBLE) &&
|
|
!(CurrentWindow->ExStyle & WS_EX_TRANSPARENT))
|
|
{
|
|
ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWindow->rcWindow);
|
|
/* Combine it with the window region if available */
|
|
if (CurrentWindow->hrgnClip && !(CurrentWindow->style & WS_MINIMIZE))
|
|
{
|
|
NtGdiOffsetRgn(ClipRgn, -CurrentWindow->rcWindow.left, -CurrentWindow->rcWindow.top);
|
|
NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentWindow->hrgnClip, RGN_AND);
|
|
NtGdiOffsetRgn(ClipRgn, CurrentWindow->rcWindow.left, CurrentWindow->rcWindow.top);
|
|
}
|
|
NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
|
|
GreDeleteObject(ClipRgn);
|
|
}
|
|
CurrentWindow = CurrentWindow->spwndNext;
|
|
}
|
|
}
|
|
|
|
if (Wnd->hrgnClip && !(Wnd->style & WS_MINIMIZE))
|
|
{
|
|
NtGdiOffsetRgn(VisRgn, -Wnd->rcWindow.left, -Wnd->rcWindow.top);
|
|
NtGdiCombineRgn(VisRgn, VisRgn, Wnd->hrgnClip, RGN_AND);
|
|
NtGdiOffsetRgn(VisRgn, Wnd->rcWindow.left, Wnd->rcWindow.top);
|
|
}
|
|
|
|
return VisRgn;
|
|
}
|
|
|
|
VOID FASTCALL
|
|
co_VIS_WindowLayoutChanged(
|
|
PWND Wnd,
|
|
HRGN NewlyExposed)
|
|
{
|
|
HRGN Temp;
|
|
PWND Parent;
|
|
USER_REFERENCE_ENTRY Ref;
|
|
|
|
ASSERT_REFS_CO(Wnd);
|
|
|
|
Parent = Wnd->spwndParent;
|
|
if(Parent)
|
|
{
|
|
Temp = IntSysCreateRectRgn(0, 0, 0, 0);
|
|
|
|
NtGdiCombineRgn(Temp, NewlyExposed, NULL, RGN_COPY);
|
|
NtGdiOffsetRgn(Temp,
|
|
Wnd->rcWindow.left - Parent->rcClient.left,
|
|
Wnd->rcWindow.top - Parent->rcClient.top);
|
|
|
|
UserRefObjectCo(Parent, &Ref);
|
|
co_UserRedrawWindow(Parent, NULL, Temp,
|
|
RDW_FRAME | RDW_ERASE | RDW_INVALIDATE |
|
|
RDW_ALLCHILDREN);
|
|
UserDerefObjectCo(Parent);
|
|
|
|
GreDeleteObject(Temp);
|
|
}
|
|
}
|
|
|
|
/* EOF */
|