Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1316 lines
36 KiB

/******************************Module*Header*******************************\
* Module Name: curseng.cxx *
* *
* Engine cursor support. These routines are only called by USER to *
* set the cursor shape and move it about the screen. This is not the *
* engine simulation of the pointer. *
* *
* Created: 18-Mar-1991 11:39:40 *
* Author: Tue 12-May-1992 01:49:04 -by- Charles Whitmer [chuckwh] *
* *
* Copyright (c) 1991 Microsoft Corporation *
\**************************************************************************/
#include "precomp.hxx"
BOOL SimSetPointerShape
(
SURFOBJ*,
SURFOBJ*,
SURFOBJ*,
XLATEOBJ*,
LONG,
LONG,
LONG,
LONG,
RECTL*,
FLONG
);
VOID SimMovePointer(SURFOBJ *pso,LONG x,LONG y,RECTL *prcl);
/******************************Public*Routine******************************\
* GreSetPointer
*
* Set the cursor shape, position and hot spot.
*
* History:
* Sun 09-Aug-1992 -by- Patrick Haluptzok [patrickh]
* add engine pointer simulations, validate data from USER.
*
* Tue 12-May-1992 01:49:04 -by- Charles Whitmer [chuckwh]
* Wrote it.
\**************************************************************************/
VOID GreSetPointer(HDEV hdev, PCURSINFO pci, ULONG fl)
{
PDEVOBJ po(hdev);
if (po.bDisabled())
return;
fl &= (SPS_ANIMATESTART | SPS_ANIMATEUPDATE);
//
// Perhaps we're being told to tear the pointer down. Just move it off the
// surface.
//
if (pci == (PCURSINFO) NULL)
{
VACQUIREDEVLOCK(po.pDevLock());
{
MUTEXOBJ mutP(po.pfmPointer());
if (!po.bPtrHidden())
{
po.pfnMove()(po.pSurface()->pSurfobj(),-1,-1,NULL); // Hide it.
//
// bPtrHidden is basically bPtrEnabled. This is the only place
// that sets the cursor to being hidden.
//
po.bPtrHidden(TRUE);
po.bPtrDirectDrawOccluded(FALSE);
}
}
VRELEASEDEVLOCK(po.pDevLock());
return;
}
//
// OK, now we have some serious work to be done. We have to have a mask.
// Lock down and validate the cursor.
//
SURFREF soMask((HSURF) pci->hbmMask);
if (!soMask.bValid() || (soMask.ps->iFormat() != BMF_1BPP))
{
WARNING("GreSetPointer failed because of invalid cursor handle\n");
return;
}
//
// Check that mask is even height.
//
if (soMask.ps->sizl().cy & 0x0001)
{
WARNING("GreSetPointer failed odd height mask\n");
return;
}
//
// We may have color.
//
XEPALOBJ palSrc;
XEPALOBJ palDisp;
XEPALOBJ palDispDC(ppalDefault);
SURFACE *psoColor = (SURFACE *) NULL;
//
// Lock the target surface and realize the color translation object.
// If soColor is invalid, this will produce the identity object.
//
XLATEOBJ *pxlo = NULL;
EXLATEOBJ xlo;
SURFREF soColor;
PPALETTE ppalSrc;
//
// We'll have to wait for drawing to complete before the change.
// So we wait for both semaphores.
//
// Note that we don't attempt to change the shape asynchronously,
// even if the driver sets GCAPS_ASYNCCHANGE.
//
DEVLOCKOBJ dlo(po);
{
//
// We can reference pSurface() only once the Devlock is acquired,
// for dynamic mode changing.
//
SURFACE* pSurfDisp = po.pSurface();
if (pci->hbmColor)
{
soColor.vAltCheckLock((HSURF) pci->hbmColor);
if (soColor.bValid())
{
if (soColor.ps->sizl().cy != (soMask.ps->sizl().cy >> 1))
{
WARNING("GreSetPointer failed color not half height mask\n");
return;
}
PPALETTE ppalSrc;
if (!bIsCompatible(&ppalSrc, soColor.ps->ppal(), soColor.ps, po.hdev()))
{
WARNING1("GreSetPointer failed - bitmap not compatible with surface\n");
return;
}
palSrc.ppalSet(ppalSrc);
palDisp.ppalSet(pSurfDisp->ppal());
if (xlo.bInitXlateObj(
(PCOLORXFORM)NULL,
palSrc,
palDisp,
palDispDC,
palDispDC,
0x000000L,
0xFFFFFFL,
0
))
{
pxlo = xlo.pxlo();
psoColor = soColor.ps;
}
}
}
ULONG iMode;
MUTEXOBJ mutP(po.pfmPointer());
LONG lInitX, lInitY;
BOOL bDirectDrawOccluded;
LONG xPointer, yPointer;
if (!po.bDisabled())
{
//
// We can't allow a software pointer to be drawn if it will
// intersect a region of the screen locked by a DirectDraw
// application. Unfortunately, the DrvSetPointerShape call
// implicitly expects the pointer to be drawn even if the
// driver returns SPS_ACCEPT_EXCLUDE (which implies a software
// pointer). Consequently, if it looks like the pointer might
// overlap a DirectDraw lock, we tell the driver to create it
// hidden; then, if it turns out the driver returned
// SPS_ACCEPT_NOEXCLUDE (meaning it's a hardware pointer), we
// can turn the pointer back on by making a call to
// DrvMovePointer.
//
// The actual pointer height is always half the mask height.
// Note that the size of the bitmap is almost always larger
// than the actual bits contained -- we could trim the size
// of 'rclPointerOffset' as a result. However, it's the
// SimSetPointerShape call that usually returns this
// information to us, and since we haven't called it yet, we
// don't know what the trimmed size would be! Plus,
// SimSetPointerShape doesn't returned the trimmed size
// information if the pointer is created invisible.
//
po.rclPointerOffset().left = -pci->xHotspot;
po.rclPointerOffset().right = -pci->xHotspot
+ (soMask.ps->sizl().cx);
po.rclPointerOffset().top = -pci->yHotspot;
po.rclPointerOffset().bottom = -pci->yHotspot
+ (soMask.ps->sizl().cy >> 1);
bDirectDrawOccluded = bDdPointerNeedsOccluding(po.hdev());
if (bDirectDrawOccluded)
{
po.bPtrDirectDrawOccluded(TRUE);
xPointer = -1;
yPointer = -1;
}
else
{
po.bPtrDirectDrawOccluded(FALSE);
xPointer = po.ptlPointer().x;
yPointer = po.ptlPointer().y;
}
//
// Ask the driver if it can support the new shape. We give it an
// invisible location if engine is simulating so if driver rejects
// engine can replace it without flash. If driver does accept we
// remove the engine cursor (flash) and then
// have driver move pointer to correct position.
//
if (po.bPtrSim())
{
lInitX = -1;
lInitY = -1;
}
else
{
lInitX = xPointer;
lInitY = yPointer;
}
if (po.pfnDrvShape())
{
iMode = po.pfnDrvShape()
(
pSurfDisp->pSurfobj(),
soMask.pSurfobj(),
psoColor->pSurfobj(),
pxlo,
pci->xHotspot,
pci->yHotspot,
lInitX,
lInitY,
(lInitX != -1) ? &po.rclPointer() : NULL,
SPS_CHANGE | fl
);
}
else
{
iMode = SPS_DECLINE;
}
//
// If the driver takes it, just finish up.
//
po.bPtrNeedsExcluding(iMode != SPS_ACCEPT_NOEXCLUDE);
if ((iMode == SPS_ACCEPT_EXCLUDE) ||
(iMode == SPS_ACCEPT_NOEXCLUDE))
{
ASSERTGDI(po.pfnDrvMove(),"pfnDrvMove is invalid (NULL)");
if (po.bPtrSim())
{
//
// Remove engine simulated pointer.
//
SimSetPointerShape(pSurfDisp->pSurfobj(),NULL,NULL,NULL,
0,0,0,0,NULL,SPS_CHANGE | fl);
}
if ((po.bPtrSim() && !bDirectDrawOccluded) ||
((iMode == SPS_ACCEPT_NOEXCLUDE) && (bDirectDrawOccluded)))
{
//
// Unhide the pointer if it was created hidden and no
// longer has to be.
//
po.bPtrDirectDrawOccluded(FALSE);
po.pfnDrvMove()(pSurfDisp->pSurfobj(),
po.ptlPointer().x,
po.ptlPointer().y,
&po.rclPointer());
}
po.pfnMove(po.pfnDrvMove());
po.bPtrHidden(FALSE);
po.bPtrSim(FALSE);
}
else
{
//
// Let the GDI simulations do it.
//
po.pfnMove(SimMovePointer);
iMode = SimSetPointerShape
(
pSurfDisp->pSurfobj(),
soMask.pSurfobj(),
psoColor->pSurfobj(),
pxlo,
pci->xHotspot,
pci->yHotspot,
xPointer,
yPointer,
(xPointer != -1) ? &po.rclPointer() : NULL,
SPS_CHANGE | fl
);
//
// Finish up.
//
if (iMode != SPS_ERROR)
{
po.bPtrHidden(FALSE);
po.bPtrSim(TRUE);
}
else
{
po.bPtrHidden(TRUE);
}
}
}
}
}
/******************************Public*Routine******************************\
* GreMovePointer (hdev,x,y)
*
* Move the Pointer to the specified location. This is called only by
* USER.
*
* History:
* Thu 14-Apr-1994 -by- Patrick Haluptzok [patrickh]
* Optimize / make Async pointers work
*
* Tue 12-May-1992 02:11:51 -by- Charles Whitmer [chuckwh]
* Wrote it.
\**************************************************************************/
VOID GreMovePointer(HDEV hdev,int x,int y)
{
BOOL bUnlockBoth = FALSE;
RECTL *prcl;
PDEVOBJ po(hdev);
PFN_DrvMovePointer pfnMove;
SURFOBJ *pso;
if (po.bValid())
{
if (po.bDisabled())
{
return;
}
ASSERTGDI(x != -1, "ERROR GreMovePointer X invalid");
ASSERTGDI(y != -1, "ERROR GreMovePointer Y invalid");
//
// If the driver has indicated it has bAsyncPointerMove capabilities
// and it currently is managing the pointer, and the pointer is
// supported in hardware so it doesn't need to be excluded
// (indicated by bPtrNeedsExcluding) then we only need to grab the pointer
// mutex which is only grabbed by people trying to make the pointer
// shape change and a few other odd ball places.
//
// Otherwise we grab the DEVLOCK and the pointer mutex which
// ensures nobody else is drawing, changing the pointer shape,
// etc.
//
if (po.bAsyncPointerMove() &&
!po.bPtrNeedsExcluding())
{
AcquireGreResource(po.pfmPointer());
//
// Make sure we really got it, bPtrNeedsExcluding may
// change if you don't hold the DEVLOCK or
// the POINTER mutex.
//
if (po.bPtrNeedsExcluding())
{
//
// Release and regrab everything, for sure
// we are safe with both of them.
//
ReleaseGreResource(po.pfmPointer());
VACQUIREDEVLOCK(po.pDevLock());
AcquireGreResource(po.pfmPointer());
bUnlockBoth = TRUE;
}
}
else
{
VACQUIREDEVLOCK(po.pDevLock());
AcquireGreResource(po.pfmPointer());
bUnlockBoth = TRUE;
}
//
// bDisabled can't change with pDevLock and pfmPointer both held.
// bPtrHidden can't change unless pfmPointer is held if the
// pointer is currently Async and the device supports Async movement.
// Otherwise pDevLock and bPtrHidden both would be held to
// change bPtrHidden.
//
if ((po.ptlPointer().x != x) ||
(po.ptlPointer().y != y))
{
po.ptlPointer(x,y);
if (!po.bDisabled())
{
pso = po.pSurface()->pSurfobj();
prcl = po.bPtrNeedsExcluding() ? &po.rclPointer() : NULL;
if (!po.bPtrHidden())
{
if (po.bPtrNeedsExcluding())
{
//
// bDdCalculatePointerExclusions returns TRUE if the
// pointer should be excluded because of DirectDraw.
//
if (bDdPointerNeedsOccluding(po.hdev()))
{
if (!po.bPtrDirectDrawOccluded())
{
//
// The pointer has moved such that it now
// intersects with a DirectDraw locked region.
// Consequently, call the driver to turn it off.
//
po.bPtrDirectDrawOccluded(TRUE);
po.pfnMove()(pso, -1, -1, NULL);
}
}
else
{
po.bPtrDirectDrawOccluded(FALSE);
po.pfnMove()(pso, x, y, prcl);
}
}
else
{
po.pfnMove()(pso, x, y, prcl);
}
}
if (po.flGraphicsCaps() & GCAPS_PANNING)
{
//
// The driver wants to be notified of the pointer
// position even if a pointer isn't actually visible
// (invisible panning!). Let it know the pointer is
// still turned off by giving it a negative 'y':
//
po.pfnDrvMove()(pso,
x,
y - pso->sizlBitmap.cy,
NULL);
}
}
}
else
{
WARNING1("GreMovePointer called but position didn't change\n");
}
ReleaseGreResource(po.pfmPointer());
if (bUnlockBoth)
{
VRELEASEDEVLOCK(po.pDevLock());
}
}
}
/******************************Public*Routine******************************\
* vExclude (hdev,prcl,pco)
*
* Does the work for the DEVEXCLUDEOBJ constructors.
*
* 1) Obtains the hardware semaphore, if needed.
* 2) Asks the driver to take down the pointer if it collides with the
* drawing area.
* 3) Sets a timer for bringing up an excluded pointer.
*
* Thu 14-Apr-1994 -by- Patrick Haluptzok [patrickh]
* Optimize / make Async pointers work
*
* Mon 24-Aug-1992 -by- Patrick Haluptzok [patrickh]
* Add drag rect exclusion.
*
* Thu 07-May-1992 19:32:06 -by- Charles Whitmer [chuckwh]
* Wrote it.
\**************************************************************************/
VOID DEVEXCLUDEOBJ::vExclude(HDEV hdev_,RECTL *prcl,ECLIPOBJ *pco)
{
bRedrawDragRect = FALSE;
bRedrawCursor = FALSE;
PDEVOBJ po(hdev_);
//
// If the pointer is hidden or handled in hardware, there's nothing to do.
//
if (po.bPtrNeedsExcluding() &&
!po.bPtrHidden() &&
!po.bPtrDirectDrawOccluded())
{
//
// See if we need to tear down the pointer because
// the pointer lies where we want to draw.
//
if (
(prcl->bottom > po.rclPointer().top) &&
(prcl->right > po.rclPointer().left) &&
(prcl->left < po.rclPointer().right) &&
(prcl->top < po.rclPointer().bottom) &&
(pco == NULL ||
pco->bInside(&po.rclPointer()) == REGION_RECT_INTERSECT)
)
{
//
// Setting hdev to be non-zero let's us know we have to
// put the pointer back on the screen when we hit the
// destructor.
//
hdev = hdev_;
bRedrawCursor = TRUE;
//
// We know we can move it off the screen because the
// GreMovePointer must grab pDevLock given the conditions
// above we just checked, and the conditions above can't
// change without holding the pDevLock.
//
po.pfnMove()(po.pSurface()->pSurfobj(),-1,-1,NULL);
}
}
if (po.bHaveDragRect())
{
vTearDownDragRect(hdev_, prcl);
}
}
VOID DEVEXCLUDEOBJ::vExclude2
(
HDEV hdev_,
RECTL *prcl,
ECLIPOBJ *pco,
POINTL *pptl
)
{
bRedrawDragRect = 0;
bRedrawCursor = FALSE;
RECTL rclOffset;
PDEVOBJ po(hdev_);
//
// If the pointer is hidden or handled in hardware, there's nothing to do.
//
if (po.bPtrNeedsExcluding() &&
!po.bPtrHidden() &&
!po.bPtrDirectDrawOccluded())
{
//
// Calculate an offset version of the pointer rectangle.
//
rclOffset.top = po.rclPointer().top + pptl->y;
rclOffset.left = po.rclPointer().left + pptl->x;
rclOffset.right = po.rclPointer().right + pptl->x;
rclOffset.bottom = po.rclPointer().bottom + pptl->y;
//
// See if we need to tear down the pointer because
// the pointer lies where we want to draw.
//
if (
(prcl->bottom > po.rclPointer().top) &&
(prcl->right > po.rclPointer().left) &&
(prcl->left < po.rclPointer().right) &&
(prcl->top < po.rclPointer().bottom) &&
(
(pco == (ECLIPOBJ *) NULL) ||
(pco->bInside(&po.rclPointer()) == REGION_RECT_INTERSECT) ||
(pco->bInside(&rclOffset) == REGION_RECT_INTERSECT)
)
)
{
//
// Tear it down.
//
// Setting hdev to be non-zero let's us know we have to
// something in the destructor.
//
hdev = hdev_;
bRedrawCursor = TRUE;
//
// We know we can move it off the screen because the
// GreMovePointer must grab pDevLock given the conditions
// above we just checked, and the conditions above can't
// change without holding the pDevLock.
//
po.pfnMove()(po.pSurface()->pSurfobj(),-1,-1,NULL);
}
}
if (po.bHaveDragRect())
{
vTearDownDragRect(hdev_, prcl);
}
}
/******************************Public*Routine******************************\
* ULONG cIntersect
*
* This routine takes a list of rectangles from 'prclIn' and clips them
* in-place to the rectangle 'prclClip'. The input rectangles don't
* have to intersect 'prclClip'; the return value will reflect the
* number of input rectangles that did intersect, and the intersecting
* rectangles will be densely packed.
*
\**************************************************************************/
ULONG cIntersect(
RECTL* prclClip,
RECTL* prclIn, // List of rectangles
LONG c) // Can be zero
{
ULONG cIntersections;
RECTL* prclOut;
cIntersections = 0;
prclOut = prclIn;
for (; c != 0; prclIn++, c--)
{
prclOut->left = max(prclIn->left, prclClip->left);
prclOut->right = min(prclIn->right, prclClip->right);
if (prclOut->left < prclOut->right)
{
prclOut->top = max(prclIn->top, prclClip->top);
prclOut->bottom = min(prclIn->bottom, prclClip->bottom);
if (prclOut->top < prclOut->bottom)
{
prclOut++;
cIntersections++;
}
}
}
return(cIntersections);
}
/******************************Public*Routine******************************\
* BOOL bDrawDragRectangles
*
* Creates a list of rectangles describing the drag rect, sticks them in
* 'po.prclRedraw()' and then draws them.
*
* Note: Devlock must already have been acquired.
*
\**************************************************************************/
BOOL bDrawDragRectangles(
PDEVOBJ& po,
ERECTL *prclClip)
{
ULONG ulDimension;
ULONG crclTemp;
ULONG i;
RECTL arclTemp[4];
REGION* prgn;
ECLIPOBJ eco;
ECLIPOBJ* pco;
ERECTL rclClip;
ulDimension = po.ulDragDimension();
arclTemp[0].left = po.rclDrag().left;
arclTemp[0].right = po.rclDrag().left + ulDimension;
arclTemp[0].top = po.rclDrag().top;
arclTemp[0].bottom = po.rclDrag().bottom;
arclTemp[1].left = po.rclDrag().right - ulDimension;
arclTemp[1].right = po.rclDrag().right;
arclTemp[1].top = po.rclDrag().top;
arclTemp[1].bottom = po.rclDrag().bottom;
arclTemp[2].left = po.rclDrag().left + ulDimension;
arclTemp[2].right = po.rclDrag().right - ulDimension;
arclTemp[2].top = po.rclDrag().top;
arclTemp[2].bottom = po.rclDrag().top + ulDimension;
arclTemp[3].left = po.rclDrag().left + ulDimension;
arclTemp[3].right = po.rclDrag().right - ulDimension;
arclTemp[3].top = po.rclDrag().bottom - ulDimension;
arclTemp[3].bottom = po.rclDrag().bottom;
//
// First intersect the passed-in clip rectangle with the clip rectangle
// given to us by USER, and then use the result to trim all the
// other rectangles:
//
rclClip = *(ERECTL*) prclClip;
rclClip *= po.rclDragClip();
crclTemp = cIntersect(&rclClip, &arclTemp[0], 4);
//
// We can't draw the drag rect over any locked DirectDraw surfaces,
// so get from DirectDraw a region that describes the unlocked
// parts of the screen:
//
pco = NULL;
prgn = prgnDdUnlockedRegion(po.hdev());
if (prgn != NULL)
{
eco.vSetup(prgn, *&rclClip, CLIP_FORCE);
if (eco.erclExclude().bEmpty())
return(FALSE);
//
// If the complexity is DC_RECT, drivers expect the destination
// rectangle to always intersect the clipping region. However,
// I can't be bothered to ensure this for each of the 'crclTemp'
// rectangles, so I will mark the clip object as 'complex' up
// front:
//
eco.iDComplexity = DC_COMPLEX;
pco = &eco;
}
for (i = 0; i != crclTemp; i++)
{
(*(po.pSurface()->pfnBitBlt()))
(po.pSurface()->pSurfobj(),
(SURFOBJ *) NULL,
(SURFOBJ *) NULL,
pco,
NULL,
&(arclTemp[i]),
(POINTL *) NULL,
(POINTL *) NULL,
po.pbo(),
&gptl00,
0x00005A5A);
}
return(crclTemp != 0);
}
/******************************Public*Routine******************************\
* vTearDownDragRect()
*
* Tears down the drag rect on a surface.
*
* History:
* 24-Aug-1992 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID DEVEXCLUDEOBJ::vTearDownDragRect(HDEV hdev_, RECTL *prclIn)
{
PDEVOBJ po(hdev_);
hdev = hdev_;
po.rclRedraw() = *(ERECTL*) prclIn;
bRedrawDragRect = bDrawDragRectangles(po, (ERECTL*) prclIn);
}
/******************************Public*Routine******************************\
* vReplaceStuff()
*
* Slap the drag rect back on screen if we took it down.
*
* History:
* Thu 14-Apr-1994 -by- Patrick Haluptzok [patrickh]
* Optimize / make Async pointers work
*
* 24-Aug-1992 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID DEVEXCLUDEOBJ::vReplaceStuff()
{
PDEVOBJ po(hdev);
if (bRedrawDragRect)
{
bDrawDragRectangles(po, &po.rclRedraw());
}
if (bRedrawCursor)
{
po.pfnMove()(po.pSurface()->pSurfobj(),
po.ptlPointer().x,
po.ptlPointer().y,
po.bPtrNeedsExcluding() ? &po.rclPointer() : NULL);
}
}
/******************************Public*Routine******************************\
* bSetDevDragRect()
*
* Called by USER to slap the drag rect on the screen, or to tear it back
* down.
*
* History:
* 3-Apr-1996 -by- J. Andrew Goossen andrewgo
* Moved all drag rect drawing to GDI and added DirectDraw support.
*
* 24-Aug-1992 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL bSetDevDragRect(
HDEV hdev,
RECTL* prclDrag,
RECTL* prclClip)
{
RECTL rclScreen;
RECTL arclDrag[4];
ULONG crclDrag;
BOOL bHaveDragRect;
PDEVOBJ po(hdev);
VACQUIREDEVLOCK(po.pDevLock());
bHaveDragRect = FALSE;
if (prclDrag != NULL)
{
ASSERTGDI(!po.bHaveDragRect(), "Expected not to have a drag rectangle");
bHaveDragRect = TRUE;
po.rclDrag() = *prclDrag;
if (prclClip != NULL)
{
po.rclDragClip() = *prclClip;
}
else
{
//
// make rclDragClip empty
//
po.rclDragClip().left = po.rclDragClip().right;
}
}
{
DEVEXCLUDEOBJ dxo;
rclScreen.left = 0;
rclScreen.top = 0;
rclScreen.right = po.sizl().cx;
rclScreen.bottom = po.sizl().cy;
dxo.vExclude(hdev, &rclScreen, NULL);
//
// Force the entire drag rect to be drawn when turning it on.
//
po.bHaveDragRect(bHaveDragRect);
po.rclRedraw() = rclScreen;
//
// vReplaceStuff will be called automatically when the dxo goes
// out of scope, and will draw the appropriate state of the drag
// rectangle. This has to be done before we release the devlock.
//
dxo.vForceDragRectRedraw(po.hdev(), bHaveDragRect);
}
VRELEASEDEVLOCK(po.pDevLock());
return(TRUE);
}
/******************************Public*Routine******************************\
* bMoveDevDragRect()
*
* Called by USER to move the drag rect on the screen.
*
* Note: Devlock must already have been acquired.
*
* History:
* 3-Apr-1996 -by- J. Andrew Goossen andrewgo
* Wrote it.
\**************************************************************************/
BOOL bMoveDevDragRect(
HDEV hdev,
RECTL *prclNew)
{
RECTL rclScreen;
PDEVOBJ po(hdev);
rclScreen.left = 0;
rclScreen.top = 0;
rclScreen.right = po.sizl().cx;
rclScreen.bottom = po.sizl().cy;
DEVEXCLUDEOBJ dxo;
dxo.vExclude(hdev, &rclScreen, NULL);
po.rclDrag() = *prclNew;
// vReplaceStuff will be called automatically when the dxo goes
// out of scope, and will draw the appropriate state of the drag
// rectangle.
dxo.vForceDragRectRedraw(po.hdev(), TRUE);
return(TRUE);
}
/******************************Public*Routine******************************\
* bSetDevDragWidth()
*
* Called by USER to tell us how wide the drag rectangle should be.
*
* 24-Aug-1992 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL bSetDevDragWidth(HDEV hdev, ULONG ulWidth)
{
PDEVOBJ po(hdev);
VACQUIREDEVLOCK(po.pDevLock());
po.ulDragDimension(ulWidth);
VRELEASEDEVLOCK(po.pDevLock());
return(TRUE);
}
/******************************Public*Routine******************************\
* DEVLOCKOBJ::bLock
*
* Device locking object. Optionally computes the Rao region.
*
* History:
* Sun 30-Aug-1992 -by- Patrick Haluptzok [patrickh]
* change to boolean return
*
* Mon 27-Apr-1992 22:46:41 -by- Charles Whitmer [chuckwh]
* Clean up again.
*
* Tue 16-Jul-1991 -by- Patrick Haluptzok [patrickh]
* Clean up.
*
* 15-Sep-1990 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
BOOL DEVLOCKOBJ::bLock(XDCOBJ& dco)
{
hsemTrg = NULL; // Remember the semaphore we're waiting on.
fl = DLO_VALID; // Remember if it is valid.
//
// We lock the semphore on direct display DCs and DFB's if
// the device has set GCAPS_SYNCHRONIZEACCESS set.
//
if (dco.bSynchronizeAccess())
{
//
// make sure we don't have any wrong sequence of acquiring locks
// should always acquire a DEVLOCK before we have the palette semaphore
//
ASSERTGDI ((gpsemPalette->OwnerThreads[0].OwnerThread
!= (ERESOURCE_THREAD)PsGetCurrentThread())
|| (dco.pDcDevLock()->OwnerThreads[0].OwnerThread
== (ERESOURCE_THREAD) PsGetCurrentThread()),
"potential deadlock!\n");
//
// Grab the display semaphore
//
hsemTrg = dco.pDcDevLock();
VACQUIREDEVLOCK(hsemTrg);
if (dco.pdc->bInFullScreen())
{
fl = 0;
return(FALSE);
}
}
//
// Compute the new Rao region if it's dirty.
//
if (dco.pdc->bDirtyRao())
{
if (!dco.pdc->bCompute())
{
fl &= ~(DLO_VALID);
return(FALSE);
}
}
return(TRUE);
}
/******************************Public*Routine******************************\
* DEVLOCKOBJ::vLockNoDrawing
*
* Device locking object for when no drawing will take place.
*
* Used primarily to protect against dynamic mode changing when looking at
* surface fields. Because no drawing will take place, the rao region
* computations and full-screen checks need not be made.
*
* History:
* Thu 8-Feb-1996 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
VOID DEVLOCKOBJ::vLockNoDrawing(XDCOBJ& dco)
{
hsemTrg = NULL; // Remember the semaphore we're waiting on.
fl = DLO_VALID; // Remember if it is valid.
//
// We lock display DC's even if bSynchronizeAccess() isn't set so that
// the surface palette will still be locked down even for device-
// dependent-bitmaps.
//
PDEVOBJ po(dco.hdev());
if (po.bDisplayPDEV())
{
//
// Grab the display semaphore
//
hsemTrg = dco.pDcDevLock();
VACQUIREDEVLOCK(hsemTrg);
}
}
/******************************Public*Routine******************************\
* DEVLOCKBLTOBJ::bLock
*
* Device locking object. Optionally computes the Rao region.
*
* History:
* Sun 30-Aug-1992 -by- Patrick Haluptzok [patrickh]
* change to boolean return
*
* Mon 27-Apr-1992 22:46:41 -by- Charles Whitmer [chuckwh]
* Clean up again.
*
* Tue 16-Jul-1991 -by- Patrick Haluptzok [patrickh]
* Clean up.
*
* 15-Sep-1990 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
BOOL DEVLOCKBLTOBJ::bLock(XDCOBJ& dco)
{
hsemTrg = NULL; // Remember the semaphore we're waiting on.
hsemSrc = NULL; // Remember the semaphore we're waiting on.
fl = DLO_VALID; // Remember if it is valid.
//
// We lock the semphore on direct display DCs and DFB's if
// the device has set GCAPS_SYNCHRONIZEACCESS set.
//
if (dco.bSynchronizeAccess())
{
//
// Grab the display semaphore
//
hsemTrg = dco.pDcDevLock();
VACQUIREDEVLOCK(hsemTrg);
//
// Check if we are in full screen and drawing
// to the Display, this may just be a DFB.
//
if (dco.bInFullScreen() && dco.bDisplay())
{
fl = 0;
return(FALSE);
}
}
//
// Compute the new Rao region if it's dirty.
//
if (dco.pdc->bDirtyRao())
{
if (!dco.pdc->bCompute())
{
fl &= ~(DLO_VALID);
return(FALSE);
}
}
return(TRUE);
}
/******************************Public*Routine******************************\
* DEVLOCKBLTOBJ::bLock
*
* Lock both a source and target DC. Used by StretchBlt, PlgBlt and such.
*
* We must check to see if we are in full screen and fail if we are.
*
* History:
* Mon 18-Apr-1994 -by- Patrick Haluptzok [patrickh]
* bSynchronize Checks
*
* 16-Feb-1993 -by- Eric Kutter [erick]
* Added full screen checks
*
* 11-Nov-1992 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
BOOL DEVLOCKBLTOBJ::bLock(XDCOBJ& dcoTrg, XDCOBJ& dcoSrc)
{
hsemTrg = NULL;
hsemSrc = NULL;
fl = DLO_VALID;
if (dcoSrc.bSynchronizeAccess())
{
//
// Grab the display semaphore
//
hsemSrc = dcoSrc.pDcDevLock();
VACQUIREDEVLOCK(hsemSrc);
//
// Check if we are in full screen and drawing
// to the Display, this may just be a DFB.
//
if (dcoSrc.bInFullScreen() && dcoSrc.bDisplay())
{
fl = 0;
return(FALSE);
}
}
if (dcoTrg.bSynchronizeAccess())
{
//
// Grab the display semaphore
//
hsemTrg = dcoTrg.pDcDevLock();
VACQUIREDEVLOCK(hsemTrg);
//
// Check if we are in full screen and drawing
// to the Display, this may just be a DFB.
//
if (dcoTrg.bInFullScreen() && dcoTrg.bDisplay())
{
fl = 0;
return(FALSE);
}
}
//
// Compute the new Rao regions.
//
if (dcoTrg.pdc->bDirtyRao())
{
if (!dcoTrg.pdc->bCompute())
{
fl &= ~(DLO_VALID);
return(FALSE);
}
}
if (dcoSrc.pdc->bDirtyRao())
{
if (!dcoSrc.pdc->bCompute())
{
fl &= ~(DLO_VALID);
return(FALSE);
}
}
return(TRUE);
}
/******************************Public*Routine******************************\
* DEVLOCK::bAddSource
*
* Add a source DC to the DEVLOCK object. This is needed for BitBlt and
* its kin that take two DC's but already locked down the target.
*
* History:
* Mon 18-Apr-1994 -by- Patrick Haluptzok [patrickh]
* bSynchronize Checks, rewrote it.
*
* 11-Nov-1992 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
BOOL DEVLOCKBLTOBJ::bAddSource(XDCOBJ& dcoSrc)
{
ASSERTGDI(fl & DLO_VALID, "ERROR this is only called after dst is locked");
if (dcoSrc.bSynchronizeAccess())
{
//
// Grab the display semaphore
//
hsemSrc = dcoSrc.pDcDevLock();
VACQUIREDEVLOCK(hsemSrc);
//
// Check if we are in full screen and drawing
// to the Display, this may just be a DFB.
//
if (dcoSrc.bInFullScreen() && dcoSrc.bDisplay())
{
fl &= ~(DLO_VALID);
return(FALSE);
}
}
if (dcoSrc.pdc->bDirtyRao())
{
if (!dcoSrc.pdc->bCompute())
{
fl &= ~(DLO_VALID);
return(FALSE);
}
}
return(TRUE);
}