зеркало из https://github.com/mozilla/pjs.git
Bug 191474. Make GTK paint in one pass, pass a region to paint up from GTK to the view manager. r+sr=blizzard
This commit is contained in:
Родитель
2e3dd4a088
Коммит
cec34e763a
|
@ -110,7 +110,8 @@ class NS_GFX nsRegion
|
|||
|
||||
|
||||
public:
|
||||
nsRegion ();
|
||||
nsRegion () { Init(); }
|
||||
nsRegion (const nsRectFast& aRect) { Init(); Copy(aRect); }
|
||||
~nsRegion () { SetToElements (0); }
|
||||
|
||||
nsRegion& Copy (const nsRegion& aRegion);
|
||||
|
@ -173,14 +174,13 @@ public:
|
|||
}
|
||||
|
||||
|
||||
PRBool GetBoundRect (nsRect& aBound) const
|
||||
nsRect GetBounds () const
|
||||
{
|
||||
aBound = mBoundRect;
|
||||
return !mBoundRect.IsEmpty ();
|
||||
return mBoundRect;
|
||||
}
|
||||
|
||||
void Offset (PRInt32 aXOffset, PRInt32 aYOffset);
|
||||
void Empty ()
|
||||
void MoveBy (PRInt32 aXOffset, PRInt32 aYOffset);
|
||||
void SetEmpty ()
|
||||
{
|
||||
SetToElements (0);
|
||||
mBoundRect.SetRect (0, 0, 0, 0);
|
||||
|
@ -197,6 +197,8 @@ private:
|
|||
RgnRect mRectListHead;
|
||||
nsRectFast mBoundRect;
|
||||
|
||||
void Init ();
|
||||
|
||||
void InsertBefore (RgnRect* aNewRect, RgnRect* aRelativeRect)
|
||||
{
|
||||
aNewRect->prev = aRelativeRect->prev;
|
||||
|
|
|
@ -411,7 +411,7 @@ void nsImageGTK::UpdateCachedImage()
|
|||
}
|
||||
}
|
||||
|
||||
mUpdateRegion.Empty();
|
||||
mUpdateRegion.SetEmpty();
|
||||
mPendingUpdate = PR_FALSE;
|
||||
mFlags = nsImageUpdateFlags_kBitsChanged; // this should be 0'd out by Draw()
|
||||
}
|
||||
|
|
|
@ -225,7 +225,7 @@ NS_IMETHODIMP nsRenderingContextGTK::LockDrawingSurface(PRInt32 aX, PRInt32 aY,
|
|||
PushState();
|
||||
|
||||
return mSurface->Lock(aX, aY, aWidth, aHeight,
|
||||
aBits, aStride, aWidthBytes, aFlags);
|
||||
aBits, aStride, aWidthBytes, aFlags);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsRenderingContextGTK::UnlockDrawingSurface(void)
|
||||
|
@ -415,22 +415,13 @@ NS_IMETHODIMP nsRenderingContextGTK::GetClipRect(nsRect &aRect, PRBool &aClipVal
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
#undef TRACE_SET_CLIP
|
||||
// #define TRACE_SET_CLIP
|
||||
#endif
|
||||
|
||||
#ifdef TRACE_SET_CLIP
|
||||
static char *
|
||||
nsClipCombine_to_string(nsClipCombine aCombine)
|
||||
{
|
||||
#ifdef TRACE_SET_CLIP
|
||||
printf("nsRenderingContextGTK::SetClipRect(x=%d,y=%d,w=%d,h=%d,%s)\n",
|
||||
trect.x,
|
||||
trect.y,
|
||||
trect.width,
|
||||
trect.height,
|
||||
nsClipCombine_to_string(aCombine));
|
||||
#endif // TRACE_SET_CLIP
|
||||
|
||||
switch(aCombine)
|
||||
{
|
||||
case nsClipCombine_kIntersect:
|
||||
|
@ -793,8 +784,12 @@ NS_IMETHODIMP nsRenderingContextGTK::CreateDrawingSurface(const nsRect &aBounds,
|
|||
if (surf)
|
||||
{
|
||||
NS_ADDREF(surf);
|
||||
PushState();
|
||||
mClipRegion = nsnull;
|
||||
UpdateGC();
|
||||
rv = surf->Init(mGC, aBounds.width, aBounds.height, aSurfFlags);
|
||||
rv = surf->Init(mGC, aBounds.width, aBounds.height, aSurfFlags);
|
||||
PRBool empty;
|
||||
PopState(empty);
|
||||
} else {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -877,7 +872,7 @@ NS_IMETHODIMP nsRenderingContextGTK::DrawPolyline(const nsPoint aPoints[], PRInt
|
|||
g_return_val_if_fail(mSurface != NULL, NS_ERROR_FAILURE);
|
||||
|
||||
GdkPoint *pts = new GdkPoint[aNumPoints];
|
||||
for (i = 0; i < aNumPoints; i++)
|
||||
for (i = 0; i < aNumPoints; i++)
|
||||
{
|
||||
nsPoint p = aPoints[i];
|
||||
mTranMatrix->TransformCoord(&p.x,&p.y);
|
||||
|
@ -1023,13 +1018,13 @@ NS_IMETHODIMP nsRenderingContextGTK::DrawPolygon(const nsPoint aPoints[], PRInt3
|
|||
g_return_val_if_fail(mSurface != NULL, NS_ERROR_FAILURE);
|
||||
|
||||
GdkPoint *pts = new GdkPoint[aNumPoints];
|
||||
for (PRInt32 i = 0; i < aNumPoints; i++)
|
||||
for (PRInt32 i = 0; i < aNumPoints; i++)
|
||||
{
|
||||
nsPoint p = aPoints[i];
|
||||
mTranMatrix->TransformCoord(&p.x,&p.y);
|
||||
pts[i].x = p.x;
|
||||
mTranMatrix->TransformCoord(&p.x,&p.y);
|
||||
pts[i].x = p.x;
|
||||
pts[i].y = p.y;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateGC();
|
||||
|
||||
|
@ -1046,13 +1041,13 @@ NS_IMETHODIMP nsRenderingContextGTK::FillPolygon(const nsPoint aPoints[], PRInt3
|
|||
g_return_val_if_fail(mSurface != NULL, NS_ERROR_FAILURE);
|
||||
|
||||
GdkPoint *pts = new GdkPoint[aNumPoints];
|
||||
for (PRInt32 i = 0; i < aNumPoints; i++)
|
||||
for (PRInt32 i = 0; i < aNumPoints; i++)
|
||||
{
|
||||
nsPoint p = aPoints[i];
|
||||
mTranMatrix->TransformCoord(&p.x,&p.y);
|
||||
pts[i].x = p.x;
|
||||
mTranMatrix->TransformCoord(&p.x,&p.y);
|
||||
pts[i].x = p.x;
|
||||
pts[i].y = p.y;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateGC();
|
||||
|
||||
|
|
|
@ -152,10 +152,7 @@ inline void nsRegion::RgnRect::operator delete (void* aRect, size_t)
|
|||
gRectPool.Free (NS_STATIC_CAST (RgnRect*, aRect));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
nsRegion::nsRegion ()
|
||||
void nsRegion::Init()
|
||||
{
|
||||
mRectListHead.prev = mRectListHead.next = &mRectListHead;
|
||||
mCurRect = &mRectListHead;
|
||||
|
@ -477,7 +474,7 @@ nsRegion& nsRegion::Copy (const nsRegion& aRegion)
|
|||
return *this;
|
||||
|
||||
if (aRegion.mRectCount == 0)
|
||||
Empty ();
|
||||
SetEmpty ();
|
||||
else
|
||||
{
|
||||
SetToElements (aRegion.mRectCount);
|
||||
|
@ -504,7 +501,7 @@ nsRegion& nsRegion::Copy (const nsRegion& aRegion)
|
|||
nsRegion& nsRegion::Copy (const nsRectFast& aRect)
|
||||
{
|
||||
if (aRect.IsEmpty ())
|
||||
Empty ();
|
||||
SetEmpty ();
|
||||
else
|
||||
{
|
||||
SetToElements (1);
|
||||
|
@ -522,7 +519,7 @@ nsRegion& nsRegion::And (const nsRegion& aRgn1, const nsRegion& aRgn2)
|
|||
Copy (aRgn1);
|
||||
else
|
||||
if (aRgn1.mRectCount == 0 || aRgn2.mRectCount == 0) // If either region is empty then result is empty
|
||||
Empty ();
|
||||
SetEmpty ();
|
||||
else
|
||||
{
|
||||
nsRectFast TmpRect;
|
||||
|
@ -534,7 +531,7 @@ nsRegion& nsRegion::And (const nsRegion& aRgn1, const nsRegion& aRgn2)
|
|||
} else
|
||||
{
|
||||
if (!aRgn1.mBoundRect.Intersects (aRgn2.mBoundRect)) // Regions do not intersect
|
||||
Empty ();
|
||||
SetEmpty ();
|
||||
else
|
||||
{
|
||||
// Region is simple rectangle and it fully overlays other region
|
||||
|
@ -624,7 +621,7 @@ nsRegion& nsRegion::And (const nsRegion& aRegion, const nsRectFast& aRect)
|
|||
{
|
||||
// If either region or rectangle is empty then result is empty
|
||||
if (aRegion.mRectCount == 0 || aRect.IsEmpty ())
|
||||
Empty ();
|
||||
SetEmpty ();
|
||||
else // Intersect region with rectangle
|
||||
{
|
||||
nsRectFast TmpRect;
|
||||
|
@ -636,7 +633,7 @@ nsRegion& nsRegion::And (const nsRegion& aRegion, const nsRectFast& aRect)
|
|||
} else // Intersect complex region with rectangle
|
||||
{
|
||||
if (!aRect.Intersects (aRegion.mBoundRect)) // Rectangle does not intersect region
|
||||
Empty ();
|
||||
SetEmpty ();
|
||||
else
|
||||
{
|
||||
if (aRect.Contains (aRegion.mBoundRect)) // Rectangle fully overlays region
|
||||
|
@ -747,7 +744,7 @@ nsRegion& nsRegion::Or (const nsRegion& aRegion, const nsRectFast& aRect)
|
|||
nsRegion& nsRegion::Xor (const nsRegion& aRgn1, const nsRegion& aRgn2)
|
||||
{
|
||||
if (&aRgn1 == &aRgn2) // Xor with self
|
||||
Empty ();
|
||||
SetEmpty ();
|
||||
else
|
||||
if (aRgn1.mRectCount == 0) // Region empty. Result is equal to other region
|
||||
Copy (aRgn2);
|
||||
|
@ -832,10 +829,10 @@ nsRegion& nsRegion::Xor (const nsRegion& aRegion, const nsRectFast& aRect)
|
|||
nsRegion& nsRegion::Sub (const nsRegion& aRgn1, const nsRegion& aRgn2)
|
||||
{
|
||||
if (&aRgn1 == &aRgn2) // Sub from self
|
||||
Empty ();
|
||||
SetEmpty ();
|
||||
else
|
||||
if (aRgn1.mRectCount == 0) // If source is empty then result is empty, too
|
||||
Empty ();
|
||||
SetEmpty ();
|
||||
else
|
||||
if (aRgn2.mRectCount == 0) // Nothing to subtract
|
||||
Copy (aRgn1);
|
||||
|
@ -857,7 +854,7 @@ nsRegion& nsRegion::Sub (const nsRegion& aRgn1, const nsRegion& aRgn2)
|
|||
nsRegion& nsRegion::Sub (const nsRegion& aRegion, const nsRectFast& aRect)
|
||||
{
|
||||
if (aRegion.mRectCount == 0) // If source is empty then result is empty, too
|
||||
Empty ();
|
||||
SetEmpty ();
|
||||
else
|
||||
if (aRect.IsEmpty ()) // Nothing to subtract
|
||||
Copy (aRegion);
|
||||
|
@ -868,7 +865,7 @@ nsRegion& nsRegion::Sub (const nsRegion& aRegion, const nsRectFast& aRect)
|
|||
else
|
||||
{
|
||||
if (aRect.Contains (aRegion.mBoundRect)) // Rectangle fully overlays region
|
||||
Empty ();
|
||||
SetEmpty ();
|
||||
else
|
||||
{
|
||||
aRegion.SubRect (aRect, *this);
|
||||
|
@ -891,7 +888,7 @@ void nsRegion::SubRegion (const nsRegion& aRegion, nsRegion& aResult) const
|
|||
if (aRegion.mRectCount == 1) // Subtract simple rectangle
|
||||
{
|
||||
if (aRegion.mBoundRect.Contains (mBoundRect))
|
||||
aResult.Empty ();
|
||||
aResult.SetEmpty ();
|
||||
else
|
||||
SubRect (*aRegion.mRectListHead.next, aResult);
|
||||
} else
|
||||
|
@ -1127,7 +1124,7 @@ PRBool nsRegion::IsEqual (const nsRegion& aRegion) const
|
|||
}
|
||||
|
||||
|
||||
void nsRegion::Offset (PRInt32 aXOffset, PRInt32 aYOffset)
|
||||
void nsRegion::MoveBy (PRInt32 aXOffset, PRInt32 aYOffset)
|
||||
{
|
||||
if (aXOffset || aYOffset)
|
||||
{
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
nsresult nsRegionImpl::Init (void)
|
||||
{
|
||||
mRegion.Empty ();
|
||||
mRegion.SetEmpty ();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -85,8 +85,7 @@ PRBool nsRegionImpl::IsEqual (const nsIRegion &aRegion)
|
|||
|
||||
void nsRegionImpl::GetBoundingBox (PRInt32 *aX, PRInt32 *aY, PRInt32 *aWidth, PRInt32 *aHeight)
|
||||
{
|
||||
nsRect BoundRect;
|
||||
mRegion.GetBoundRect (BoundRect);
|
||||
nsRect BoundRect = mRegion.GetBounds();
|
||||
*aX = BoundRect.x;
|
||||
*aY = BoundRect.y;
|
||||
*aWidth = BoundRect.width;
|
||||
|
@ -95,7 +94,7 @@ void nsRegionImpl::GetBoundingBox (PRInt32 *aX, PRInt32 *aY, PRInt32 *aWidth, PR
|
|||
|
||||
void nsRegionImpl::Offset (PRInt32 aXOffset, PRInt32 aYOffset)
|
||||
{
|
||||
mRegion.Offset (aXOffset, aYOffset);
|
||||
mRegion.MoveBy (aXOffset, aYOffset);
|
||||
}
|
||||
|
||||
PRBool nsRegionImpl::ContainsRect (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
|
||||
|
|
|
@ -627,19 +627,66 @@ PRBool DoDoubleBuffering(void)
|
|||
return doDoublebuffering;
|
||||
}
|
||||
|
||||
static void ConvertNativeRegionToAppRegion(nsIRegion* aIn, nsRegion* aOut,
|
||||
nsIDeviceContext* context)
|
||||
{
|
||||
nsRegionRectSet* rects = nsnull;
|
||||
aIn->GetRects(&rects);
|
||||
if (!rects)
|
||||
return;
|
||||
|
||||
float p2t;
|
||||
context->GetDevUnitsToAppUnits(p2t);
|
||||
|
||||
PRUint32 i;
|
||||
for (i = 0; i < rects->mNumRects; i++) {
|
||||
const nsRegionRect& inR = rects->mRects[i];
|
||||
nsRect outR(inR.x, inR.y, inR.width, inR.height);
|
||||
outR.ScaleRoundOut(p2t);
|
||||
aOut->Or(*aOut, outR);
|
||||
}
|
||||
|
||||
aIn->FreeRects(rects);
|
||||
}
|
||||
|
||||
/**
|
||||
aRegion is given in device coordinates!!
|
||||
*/
|
||||
void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext, nsIRegion *aRegion, PRUint32 aUpdateFlags)
|
||||
void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext,
|
||||
nsIRegion *aRegion, PRUint32 aUpdateFlags)
|
||||
{
|
||||
nsCOMPtr<nsIRenderingContext> localcx;
|
||||
nsDrawingSurface ds = nsnull;
|
||||
|
||||
NS_ASSERTION(aRegion != nsnull, "Null aRegion");
|
||||
|
||||
if (PR_FALSE == mRefreshEnabled)
|
||||
return;
|
||||
|
||||
nsRect viewRect;
|
||||
aView->GetDimensions(viewRect);
|
||||
// move the view rect into widget pixel coordinates
|
||||
nsRect viewRectInPixels = viewRect;
|
||||
viewRectInPixels.MoveTo(0, 0);
|
||||
float t2p;
|
||||
mContext->GetAppUnitsToDevUnits(t2p);
|
||||
viewRectInPixels.ScaleRoundOut(t2p);
|
||||
|
||||
// Get the damaged area into app coordinates (twips), but the origin is
|
||||
// still the widget origin
|
||||
nsRegion damageRegion;
|
||||
ConvertNativeRegionToAppRegion(aRegion, &damageRegion, mContext);
|
||||
damageRegion.MoveBy(viewRect.x, viewRect.y);
|
||||
|
||||
// Clip it to the view; shouldn't be necessary, but do it for sanity
|
||||
damageRegion.And(damageRegion, viewRect);
|
||||
if (damageRegion.IsEmpty()) {
|
||||
#ifdef DEBUG_roc
|
||||
nsRect damageRect = damageRegion.GetBounds();
|
||||
printf("XXX Damage rectangle (%d,%d,%d,%d) does not intersect the widget's view (%d,%d,%d,%d)!\n",
|
||||
damageRect.x, damageRect.y, damageRect.width, damageRect.height,
|
||||
viewRect.x, viewRect.y, viewRect.width, viewRect.height);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef NS_VM_PERF_METRICS
|
||||
MOZ_TIMER_DEBUGLOG(("Reset nsViewManager::Refresh(region), this=%p\n", this));
|
||||
MOZ_TIMER_RESET(mWatch);
|
||||
|
@ -648,12 +695,11 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext, nsIReg
|
|||
MOZ_TIMER_START(mWatch);
|
||||
#endif
|
||||
|
||||
NS_ASSERTION(!(PR_TRUE == mPainting), "recursive painting not permitted");
|
||||
NS_ASSERTION(!mPainting, "recursive painting not permitted");
|
||||
if (mPainting) {
|
||||
mRecursiveRefreshPending = PR_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
mPainting = PR_TRUE;
|
||||
|
||||
//printf("refreshing region...\n");
|
||||
|
@ -662,9 +708,8 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext, nsIReg
|
|||
if (mTransCnt > 0)
|
||||
aUpdateFlags |= NS_VMREFRESH_DOUBLE_BUFFER;
|
||||
|
||||
if (!DoDoubleBuffering()) {
|
||||
if (!DoDoubleBuffering())
|
||||
aUpdateFlags &= ~NS_VMREFRESH_DOUBLE_BUFFER;
|
||||
}
|
||||
|
||||
// check if the rendering context wants double-buffering or not
|
||||
if (aContext) {
|
||||
|
@ -679,6 +724,9 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext, nsIReg
|
|||
aUpdateFlags &= ~NS_VMREFRESH_DOUBLE_BUFFER;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRenderingContext> localcx;
|
||||
nsDrawingSurface ds = nsnull;
|
||||
|
||||
if (nsnull == aContext)
|
||||
{
|
||||
localcx = getter_AddRefs(CreateRenderingContext(*aView));
|
||||
|
@ -706,76 +754,48 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext, nsIReg
|
|||
}
|
||||
}
|
||||
|
||||
nsRect damageRectInPixels;
|
||||
aRegion->GetBoundingBox(&damageRectInPixels.x, &damageRectInPixels.y,
|
||||
&damageRectInPixels.width, &damageRectInPixels.height);
|
||||
nsRect damageRect = damageRegion.GetBounds();
|
||||
nsRect damageRectInPixels = damageRect;
|
||||
damageRectInPixels.ScaleRoundOut(t2p);
|
||||
|
||||
if (aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER)
|
||||
{
|
||||
nsRect maxWidgetSize;
|
||||
GetMaxWidgetBounds(maxWidgetSize);
|
||||
if NS_FAILED(localcx->GetBackbuffer(nsRect(0, 0, damageRectInPixels.width, damageRectInPixels.height), maxWidgetSize, ds)) {
|
||||
|
||||
nsRect r(0, 0, damageRectInPixels.width, damageRectInPixels.height);
|
||||
if (NS_FAILED(localcx->GetBackbuffer(r, maxWidgetSize, ds))) {
|
||||
//Failed to get backbuffer so turn off double buffering
|
||||
aUpdateFlags &= ~NS_VMREFRESH_DOUBLE_BUFFER;
|
||||
}
|
||||
}
|
||||
|
||||
nsRect viewRect;
|
||||
aView->GetDimensions(viewRect);
|
||||
if ((aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER) && ds) {
|
||||
// backbuffer's (0,0) is mapped to damageRect.x, damageRect.y
|
||||
localcx->Translate(-damageRect.x, -damageRect.y);
|
||||
aRegion->Offset(-damageRectInPixels.x, -damageRectInPixels.y);
|
||||
}
|
||||
|
||||
nsRect damageRect;
|
||||
nsRect paintRect;
|
||||
float p2t;
|
||||
mContext->GetDevUnitsToAppUnits(p2t);
|
||||
damageRect.x = NSToIntRound(damageRectInPixels.x * p2t);
|
||||
damageRect.y = NSToIntRound(damageRectInPixels.y * p2t);
|
||||
damageRect.width = NSToIntRound(damageRectInPixels.width * p2t);
|
||||
damageRect.height = NSToIntRound(damageRectInPixels.height * p2t);
|
||||
|
||||
// move the view rect into widget coordinates
|
||||
viewRect.x = 0;
|
||||
viewRect.y = 0;
|
||||
PRBool result;
|
||||
// Note that nsIRenderingContext::SetClipRegion always works in pixel coordinates,
|
||||
// and nsIRenderingContext::SetClipRect always works in app coordinates. Stupid huh?
|
||||
// Also, SetClipRegion doesn't subject its argument to the current transform, but
|
||||
// SetClipRect does.
|
||||
localcx->SetClipRegion(*aRegion, nsClipCombine_kReplace, result);
|
||||
localcx->SetClipRect(damageRect, nsClipCombine_kIntersect, result);
|
||||
|
||||
if (paintRect.IntersectRect(damageRect, viewRect)) {
|
||||
// painting will be done in aView's coordinates, so shift them back to widget coordinates
|
||||
localcx->Translate(-viewRect.x, -viewRect.y);
|
||||
RenderViews(aView, *localcx, damageRegion, result);
|
||||
localcx->Translate(viewRect.x, viewRect.y);
|
||||
|
||||
if ((aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER) && ds) {
|
||||
// backbuffer's (0,0) is mapped to damageRect.x, damageRect.y
|
||||
localcx->Translate(-damageRect.x, -damageRect.y);
|
||||
aRegion->Offset(-damageRectInPixels.x, -damageRectInPixels.y);
|
||||
}
|
||||
|
||||
PRBool result;
|
||||
// Note that nsIRenderingContext::SetClipRegion always works in pixel coordinates,
|
||||
// and nsIRenderingContext::SetClipRect always works in app coordinates. Stupid huh?
|
||||
if ((aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER) && ds) {
|
||||
// Setup the region relative to the destination's coordinates
|
||||
aRegion->Offset(damageRectInPixels.x, damageRectInPixels.y);
|
||||
localcx->SetClipRegion(*aRegion, nsClipCombine_kReplace, result);
|
||||
localcx->SetClipRect(paintRect, nsClipCombine_kIntersect, result);
|
||||
|
||||
// pass in a damage rectangle in aView's coordinates.
|
||||
nsRect r = paintRect;
|
||||
nsRect dims;
|
||||
aView->GetDimensions(dims);
|
||||
r.x += dims.x;
|
||||
r.y += dims.y;
|
||||
|
||||
// painting will be done in aView's coordinates, so shift them back to widget coordinates
|
||||
localcx->Translate(-dims.x, -dims.y);
|
||||
RenderViews(aView, *localcx, r, result);
|
||||
localcx->Translate(dims.x, dims.y);
|
||||
|
||||
if ((aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER) && ds) {
|
||||
// Setup the region relative to the destination's coordinates
|
||||
aRegion->Offset(damageRectInPixels.x, damageRectInPixels.y);
|
||||
localcx->SetClipRegion(*aRegion, nsClipCombine_kReplace, result);
|
||||
localcx->Translate(damageRect.x, damageRect.y);
|
||||
localcx->SetClipRect(paintRect, nsClipCombine_kIntersect, result);
|
||||
localcx->CopyOffScreenBits(ds, 0, 0, damageRectInPixels, NS_COPYBITS_USE_SOURCE_CLIP_REGION);
|
||||
}
|
||||
} else {
|
||||
#ifdef DEBUG_roc
|
||||
printf("XXX Damage rectangle (%d,%d,%d,%d) does not intersect the widget's view (%d,%d,%d,%d)!\n",
|
||||
damageRect.x, damageRect.y, damageRect.width, damageRect.height,
|
||||
viewRect.x, viewRect.y, viewRect.width, viewRect.height);
|
||||
#endif
|
||||
localcx->Translate(damageRect.x, damageRect.y);
|
||||
localcx->SetClipRect(damageRect, nsClipCombine_kIntersect, result);
|
||||
localcx->CopyOffScreenBits(ds, 0, 0, damageRectInPixels, NS_COPYBITS_USE_SOURCE_CLIP_REGION);
|
||||
}
|
||||
|
||||
mPainting = PR_FALSE;
|
||||
|
@ -1036,7 +1056,7 @@ void nsViewManager::AddCoveringWidgetsToOpaqueRegion(nsRegion &aRgn, nsIDeviceCo
|
|||
//
|
||||
// NB: we must NOT add widgets that correspond to floating views!
|
||||
// We may be required to paint behind them
|
||||
aRgn.Empty();
|
||||
aRgn.SetEmpty();
|
||||
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
GetWidgetForView(aRootView, getter_AddRefs(widget));
|
||||
|
@ -1090,16 +1110,17 @@ void nsViewManager::AddCoveringWidgetsToOpaqueRegion(nsRegion &aRgn, nsIDeviceCo
|
|||
} while (NS_SUCCEEDED(children->Next()));
|
||||
}
|
||||
|
||||
void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC, const nsRect& aRect, PRBool &aResult)
|
||||
void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC,
|
||||
const nsRegion& aRegion, PRBool &aResult)
|
||||
{
|
||||
BuildDisplayList(aRootView, aRect, PR_FALSE, PR_FALSE);
|
||||
BuildDisplayList(aRootView, aRegion.GetBounds(), PR_FALSE, PR_FALSE);
|
||||
|
||||
PRBool anyRendered;
|
||||
nsRect finalTransparentRect;
|
||||
|
||||
nsRegion opaqueRgn;
|
||||
AddCoveringWidgetsToOpaqueRegion(opaqueRgn, mContext, aRootView);
|
||||
OptimizeDisplayList(aRect, finalTransparentRect, opaqueRgn);
|
||||
OptimizeDisplayList(aRegion, finalTransparentRect, opaqueRgn);
|
||||
|
||||
#ifdef DEBUG_roc
|
||||
// ShowDisplayList(mDisplayListCount);
|
||||
|
@ -1123,6 +1144,12 @@ void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC, con
|
|||
PRInt32 index = 0;
|
||||
nsRect fakeClipRect;
|
||||
OptimizeDisplayListClipping(PR_FALSE, fakeClipRect, index, anyRendered);
|
||||
|
||||
#ifdef DEBUG_roc
|
||||
printf("*** mTranslucentArea=%d,%d,%d,%d\n", mTranslucentArea.x, mTranslucentArea.y,
|
||||
mTranslucentArea.width, mTranslucentArea.height);
|
||||
printf("*** gOffscreenSize=%d,%d\n", gOffScreenSize.width, gOffScreenSize.height);
|
||||
#endif
|
||||
|
||||
// We keep a list of all the rendering contexts whose clip rects
|
||||
// need to be updated.
|
||||
|
@ -1133,7 +1160,7 @@ void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC, con
|
|||
// create blending buffers, if necessary.
|
||||
if (mTranslucentViewCount > 0) {
|
||||
nsresult rv = CreateBlendingBuffers(aRC);
|
||||
NS_ASSERTION((rv == NS_OK), "not enough memory to blend");
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "not enough memory to blend");
|
||||
if (NS_FAILED(rv)) {
|
||||
// fall back by just rendering with transparency.
|
||||
mTranslucentViewCount = 0;
|
||||
|
@ -1155,8 +1182,8 @@ void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC, con
|
|||
mOffScreenCX->FillRect(nsRect(0, 0, gOffScreenSize.width, gOffScreenSize.height));
|
||||
}
|
||||
// DEBUGGING: fill in complete offscreen image in green, to see if we've got a blending bug.
|
||||
//mOffScreenCX->SetColor(NS_RGB(0, 255, 0));
|
||||
//mOffScreenCX->FillRect(nsRect(0, 0, gOffScreenSize.width, gOffScreenSize.height));
|
||||
// mOffScreenCX->SetColor(NS_RGB(0, 255, 0));
|
||||
// mOffScreenCX->FillRect(nsRect(0, 0, gOffScreenSize.width, gOffScreenSize.height));
|
||||
}
|
||||
|
||||
// draw all views in the display list, from back to front.
|
||||
|
@ -1192,13 +1219,13 @@ void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC, con
|
|||
// Must flush back when no clipping is in effect.
|
||||
if (mTranslucentViewCount > 0) {
|
||||
// DEBUG: is this getting through?
|
||||
// mOffScreenCX->SetColor(NS_RGB(0, 0, 0));
|
||||
// mOffScreenCX->DrawRect(nsRect(0, 0, mTranslucentArea.width, mTranslucentArea.height));
|
||||
// mOffScreenCX->SetColor(NS_RGB(177, 177, 0));
|
||||
// mOffScreenCX->FillRect(nsRect(1, 1, mTranslucentArea.width-2, mTranslucentArea.height-2));
|
||||
aRC.CopyOffScreenBits(gOffScreen, 0, 0, mTranslucentArea,
|
||||
NS_COPYBITS_XFORM_DEST_VALUES |
|
||||
NS_COPYBITS_TO_BACK_BUFFER);
|
||||
// DEBUG: what rectangle are we blitting?
|
||||
// aRC.SetColor(NS_RGB(0, 0, 0));
|
||||
// aRC.SetColor(NS_RGB(0, 177, 177));
|
||||
// aRC.DrawRect(mTranslucentArea);
|
||||
}
|
||||
|
||||
|
@ -1278,6 +1305,7 @@ void nsViewManager::RenderDisplayListElement(DisplayListElement2* element, nsIRe
|
|||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Blend failed!");
|
||||
// let's paint SOMETHING. Paint opaquely
|
||||
damageRect.MoveBy(-viewX, -viewY);
|
||||
PaintView(view, *mOffScreenCX, viewX, viewY, damageRect);
|
||||
}
|
||||
}
|
||||
|
@ -1750,75 +1778,63 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS
|
|||
{
|
||||
nsView *view = nsView::GetViewFor(aEvent->widget);
|
||||
|
||||
if (nsnull != view)
|
||||
{
|
||||
// Do an immediate refresh
|
||||
if (nsnull != mContext)
|
||||
{
|
||||
// The rect is in device units, and it's in the coordinate space of its
|
||||
// associated window.
|
||||
nsRect& damrect = *((nsPaintEvent*)aEvent)->rect;
|
||||
if (!view || !mContext)
|
||||
break;
|
||||
|
||||
if (damrect.width > 0 && damrect.height > 0)
|
||||
{
|
||||
PRUint32 updateFlags = NS_VMREFRESH_DOUBLE_BUFFER;
|
||||
PRBool doDefault = PR_TRUE;
|
||||
// The rect is in device units, and it's in the coordinate space of its
|
||||
// associated window.
|
||||
nsCOMPtr<nsIRegion> region = ((nsPaintEvent*)aEvent)->region;
|
||||
if (!region) {
|
||||
if (NS_FAILED(CreateRegion(getter_AddRefs(region))))
|
||||
break;
|
||||
|
||||
// printf("refreshing: view: %x, %d, %d, %d, %d\n", view, damrect.x, damrect.y, damrect.width, damrect.height);
|
||||
// Refresh the view
|
||||
if (mRefreshEnabled) {
|
||||
nsCOMPtr<nsIRegion> rgn;
|
||||
nsresult rv = CreateRegion(getter_AddRefs(rgn));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Eventually we would like the platform paint event to include a region
|
||||
// we can use. This could improve paint performance when the invalid area
|
||||
// is more complicated than a rectangle. Right now the event's region field
|
||||
// just contains garbage on some platforms so we can't trust it at all.
|
||||
// When that gets fixed, we can just change the code right here.
|
||||
rgn->SetTo(damrect.x, damrect.y, damrect.width, damrect.height);
|
||||
Refresh(view, ((nsPaintEvent*)aEvent)->renderingContext, rgn, updateFlags);
|
||||
doDefault = PR_FALSE;
|
||||
}
|
||||
}
|
||||
const nsRect& damrect = *((nsPaintEvent*)aEvent)->rect;
|
||||
region->SetTo(damrect.x, damrect.y, damrect.width, damrect.height);
|
||||
}
|
||||
|
||||
if (region->IsEmpty())
|
||||
break;
|
||||
|
||||
// since we got an NS_PAINT event, we need to
|
||||
// draw something so we don't get blank areas.
|
||||
if (doDefault) {
|
||||
float p2t;
|
||||
mContext->GetDevUnitsToAppUnits(p2t);
|
||||
damrect.ScaleRoundOut(p2t);
|
||||
DefaultRefresh(view, &damrect);
|
||||
|
||||
// Clients like the editor can trigger multiple
|
||||
// reflows during what the user perceives as a single
|
||||
// edit operation, so it disables view manager
|
||||
// refreshing until the edit operation is complete
|
||||
// so that users don't see the intermediate steps.
|
||||
//
|
||||
// Unfortunately some of these reflows can trigger
|
||||
// nsScrollPortView and nsScrollingView Scroll() calls
|
||||
// which in most cases force an immediate BitBlt and
|
||||
// synchronous paint to happen even if the view manager's
|
||||
// refresh is disabled. (Bug 97674)
|
||||
//
|
||||
// Calling UpdateView() here, is neccessary to add
|
||||
// the exposed region specified in the synchronous paint
|
||||
// event to the view's damaged region so that it gets
|
||||
// painted properly when refresh is enabled.
|
||||
//
|
||||
// Note that calling UpdateView() here was deemed
|
||||
// to have the least impact on performance, since the
|
||||
// other alternative was to make Scroll() post an
|
||||
// async paint event for the *entire* ScrollPort or
|
||||
// ScrollingView's viewable area. (See bug 97674 for this
|
||||
// alternate patch.)
|
||||
|
||||
UpdateView(view, damrect, NS_VMREFRESH_NO_SYNC);
|
||||
}
|
||||
}
|
||||
}
|
||||
*aStatus = nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
// Refresh the view
|
||||
if (mRefreshEnabled) {
|
||||
Refresh(view, ((nsPaintEvent*)aEvent)->renderingContext, region,
|
||||
NS_VMREFRESH_DOUBLE_BUFFER);
|
||||
} else {
|
||||
// since we got an NS_PAINT event, we need to
|
||||
// draw something so we don't get blank areas.
|
||||
nsRect damRect;
|
||||
region->GetBoundingBox(&damRect.x, &damRect.y, &damRect.width, &damRect.height);
|
||||
float p2t;
|
||||
mContext->GetDevUnitsToAppUnits(p2t);
|
||||
damRect.ScaleRoundOut(p2t);
|
||||
DefaultRefresh(view, &damRect);
|
||||
|
||||
// Clients like the editor can trigger multiple
|
||||
// reflows during what the user perceives as a single
|
||||
// edit operation, so it disables view manager
|
||||
// refreshing until the edit operation is complete
|
||||
// so that users don't see the intermediate steps.
|
||||
//
|
||||
// Unfortunately some of these reflows can trigger
|
||||
// nsScrollPortView and nsScrollingView Scroll() calls
|
||||
// which in most cases force an immediate BitBlt and
|
||||
// synchronous paint to happen even if the view manager's
|
||||
// refresh is disabled. (Bug 97674)
|
||||
//
|
||||
// Calling UpdateView() here, is neccessary to add
|
||||
// the exposed region specified in the synchronous paint
|
||||
// event to the view's damaged region so that it gets
|
||||
// painted properly when refresh is enabled.
|
||||
//
|
||||
// Note that calling UpdateView() here was deemed
|
||||
// to have the least impact on performance, since the
|
||||
// other alternative was to make Scroll() post an
|
||||
// async paint event for the *entire* ScrollPort or
|
||||
// ScrollingView's viewable area. (See bug 97674 for this
|
||||
// alternate patch.)
|
||||
|
||||
UpdateView(view, damRect, NS_VMREFRESH_NO_SYNC);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -2619,7 +2635,7 @@ NS_IMETHODIMP nsViewManager::SetViewChildClipRegion(nsIView *aView, const nsRegi
|
|||
// and it is set to no more than the bounds of the view.
|
||||
if (aRegion != nsnull) {
|
||||
newClipFlag = PR_TRUE;
|
||||
aRegion->GetBoundRect(newClipRect);
|
||||
newClipRect = aRegion->GetBounds();
|
||||
if (IsClipView(view)) {
|
||||
nsRect dims;
|
||||
view->GetDimensions(dims);
|
||||
|
@ -2801,7 +2817,7 @@ PRBool nsViewManager::CanScrollWithBitBlt(nsView* aView)
|
|||
v->ConvertToParentCoords(&deltaX, &deltaY);
|
||||
v = v->GetParent();
|
||||
}
|
||||
opaqueRegion.Offset(-deltaX, -deltaY);
|
||||
opaqueRegion.MoveBy(-deltaX, -deltaY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2811,7 +2827,7 @@ PRBool nsViewManager::CanScrollWithBitBlt(nsView* aView)
|
|||
|
||||
// (Of course it's possible that aView's parent is actually in front of aView (if aView has a negative
|
||||
// z-index) but if so, this code still does the right thing. Yay for the display list based approach!)
|
||||
OptimizeDisplayList(r, finalTransparentRect, opaqueRegion);
|
||||
OptimizeDisplayList(nsRegion(r), finalTransparentRect, opaqueRegion);
|
||||
|
||||
PRBool anyUnscrolledViews = PR_FALSE;
|
||||
PRBool anyUnblittableViews = PR_FALSE;
|
||||
|
@ -3287,7 +3303,7 @@ NS_IMETHODIMP nsViewManager::Display(nsIView* aView, nscoord aX, nscoord aY, con
|
|||
|
||||
// Paint the view. The clipping rect was set above set don't clip again.
|
||||
//aView->Paint(*localcx, trect, NS_VIEW_FLAG_CLIP_SET, result);
|
||||
RenderViews(view, *localcx, trect, result);
|
||||
RenderViews(view, *localcx, nsRegion(trect), result);
|
||||
|
||||
NS_RELEASE(localcx);
|
||||
|
||||
|
@ -3662,23 +3678,22 @@ void nsViewManager::ReapplyClipInstructions(PRBool aHaveClip, nsRect& aClipRect,
|
|||
Usually this will be empty, but nothing really prevents someone
|
||||
from creating a set of views that are (for example) all transparent.
|
||||
*/
|
||||
nsresult nsViewManager::OptimizeDisplayList(const nsRect& aDamageRect, nsRect& aFinalTransparentRect,
|
||||
nsresult nsViewManager::OptimizeDisplayList(const nsRegion& aDamageRegion,
|
||||
nsRect& aFinalTransparentRect,
|
||||
nsRegion &aOpaqueRegion)
|
||||
{
|
||||
aFinalTransparentRect = aDamageRect;
|
||||
|
||||
PRInt32 count = mDisplayListCount;
|
||||
for (PRInt32 i = count - 1; i >= 0; i--) {
|
||||
DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, mDisplayList.ElementAt(i));
|
||||
if (element->mFlags & VIEW_RENDERED) {
|
||||
nsRegion tmpRgn;
|
||||
tmpRgn.Copy(element->mBounds);
|
||||
tmpRgn.Sub(tmpRgn, aOpaqueRegion);
|
||||
tmpRgn.Sub(element->mBounds, aOpaqueRegion);
|
||||
tmpRgn.And(tmpRgn, aDamageRegion);
|
||||
|
||||
if (tmpRgn.IsEmpty()) {
|
||||
element->mFlags &= ~VIEW_RENDERED;
|
||||
} else {
|
||||
tmpRgn.GetBoundRect(element->mBounds);
|
||||
element->mBounds = tmpRgn.GetBounds();
|
||||
|
||||
// a view is opaque if it is neither transparent nor transluscent
|
||||
if (!(element->mFlags & (VIEW_TRANSPARENT | VIEW_TRANSLUCENT))) {
|
||||
|
@ -3689,9 +3704,8 @@ nsresult nsViewManager::OptimizeDisplayList(const nsRect& aDamageRect, nsRect& a
|
|||
}
|
||||
|
||||
nsRegion tmpRgn;
|
||||
tmpRgn.Copy(aDamageRect);
|
||||
tmpRgn.Sub(tmpRgn, aOpaqueRegion);
|
||||
tmpRgn.GetBoundRect(aFinalTransparentRect);
|
||||
tmpRgn.Sub(aDamageRegion, aOpaqueRegion);
|
||||
aFinalTransparentRect = tmpRgn.GetBounds();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -252,7 +252,7 @@ private:
|
|||
void Refresh(nsView *aView, nsIRenderingContext *aContext,
|
||||
nsIRegion *region, PRUint32 aUpdateFlags);
|
||||
void DefaultRefresh(nsView* aView, const nsRect* aRect);
|
||||
void RenderViews(nsView *aRootView, nsIRenderingContext& aRC, const nsRect& aRect,
|
||||
void RenderViews(nsView *aRootView, nsIRenderingContext& aRC, const nsRegion& aRegion,
|
||||
PRBool &aResult);
|
||||
|
||||
void RenderDisplayListElement(DisplayListElement2* element, nsIRenderingContext &aRC);
|
||||
|
@ -276,7 +276,8 @@ private:
|
|||
PRBool AddToDisplayList(nsView *aView, DisplayZTreeNode* &aParent, nsRect &aClipRect,
|
||||
nsRect& aDirtyRect, PRUint32 aFlags, nscoord aAbsX, nscoord aAbsY, PRBool aAssumeIntersection);
|
||||
void ReapplyClipInstructions(PRBool aHaveClip, nsRect& aClipRect, PRInt32& aIndex);
|
||||
nsresult OptimizeDisplayList(const nsRect& aDamageRect, nsRect& aFinalTransparentRect, nsRegion& aOpaqueRgn);
|
||||
nsresult OptimizeDisplayList(const nsRegion& aDirtyRegion,
|
||||
nsRect& aFinalTransparentRect, nsRegion& aOpaqueRgn);
|
||||
// Remove redundant PUSH/POP_CLIP pairs.
|
||||
void ComputeViewOffset(nsView *aView, nsPoint *aOrigin);
|
||||
|
||||
|
|
|
@ -2645,6 +2645,7 @@ PRBool nsWindow::OnPaint(nsRect &r)
|
|||
nsPaintEvent event;
|
||||
|
||||
InitEvent(event, NS_PAINT);
|
||||
event.region = nsnull;
|
||||
event.rect = &r;
|
||||
event.eventStructType = NS_PAINT_EVENT;
|
||||
|
||||
|
|
|
@ -1562,6 +1562,7 @@ nsChildView::UpdateWidget(nsRect& aRect, nsIRenderingContext* aContext)
|
|||
paintEvent.nativeMsg = NULL;
|
||||
paintEvent.renderingContext = aContext; // nsPaintEvent
|
||||
paintEvent.rect = &aRect;
|
||||
paintEvent.region = nsnull;
|
||||
|
||||
// offscreen drawing is pointless.
|
||||
if (paintEvent.rect->x < 0)
|
||||
|
|
|
@ -156,7 +156,7 @@ nsGtkUtils::gdk_keyboard_get_modifiers()
|
|||
nsGtkUtils::gdk_window_flash(GdkWindow * aGdkWindow,
|
||||
unsigned int aTimes,
|
||||
unsigned long aInterval,
|
||||
GdkRectangle * aArea)
|
||||
GdkRegion * aRegion)
|
||||
{
|
||||
gint x;
|
||||
gint y;
|
||||
|
@ -185,18 +185,8 @@ nsGtkUtils::gdk_window_flash(GdkWindow * aGdkWindow,
|
|||
gdk_gc_set_function(gc,GDK_XOR);
|
||||
gdk_gc_set_subwindow(gc,GDK_INCLUDE_INFERIORS);
|
||||
|
||||
/*
|
||||
* If an area is given, use that. Notice how out of whack coordinates
|
||||
* and dimentsions are not checked!!!
|
||||
*/
|
||||
if (aArea)
|
||||
{
|
||||
x += aArea->x;
|
||||
y += aArea->y;
|
||||
|
||||
width = aArea->width;
|
||||
height = aArea->height;
|
||||
}
|
||||
gdk_region_offset(aRegion, x, y);
|
||||
gdk_gc_set_clip_region(gc, aRegion);
|
||||
|
||||
/*
|
||||
* Need to do this twice so that the XOR effect can replace
|
||||
|
@ -218,5 +208,7 @@ nsGtkUtils::gdk_window_flash(GdkWindow * aGdkWindow,
|
|||
}
|
||||
|
||||
gdk_gc_destroy(gc);
|
||||
|
||||
gdk_region_offset(aRegion, -x, -y);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -94,7 +94,7 @@ struct nsGtkUtils
|
|||
static void gdk_window_flash(GdkWindow * aGdkWindow,
|
||||
unsigned int aTimes,
|
||||
unsigned long aInterval,
|
||||
GdkRectangle * aArea);
|
||||
GdkRegion * aArea);
|
||||
};
|
||||
|
||||
#endif // __nsGtkEventHandler.h
|
||||
|
|
|
@ -792,71 +792,56 @@ nsWindow::UnqueueDraw ()
|
|||
}
|
||||
|
||||
void
|
||||
nsWindow::DoPaint (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
|
||||
nsIRegion *aClipRegion)
|
||||
nsWindow::DoPaint (nsIRegion *aClipRegion)
|
||||
{
|
||||
//Don't dispatch paint event if widget's height or width is 0
|
||||
if ((mBounds.width == 0) || (mBounds.height == 0)) {
|
||||
return;
|
||||
}
|
||||
if (!mEventCallback)
|
||||
return;
|
||||
|
||||
if (mEventCallback) {
|
||||
|
||||
nsPaintEvent event;
|
||||
nsRect rect(aX, aY, aWidth, aHeight);
|
||||
nsPaintEvent event;
|
||||
|
||||
event.message = NS_PAINT;
|
||||
event.widget = (nsWidget *)this;
|
||||
event.eventStructType = NS_PAINT_EVENT;
|
||||
event.point.x = aX;
|
||||
event.point.y = aY;
|
||||
event.time = GDK_CURRENT_TIME; // No time in EXPOSE events
|
||||
|
||||
event.rect = ▭
|
||||
event.region = nsnull;
|
||||
|
||||
event.renderingContext = GetRenderingContext();
|
||||
if (event.renderingContext) {
|
||||
event.message = NS_PAINT;
|
||||
event.widget = (nsWidget *)this;
|
||||
event.eventStructType = NS_PAINT_EVENT;
|
||||
event.point.x = 0;
|
||||
event.point.y = 0;
|
||||
event.time = GDK_CURRENT_TIME; // No time in EXPOSE events
|
||||
|
||||
nsRect boundsRect;
|
||||
aClipRegion->GetBoundingBox(&boundsRect.x, &boundsRect.y, &boundsRect.width, &boundsRect.height);
|
||||
event.rect = &boundsRect;
|
||||
event.region = aClipRegion;
|
||||
|
||||
// Don't paint anything if our window isn't visible.
|
||||
if (!mSuperWin || mSuperWin->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
|
||||
return;
|
||||
|
||||
event.renderingContext = GetRenderingContext();
|
||||
if (!event.renderingContext)
|
||||
return;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (WANT_PAINT_FLASHING)
|
||||
{
|
||||
GdkWindow *gw = GetRenderWindow(GTK_OBJECT(mSuperWin));
|
||||
if (gw)
|
||||
{
|
||||
GdkRectangle ar;
|
||||
GdkRectangle * area = (GdkRectangle*) NULL;
|
||||
|
||||
if (event.rect)
|
||||
{
|
||||
ar.x = event.rect->x;
|
||||
ar.y = event.rect->y;
|
||||
|
||||
ar.width = event.rect->width;
|
||||
ar.height = event.rect->height;
|
||||
|
||||
area = &ar;
|
||||
}
|
||||
|
||||
nsGtkUtils::gdk_window_flash(gw,1,100000,area);
|
||||
}
|
||||
}
|
||||
|
||||
// Check the pref _before_ checking caps lock, because checking
|
||||
// caps lock requires a server round-trip.
|
||||
if (debug_GetCachedBoolPref("nglayout.debug.paint_dumping") && CAPS_LOCK_IS_ON)
|
||||
debug_DumpPaintEvent(stdout, this, &event,
|
||||
debug_GetName(GTK_OBJECT(mSuperWin)),
|
||||
(PRInt32) debug_GetRenderXID(GTK_OBJECT(mSuperWin)));
|
||||
#endif // DEBUG
|
||||
|
||||
DispatchWindowEvent(&event);
|
||||
NS_RELEASE(event.renderingContext);
|
||||
GdkWindow *gw = GetRenderWindow(GTK_OBJECT(mSuperWin));
|
||||
if (WANT_PAINT_FLASHING && gw)
|
||||
{
|
||||
GdkRegion *region;
|
||||
aClipRegion->GetNativeRegion(*(void**)®ion);
|
||||
nsGtkUtils::gdk_window_flash(gw,1,100000,region);
|
||||
}
|
||||
|
||||
}
|
||||
// Check the pref _before_ checking caps lock, because checking
|
||||
// caps lock requires a server round-trip.
|
||||
if (debug_GetCachedBoolPref("nglayout.debug.paint_dumping") && CAPS_LOCK_IS_ON)
|
||||
debug_DumpPaintEvent(stdout, this, &event,
|
||||
debug_GetName(GTK_OBJECT(mSuperWin)),
|
||||
(PRInt32) debug_GetRenderXID(GTK_OBJECT(mSuperWin)));
|
||||
#endif // DEBUG
|
||||
|
||||
DispatchWindowEvent(&event);
|
||||
NS_RELEASE(event.renderingContext);
|
||||
}
|
||||
|
||||
static NS_DEFINE_CID(kRegionCID, NS_REGION_CID);
|
||||
|
||||
NS_IMETHODIMP nsWindow::Update(void)
|
||||
{
|
||||
if (!mSuperWin) // XXX ???
|
||||
|
@ -866,40 +851,16 @@ NS_IMETHODIMP nsWindow::Update(void)
|
|||
UnqueueDraw();
|
||||
|
||||
if (!mUpdateArea->IsEmpty()) {
|
||||
|
||||
PRUint32 numRects;
|
||||
mUpdateArea->GetNumRects(&numRects);
|
||||
|
||||
// if we have 1 or more than 10 rects, just paint the bounding box otherwise
|
||||
// lets paint each rect by itself
|
||||
|
||||
if (numRects != 1 && numRects < 10) {
|
||||
nsRegionRectSet *regionRectSet = nsnull;
|
||||
|
||||
if (NS_FAILED(mUpdateArea->GetRects(®ionRectSet)))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRUint32 len;
|
||||
PRUint32 i;
|
||||
|
||||
len = regionRectSet->mRectsLen;
|
||||
|
||||
for (i=0;i<len;++i) {
|
||||
nsRegionRect *r = &(regionRectSet->mRects[i]);
|
||||
DoPaint (r->x, r->y, r->width, r->height, mUpdateArea);
|
||||
}
|
||||
|
||||
mUpdateArea->FreeRects(regionRectSet);
|
||||
|
||||
mUpdateArea->SetTo(0, 0, 0, 0);
|
||||
return NS_OK;
|
||||
} else {
|
||||
PRInt32 x, y, w, h;
|
||||
mUpdateArea->GetBoundingBox(&x, &y, &w, &h);
|
||||
DoPaint (x, y, w, h, mUpdateArea);
|
||||
// Watch out for updates occuring during DoPaint. We must clear
|
||||
// mUpdateArea before we go into DoPaint.
|
||||
nsCOMPtr<nsIRegion> updateArea = mUpdateArea;
|
||||
mUpdateArea = do_CreateInstance(kRegionCID);
|
||||
if (mUpdateArea) {
|
||||
mUpdateArea->Init();
|
||||
mUpdateArea->SetTo(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
DoPaint(updateArea);
|
||||
} else {
|
||||
// g_print("nsWidget::Update(this=%p): avoided update of empty area\n", this);
|
||||
}
|
||||
|
|
|
@ -126,8 +126,7 @@ public:
|
|||
|
||||
void QueueDraw();
|
||||
void UnqueueDraw();
|
||||
void DoPaint(PRInt32 x, PRInt32 y, PRInt32 width, PRInt32 height,
|
||||
nsIRegion *aClipRegion);
|
||||
void DoPaint(nsIRegion *aClipRegion);
|
||||
static gboolean UpdateIdle (gpointer data);
|
||||
// get the toplevel window for this widget
|
||||
virtual GtkWindow *GetTopLevelWindow(void);
|
||||
|
|
|
@ -82,6 +82,7 @@ nsCommonWidget::InitPaintEvent(nsPaintEvent &aEvent)
|
|||
aEvent.eventStructType = NS_PAINT_EVENT;
|
||||
aEvent.message = NS_PAINT;
|
||||
aEvent.widget = NS_STATIC_CAST(nsIWidget *, this);
|
||||
aEvent.region = nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1677,12 +1677,13 @@ void nsWindow::UpdateWidget(nsRect& aRect, nsIRenderingContext* aContext)
|
|||
|
||||
// initialize the paint event
|
||||
nsPaintEvent paintEvent;
|
||||
paintEvent.eventStructType = NS_PAINT_EVENT; // nsEvent
|
||||
paintEvent.message = NS_PAINT;
|
||||
paintEvent.widget = this; // nsGUIEvent
|
||||
paintEvent.nativeMsg = NULL;
|
||||
paintEvent.renderingContext = aContext; // nsPaintEvent
|
||||
paintEvent.rect = &aRect;
|
||||
paintEvent.eventStructType = NS_PAINT_EVENT; // nsEvent
|
||||
paintEvent.message = NS_PAINT;
|
||||
paintEvent.widget = this; // nsGUIEvent
|
||||
paintEvent.nativeMsg = NULL;
|
||||
paintEvent.renderingContext = aContext; // nsPaintEvent
|
||||
paintEvent.rect = &aRect;
|
||||
paintEvent.region = nsnull;
|
||||
|
||||
// draw the widget
|
||||
StartDraw(aContext);
|
||||
|
|
|
@ -2788,6 +2788,7 @@ PRBool nsWindow::OnPaint()
|
|||
rect.width = rcl.xRight - rcl.xLeft;
|
||||
rect.height = rcl.yTop - rcl.yBottom;
|
||||
event.rect = ▭
|
||||
event.region = nsnull;
|
||||
event.eventStructType = NS_PAINT_EVENT;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
|
|
|
@ -849,6 +849,7 @@ void nsWindow::RawDrawFunc( PtWidget_t * pWidget, PhTile_t * damage )
|
|||
|
||||
pWin->InitEvent(pev, NS_PAINT);
|
||||
pev.eventStructType = NS_PAINT_EVENT;
|
||||
pev.region = nsnull;
|
||||
pev.renderingContext = nsnull;
|
||||
pev.renderingContext = pWin->GetRenderingContext();
|
||||
for( dmg = new_damage; dmg; dmg = dmg->next ) {
|
||||
|
@ -866,6 +867,7 @@ void nsWindow::RawDrawFunc( PtWidget_t * pWidget, PhTile_t * damage )
|
|||
pev.point.x = nsDmg.x;
|
||||
pev.point.y = nsDmg.y;
|
||||
pev.rect = &nsDmg;
|
||||
pev.region = nsnull;
|
||||
|
||||
if( pev.renderingContext ) {
|
||||
nsIRegion *ClipRegion = pWin->GetRegion( );
|
||||
|
|
|
@ -5202,8 +5202,11 @@ PRBool nsWindow::OnPaint()
|
|||
ps.rcPaint.top,
|
||||
ps.rcPaint.right - ps.rcPaint.left,
|
||||
ps.rcPaint.bottom - ps.rcPaint.top);
|
||||
event.rect = ▭
|
||||
event.eventStructType = NS_PAINT_EVENT;
|
||||
event.region = nsnull;
|
||||
event.rect = ▭
|
||||
// Should probably pass in a real region here, using GetRandomRgn
|
||||
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/clipping_4q0e.asp
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
debug_DumpPaintEvent(stdout,
|
||||
|
|
Загрузка…
Ссылка в новой задаче