2003-07-17 07:49:15 +00:00
|
|
|
/*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* PURPOSE: Visibility computations
|
2015-11-10 17:41:55 +00:00
|
|
|
* FILE: win32ss/user/ntuser/vis.c
|
2003-07-17 07:49:15 +00:00
|
|
|
* PROGRAMMER: Ge van Geldorp (ge@gse.nl)
|
|
|
|
*/
|
|
|
|
|
2010-04-26 13:58:46 +00:00
|
|
|
#include <win32k.h>
|
2011-08-21 12:38:52 +00:00
|
|
|
DBG_DEFAULT_CHANNEL(UserWinpos);
|
2003-07-17 07:49:15 +00:00
|
|
|
|
2014-09-17 09:54:27 +00:00
|
|
|
PREGION FASTCALL
|
2004-01-17 15:18:25 +00:00
|
|
|
VIS_ComputeVisibleRegion(
|
2010-10-11 03:41:41 +00:00
|
|
|
PWND Wnd,
|
2004-01-17 15:18:25 +00:00
|
|
|
BOOLEAN ClientArea,
|
|
|
|
BOOLEAN ClipChildren,
|
|
|
|
BOOLEAN ClipSiblings)
|
|
|
|
{
|
2014-09-17 09:54:27 +00:00
|
|
|
PREGION VisRgn, ClipRgn;
|
2010-10-11 03:41:41 +00:00
|
|
|
PWND PreviousWindow, CurrentWindow, CurrentSibling;
|
2007-11-15 22:08:13 +00:00
|
|
|
|
2009-07-20 23:18:16 +00:00
|
|
|
if (!Wnd || !(Wnd->style & WS_VISIBLE))
|
2004-01-17 15:18:25 +00:00
|
|
|
{
|
2005-09-19 10:39:26 +00:00
|
|
|
return NULL;
|
2004-01-17 15:18:25 +00:00
|
|
|
}
|
|
|
|
|
2010-01-28 01:00:09 +00:00
|
|
|
VisRgn = NULL;
|
|
|
|
|
2004-01-17 15:18:25 +00:00
|
|
|
if (ClientArea)
|
|
|
|
{
|
2014-09-17 09:54:27 +00:00
|
|
|
VisRgn = IntSysCreateRectpRgnIndirect(&Wnd->rcClient);
|
2007-07-30 02:49:11 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-09-17 09:54:27 +00:00
|
|
|
VisRgn = IntSysCreateRectpRgnIndirect(&Wnd->rcWindow);
|
2004-01-17 15:18:25 +00:00
|
|
|
}
|
2004-03-23 16:32:20 +00:00
|
|
|
|
2004-02-22 12:25:35 +00:00
|
|
|
/*
|
2005-05-08 02:11:54 +00:00
|
|
|
* Walk through all parent windows and for each clip the visble region
|
2004-02-22 12:25:35 +00:00
|
|
|
* to the parent's client area and exclude all siblings that are over
|
|
|
|
* our window.
|
|
|
|
*/
|
|
|
|
|
2010-10-11 03:41:41 +00:00
|
|
|
PreviousWindow = Wnd;
|
|
|
|
CurrentWindow = Wnd->spwndParent;
|
2004-01-17 15:18:25 +00:00
|
|
|
while (CurrentWindow)
|
|
|
|
{
|
2013-11-08 00:26:08 +00:00
|
|
|
if (!VerifyWnd(CurrentWindow))
|
2009-12-14 05:02:56 +00:00
|
|
|
{
|
2013-11-08 00:26:08 +00:00
|
|
|
ERR("ATM the Current Window or Parent is dead! %p\n",CurrentWindow);
|
2014-09-17 09:54:27 +00:00
|
|
|
if (VisRgn)
|
|
|
|
REGION_Delete(VisRgn);
|
2009-12-14 05:02:56 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-10-11 03:41:41 +00:00
|
|
|
if (!(CurrentWindow->style & WS_VISIBLE))
|
2004-01-17 15:18:25 +00:00
|
|
|
{
|
2014-09-17 09:54:27 +00:00
|
|
|
if (VisRgn)
|
|
|
|
REGION_Delete(VisRgn);
|
2005-09-19 10:39:26 +00:00
|
|
|
return NULL;
|
2004-01-17 15:18:25 +00:00
|
|
|
}
|
2005-09-19 10:39:26 +00:00
|
|
|
|
2014-09-17 09:54:27 +00:00
|
|
|
ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentWindow->rcClient);
|
|
|
|
IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
|
|
|
|
REGION_Delete(ClipRgn);
|
2004-02-22 12:25:35 +00:00
|
|
|
|
2010-10-11 03:41:41 +00:00
|
|
|
if ((PreviousWindow->style & WS_CLIPSIBLINGS) ||
|
|
|
|
(PreviousWindow == Wnd && ClipSiblings))
|
2004-02-22 12:25:35 +00:00
|
|
|
{
|
2009-12-14 05:02:56 +00:00
|
|
|
CurrentSibling = CurrentWindow->spwndChild;
|
[WIN32K]
Rewrite of the GDI handle manager
- The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive
and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It
is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability.
- Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also
much faster and uses much less memory.
- Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs.
- Allow allcoating objects without a handle and insert them into the handle table later
- Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles.
- Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track
possible leaks
- Make sure that all objects of a process are deleted in cleanup
- Make sure all usermode memory allocations are freed, when cleaning up the process pool.
- Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture)
- Fix some object / reference leaks
- Lots of inferface improvements
- Use global variables for certain things instead of members in the mapped gdi handle table
- Make IntSysCreateRectpRgn create a region without a handle
- Fix detection od source and mask use in GreStretchBltMask
- Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks
- Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always
- Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool
- Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway,
- Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter
- Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid
- Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure
svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
|
|
|
while ( CurrentSibling != NULL &&
|
2010-10-11 03:41:41 +00:00
|
|
|
CurrentSibling != PreviousWindow )
|
2004-02-22 12:25:35 +00:00
|
|
|
{
|
2010-10-11 03:41:41 +00:00
|
|
|
if ((CurrentSibling->style & WS_VISIBLE) &&
|
|
|
|
!(CurrentSibling->ExStyle & WS_EX_TRANSPARENT))
|
2004-02-22 12:25:35 +00:00
|
|
|
{
|
2014-09-17 09:54:27 +00:00
|
|
|
ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentSibling->rcWindow);
|
2004-03-23 16:32:20 +00:00
|
|
|
/* Combine it with the window region if available */
|
2010-10-11 03:41:41 +00:00
|
|
|
if (CurrentSibling->hrgnClip && !(CurrentSibling->style & WS_MINIMIZE))
|
2004-03-23 16:32:20 +00:00
|
|
|
{
|
2014-12-19 10:34:52 +00:00
|
|
|
PREGION SiblingClipRgn = REGION_LockRgn(CurrentSibling->hrgnClip);
|
2014-09-17 09:54:27 +00:00
|
|
|
if (SiblingClipRgn)
|
|
|
|
{
|
2014-12-18 08:12:41 +00:00
|
|
|
REGION_bOffsetRgn(ClipRgn, -CurrentSibling->rcWindow.left, -CurrentSibling->rcWindow.top);
|
2014-09-17 09:54:27 +00:00
|
|
|
IntGdiCombineRgn(ClipRgn, ClipRgn, SiblingClipRgn, RGN_AND);
|
2014-12-18 08:12:41 +00:00
|
|
|
REGION_bOffsetRgn(ClipRgn, CurrentSibling->rcWindow.left, CurrentSibling->rcWindow.top);
|
2014-12-19 10:34:52 +00:00
|
|
|
REGION_UnlockRgn(SiblingClipRgn);
|
2014-09-17 09:54:27 +00:00
|
|
|
}
|
2004-03-23 16:32:20 +00:00
|
|
|
}
|
2014-09-17 09:54:27 +00:00
|
|
|
IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
|
|
|
|
REGION_Delete(ClipRgn);
|
2004-02-22 12:25:35 +00:00
|
|
|
}
|
2009-12-14 05:02:56 +00:00
|
|
|
CurrentSibling = CurrentSibling->spwndNext;
|
2004-02-22 12:25:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PreviousWindow = CurrentWindow;
|
2009-12-14 05:02:56 +00:00
|
|
|
CurrentWindow = CurrentWindow->spwndParent;
|
2004-01-17 15:18:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ClipChildren)
|
|
|
|
{
|
2010-10-11 03:41:41 +00:00
|
|
|
CurrentWindow = Wnd->spwndChild;
|
|
|
|
while (CurrentWindow)
|
2004-01-17 15:18:25 +00:00
|
|
|
{
|
2010-10-11 03:41:41 +00:00
|
|
|
if ((CurrentWindow->style & WS_VISIBLE) &&
|
|
|
|
!(CurrentWindow->ExStyle & WS_EX_TRANSPARENT))
|
2004-01-17 15:18:25 +00:00
|
|
|
{
|
2014-09-17 09:54:27 +00:00
|
|
|
ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentWindow->rcWindow);
|
2004-03-23 16:32:20 +00:00
|
|
|
/* Combine it with the window region if available */
|
2010-10-11 03:41:41 +00:00
|
|
|
if (CurrentWindow->hrgnClip && !(CurrentWindow->style & WS_MINIMIZE))
|
2004-03-23 16:32:20 +00:00
|
|
|
{
|
2014-12-19 10:34:52 +00:00
|
|
|
PREGION CurrentRgnClip = REGION_LockRgn(CurrentWindow->hrgnClip);
|
2014-09-17 09:54:27 +00:00
|
|
|
if (CurrentRgnClip)
|
|
|
|
{
|
2014-12-18 08:12:41 +00:00
|
|
|
REGION_bOffsetRgn(ClipRgn, -CurrentWindow->rcWindow.left, -CurrentWindow->rcWindow.top);
|
2014-09-17 09:54:27 +00:00
|
|
|
IntGdiCombineRgn(ClipRgn, ClipRgn, CurrentRgnClip, RGN_AND);
|
2014-12-18 08:12:41 +00:00
|
|
|
REGION_bOffsetRgn(ClipRgn, CurrentWindow->rcWindow.left, CurrentWindow->rcWindow.top);
|
2014-12-19 10:34:52 +00:00
|
|
|
REGION_UnlockRgn(CurrentRgnClip);
|
2014-09-17 09:54:27 +00:00
|
|
|
}
|
2004-03-23 16:32:20 +00:00
|
|
|
}
|
2014-09-17 09:54:27 +00:00
|
|
|
IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
|
|
|
|
REGION_Delete(ClipRgn);
|
2004-01-17 15:18:25 +00:00
|
|
|
}
|
2009-12-14 05:02:56 +00:00
|
|
|
CurrentWindow = CurrentWindow->spwndNext;
|
2004-01-17 15:18:25 +00:00
|
|
|
}
|
|
|
|
}
|
2005-05-08 02:11:54 +00:00
|
|
|
|
2010-10-11 03:41:41 +00:00
|
|
|
if (Wnd->hrgnClip && !(Wnd->style & WS_MINIMIZE))
|
2004-03-23 16:32:20 +00:00
|
|
|
{
|
2014-12-19 10:34:52 +00:00
|
|
|
PREGION WndRgnClip = REGION_LockRgn(Wnd->hrgnClip);
|
2014-09-17 09:54:27 +00:00
|
|
|
if (WndRgnClip)
|
|
|
|
{
|
2014-12-18 08:12:41 +00:00
|
|
|
REGION_bOffsetRgn(VisRgn, -Wnd->rcWindow.left, -Wnd->rcWindow.top);
|
2014-09-17 09:54:27 +00:00
|
|
|
IntGdiCombineRgn(VisRgn, VisRgn, WndRgnClip, RGN_AND);
|
2014-12-18 08:12:41 +00:00
|
|
|
REGION_bOffsetRgn(VisRgn, Wnd->rcWindow.left, Wnd->rcWindow.top);
|
2014-12-19 10:34:52 +00:00
|
|
|
REGION_UnlockRgn(WndRgnClip);
|
2014-09-17 09:54:27 +00:00
|
|
|
}
|
2004-03-23 16:32:20 +00:00
|
|
|
}
|
2005-05-08 02:11:54 +00:00
|
|
|
|
2004-01-17 15:18:25 +00:00
|
|
|
return VisRgn;
|
|
|
|
}
|
2003-07-17 07:49:15 +00:00
|
|
|
|
|
|
|
VOID FASTCALL
|
2005-09-05 21:19:23 +00:00
|
|
|
co_VIS_WindowLayoutChanged(
|
2010-10-11 03:41:41 +00:00
|
|
|
PWND Wnd,
|
2014-09-17 09:54:27 +00:00
|
|
|
PREGION NewlyExposed)
|
2003-07-17 07:49:15 +00:00
|
|
|
{
|
2010-10-11 03:41:41 +00:00
|
|
|
PWND Parent;
|
2005-10-15 13:22:13 +00:00
|
|
|
USER_REFERENCE_ENTRY Ref;
|
2005-09-06 14:19:03 +00:00
|
|
|
|
2010-10-11 03:41:41 +00:00
|
|
|
ASSERT_REFS_CO(Wnd);
|
2007-11-15 22:08:13 +00:00
|
|
|
|
2010-10-11 03:41:41 +00:00
|
|
|
Parent = Wnd->spwndParent;
|
2004-02-24 01:30:58 +00:00
|
|
|
if(Parent)
|
2003-12-27 15:09:51 +00:00
|
|
|
{
|
2014-09-17 09:54:27 +00:00
|
|
|
PREGION TempRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
|
|
|
|
|
|
|
|
if (!TempRgn)
|
|
|
|
return;
|
2011-06-18 12:41:29 +00:00
|
|
|
|
2014-09-17 09:54:27 +00:00
|
|
|
IntGdiCombineRgn(TempRgn, NewlyExposed, NULL, RGN_COPY);
|
2014-12-18 08:12:41 +00:00
|
|
|
REGION_bOffsetRgn(TempRgn,
|
2014-12-18 08:12:34 +00:00
|
|
|
Wnd->rcWindow.left - Parent->rcClient.left,
|
|
|
|
Wnd->rcWindow.top - Parent->rcClient.top);
|
2005-09-07 21:25:42 +00:00
|
|
|
|
2014-09-17 09:54:27 +00:00
|
|
|
UserRefObjectCo(Parent, &Ref);
|
|
|
|
co_UserRedrawWindow(Parent, NULL, TempRgn,
|
|
|
|
RDW_FRAME | RDW_ERASE | RDW_INVALIDATE |
|
|
|
|
RDW_ALLCHILDREN);
|
|
|
|
UserDerefObjectCo(Parent);
|
2011-06-18 12:41:29 +00:00
|
|
|
|
2014-09-17 09:54:27 +00:00
|
|
|
REGION_Delete(TempRgn);
|
2004-02-26 22:23:55 +00:00
|
|
|
}
|
2003-07-17 07:49:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|