added Get/SetScrollableRoot() to nsIViewManager. fixed bug where maximizing

window would cause junk to be shown below/to the right of the real content
if the document was scrolled towards bottom/right. fixed flashing scrollbar
problem. made quality control work again.
This commit is contained in:
michaelp%netscape.com 1999-02-16 00:57:06 +00:00
parent 6992018f6f
commit f8b4bc0d49
5 changed files with 538 additions and 138 deletions

View File

@ -28,6 +28,7 @@ class nsIRegion;
class nsIEvent;
class nsIPresContext;
class nsIView;
class nsIScrollableView;
class nsIWidget;
struct nsRect;
@ -355,6 +356,22 @@ public:
*/
NS_IMETHOD EnableRefresh(void) = 0;
/**
* set the view that is is considered to be the root scrollable
* view for the document.
* @param aScrollable root scrollable view
* @return error status
*/
NS_IMETHOD SetRootScrollableView(nsIScrollableView *aScrollable) = 0;
/**
* get the view that is is considered to be the root scrollable
* view for the document.
* @param aScrollable out parameter for root scrollable view
* @return error status
*/
NS_IMETHOD GetRootScrollableView(nsIScrollableView **aScrollable) = 0;
/**
* Display the specified view. Used when printing.
*/

View File

@ -152,7 +152,7 @@ public:
NS_IMETHOD Paint(nsIRenderingContext& rc, const nsRect& rect,
PRUint32 aPaintFlags, PRBool &Result);
void Show(PRBool aShow);
void Show(PRBool aShow, PRBool aRethink);
PRBool mShowQuality;
nsContentQuality mQuality;
@ -181,17 +181,15 @@ NS_IMETHODIMP CornerView :: ShowQuality(PRBool aShow)
if (mShow == PR_FALSE)
{
if (mVis == nsViewVisibility_kShow)
if (mShowQuality == PR_FALSE)
mViewManager->SetViewVisibility(this, nsViewVisibility_kHide);
else
mViewManager->SetViewVisibility(this, nsViewVisibility_kShow);
nscoord dimx, dimy;
nsIScrollableView *par;
//this will force the scrolling view to recalc the scrollbar sizes... MMP
mParent->GetDimensions(&dimx, &dimy);
mParent->SetDimensions(dimx, dimy);
if (NS_OK == mParent->QueryInterface(kIScrollableViewIID, (void **)&par))
par->ComputeContainerSize();
}
mViewManager->UpdateView(this, nsnull, NS_VMREFRESH_IMMEDIATE);
@ -211,7 +209,7 @@ NS_IMETHODIMP CornerView :: SetQuality(nsContentQuality aQuality)
return NS_OK;
}
void CornerView :: Show(PRBool aShow)
void CornerView :: Show(PRBool aShow, PRBool aRethink)
{
if (mShow != aShow)
{
@ -222,12 +220,13 @@ void CornerView :: Show(PRBool aShow)
else if (mShowQuality == PR_FALSE)
mViewManager->SetViewVisibility(this, nsViewVisibility_kHide);
nscoord dimx, dimy;
if (PR_TRUE == aRethink)
{
nsIScrollableView *par;
//this will force the scrolling view to recalc the scrollbar sizes... MMP
mParent->GetDimensions(&dimx, &dimy);
mParent->SetDimensions(dimx, dimy);
if (NS_OK == mParent->QueryInterface(kIScrollableViewIID, (void **)&par))
par->ComputeContainerSize();
}
}
}
@ -403,9 +402,19 @@ NS_IMETHODIMP nsScrollingView :: SetDimensions(nscoord width, nscoord height, PR
// Set our bounds and size our widget if we have one
nsView::SetDimensions(width, height, aPaint);
#if 0
//this will fix the size of the thumb when we resize the root window,
//but unfortunately it will also cause scrollbar flashing. so long as
//all resize operations happen through the viewmanager, this is not
//an issue. we'll see. MMP
ComputeContainerSize();
#endif
// Determine how much space is actually taken up by the scrollbars
if (mHScrollBarView && ViewIsShowing(mHScrollBarView))
showHorz = NSToCoordRound(scrollHeight);
if (mVScrollBarView && ViewIsShowing(mVScrollBarView))
showVert = NSToCoordRound(scrollWidth);
@ -413,12 +422,6 @@ NS_IMETHODIMP nsScrollingView :: SetDimensions(nscoord width, nscoord height, PR
clipRect.SetRect(0, 0, width - showVert, height - showHorz);
clipRect.Deflate(mInsets);
//this will fix the size of the thumb when we resize the root window,
//but unfortunately it will also cause scrollbar flashing. so long as
//all resize operations happen through the viewmanager, this is not
//an issue. we'll see. MMP
ComputeContainerSize();
// Size and position the clip view
if (nsnull != mClipView)
mClipView->SetBounds(clipRect, aPaint);
@ -929,6 +932,7 @@ NS_IMETHODIMP nsScrollingView :: ComputeContainerSize()
nscoord offx, offy;
float scale;
nsRect controlRect(0, 0, mBounds.width, mBounds.height);
controlRect.Deflate(mInsets);
mViewManager->GetDeviceContext(px);
@ -978,23 +982,34 @@ NS_IMETHODIMP nsScrollingView :: ComputeContainerSize()
//now update the scroller position for the new size
PRUint32 oldpos = 0;
scrollv->GetPosition(oldpos);
float p2t;
PRInt32 availheight;
scrollv->GetPosition(oldpos);
px->GetDevUnitsToAppUnits(p2t);
availheight = controlRect.height - ((nsnull != scrollh) ? hheight : 0);
// XXX Check for 0 initial size. This is really indicative
// of a problem.
if (0 == oldsizey) {
if (0 == oldsizey)
mOffsetY = 0;
}
else {
else
{
mOffsetY = NSIntPixelsToTwips(NSTwipsToIntPixels(nscoord(((float)oldpos * mSizeY) / oldsizey), scale), p2t);
if ((mSizeY - mOffsetY) < availheight)
{
mOffsetY = mSizeY - availheight;
if (mOffsetY < 0)
mOffsetY = 0;
}
}
dy = NSTwipsToIntPixels((offy - mOffsetY), scale);
scrollv->SetParameters(mSizeY, controlRect.height - ((nsnull != scrollh) ? hheight : 0),
scrollv->SetParameters(mSizeY, availheight,
mOffsetY, NSIntPointsToTwips(12));
}
else
@ -1005,6 +1020,7 @@ NS_IMETHODIMP nsScrollingView :: ComputeContainerSize()
dy = NSTwipsToIntPixels(offy, scale);
scrollv->SetPosition(0); // make sure thumb is at the top
if (mScrollPref == nsScrollPreference_kAlwaysScroll)
{
mVScrollBarView->SetVisibility(nsViewVisibility_kShow);
@ -1045,29 +1061,35 @@ NS_IMETHODIMP nsScrollingView :: ComputeContainerSize()
//now update the scroller position for the new size
PRUint32 oldpos = 0;
scrollh->GetPosition(oldpos);
float p2t;
PRInt32 availwidth;
scrollh->GetPosition(oldpos);
px->GetDevUnitsToAppUnits(p2t);
availwidth = controlRect.width - ((nsnull != scrollv) ? vwidth : 0);
// XXX Check for 0 initial size. This is really indicative
// of a problem.
if (0 == oldsizex) {
if (0 == oldsizex)
mOffsetX = 0;
}
else {
else
{
mOffsetX = NSIntPixelsToTwips(NSTwipsToIntPixels(nscoord(((float)oldpos * mSizeX) / oldsizex), scale), p2t);
if ((mSizeX - mOffsetX) < availwidth)
{
mOffsetX = mSizeX - availwidth;
if (mOffsetX < 0)
mOffsetX = 0;
}
}
dx = NSTwipsToIntPixels((offx - mOffsetX), scale);
scrollh->SetParameters(mSizeX, controlRect.width - ((nsnull != scrollv) ? vwidth : 0),
scrollh->SetParameters(mSizeX, availwidth,
mOffsetX, NSIntPointsToTwips(12));
// //now make the vertical scroll region account for this scrollbar
//
// if (nsnull != scrollv)
// scrollv->SetParameters(mSizeY, mBounds.height - hheight, mOffsetY, NSIntPointsToTwips(12));
}
else
{
@ -1077,6 +1099,7 @@ NS_IMETHODIMP nsScrollingView :: ComputeContainerSize()
dx = NSTwipsToIntPixels(offx, scale);
scrollh->SetPosition(0); // make sure thumb is all the way to the left
if (mScrollPref == nsScrollPreference_kAlwaysScroll)
{
mHScrollBarView->SetVisibility(nsViewVisibility_kShow);
@ -1112,9 +1135,9 @@ NS_IMETHODIMP nsScrollingView :: ComputeContainerSize()
{
if (mHScrollBarView && ViewIsShowing(mHScrollBarView) &&
mVScrollBarView && ViewIsShowing(mVScrollBarView))
((CornerView *)mCornerView)->Show(PR_TRUE);
((CornerView *)mCornerView)->Show(PR_TRUE, PR_FALSE);
else
((CornerView *)mCornerView)->Show(PR_FALSE);
((CornerView *)mCornerView)->Show(PR_FALSE, PR_FALSE);
}
// now we can release the vertical scroller if there was one...
@ -1156,7 +1179,7 @@ NS_IMETHODIMP nsScrollingView :: ComputeContainerSize()
}
if (nsnull != mCornerView)
((CornerView *)mCornerView)->Show(PR_FALSE);
((CornerView *)mCornerView)->Show(PR_FALSE, PR_FALSE);
mOffsetX = mOffsetY = 0;
mSizeX = mSizeY = 0;
@ -1367,40 +1390,72 @@ void nsScrollingView :: AdjustChildWidgets(nsScrollingView *aScrolling, nsIView
void nsScrollingView :: UpdateScrollControls(PRBool aPaint)
{
nsRect clipRect;
nsSize cornerSize = nsSize(0, 0);
nsSize visCornerSize = nsSize(0, 0);
nsPoint cornerPos = nsPoint(0, 0);
nsViewVisibility vertVis = nsViewVisibility_kHide;
nsViewVisibility horzVis = nsViewVisibility_kHide;
if (nsnull != mClipView)
{
mClipView->GetBounds(clipRect);
// Position the corner view
if (nsnull != mVScrollBarView)
mVScrollBarView->GetVisibility(vertVis);
if (nsnull != mHScrollBarView)
mHScrollBarView->GetVisibility(horzVis);
if (nsnull != mCornerView)
{
nsSize cornerSize;
nsViewVisibility cornerVis;
mCornerView->GetDimensions(&cornerSize.width, &cornerSize.height);
mCornerView->SetBounds(clipRect.XMost(), clipRect.YMost(), cornerSize.width,
cornerSize.height, aPaint);
mCornerView->GetVisibility(cornerVis);
if (cornerVis == nsViewVisibility_kShow)
visCornerSize = cornerSize;
if (vertVis == nsViewVisibility_kShow)
visCornerSize.width = 0;
if (horzVis == nsViewVisibility_kShow)
visCornerSize.height = 0;
}
// Size and position the vertical scrollbar
if (nsnull != mVScrollBarView)
{
nsSize sbSize;
nsSize vertSize;
mVScrollBarView->GetDimensions(&sbSize.width, &sbSize.height);
mVScrollBarView->SetBounds(clipRect.XMost(), clipRect.y, sbSize.width,
clipRect.height, aPaint);
mVScrollBarView->GetDimensions(&vertSize.width, &vertSize.height);
mVScrollBarView->SetBounds(clipRect.XMost(), clipRect.y, vertSize.width,
clipRect.height - visCornerSize.height, aPaint);
if (vertVis == nsViewVisibility_kShow)
cornerPos.x = clipRect.XMost();
else
cornerPos.x = clipRect.XMost() - cornerSize.width;
}
// Size and position the horizontal scrollbar
if (nsnull != mHScrollBarView)
{
nsSize sbSize;
mHScrollBarView->GetDimensions(&sbSize.width, &sbSize.height);
mHScrollBarView->SetBounds(clipRect.x, clipRect.YMost(), clipRect.width,
sbSize.height, aPaint);
nsSize horzSize;
mHScrollBarView->GetDimensions(&horzSize.width, &horzSize.height);
mHScrollBarView->SetBounds(clipRect.x, clipRect.YMost(), clipRect.width - visCornerSize.width,
horzSize.height, aPaint);
if (horzVis == nsViewVisibility_kShow)
cornerPos.y = clipRect.YMost();
else
cornerPos.y = clipRect.YMost() - cornerSize.height;
}
// Position the corner view
if (nsnull != mCornerView)
mCornerView->SetPosition(cornerPos.x, cornerPos.y);
}
}

View File

@ -875,6 +875,7 @@ NS_IMETHODIMP nsView :: SetDimensions(nscoord width, nscoord height, PRBool aPai
{
mBounds.SizeTo(width, height);
#if 0
if (nsnull != mParent)
{
nsIScrollableView *scroller;
@ -892,6 +893,7 @@ NS_IMETHODIMP nsView :: SetDimensions(nscoord width, nscoord height, PRBool aPai
scroller->ComputeContainerSize();
}
}
#endif
if (nsnull != mWindow)
{

View File

@ -26,6 +26,7 @@
#include "nsIRegion.h"
#include "nsView.h"
#include "nsIScrollbar.h"
#include "nsIBlender.h"
static NS_DEFINE_IID(kIScrollableViewIID, NS_ISCROLLABLEVIEW_IID);
static NS_DEFINE_IID(kIScrollbarIID, NS_ISCROLLBAR_IID);
@ -37,6 +38,8 @@ static const PRBool gsDebug = PR_FALSE;
//#define NO_DOUBLE_BUFFER
//#define NEW_COMPOSITOR
#define FLATVIEW_INC 3
static void vm_timer_callback(nsITimer *aTimer, void *aClosure)
{
nsViewManager *vm = (nsViewManager *)aClosure;
@ -81,11 +84,15 @@ nsViewManager :: ~nsViewManager()
NS_IF_RELEASE(mRootWindow);
mRootScrollable = nsnull;
--mVMCount;
NS_ASSERTION(!(mVMCount < 0), "underflow of viewmanagers");
if ((0 == mVMCount) && (nsnull != mDrawingSurface))
if ((0 == mVMCount) &&
((nsnull != mDrawingSurface) || (nsnull != gOffScreen) ||
(nsnull != gRed) || (nsnull != gBlue)))
{
nsIRenderingContext *rc;
@ -99,11 +106,25 @@ nsViewManager :: ~nsViewManager()
if (NS_OK == rv)
{
rc->DestroyDrawingSurface(mDrawingSurface);
if (nsnull != mDrawingSurface)
rc->DestroyDrawingSurface(mDrawingSurface);
if (nsnull != gOffScreen)
rc->DestroyDrawingSurface(gOffScreen);
if (nsnull != gRed)
rc->DestroyDrawingSurface(gRed);
if (nsnull != gBlue)
rc->DestroyDrawingSurface(gBlue);
NS_RELEASE(rc);
}
mDrawingSurface = nsnull;
gOffScreen = nsnull;
gRed = nsnull;
gBlue = nsnull;
}
mObserver = nsnull;
@ -113,7 +134,7 @@ nsViewManager :: ~nsViewManager()
{
PRInt32 cnt = mFlatViews->Count(), idx;
for (idx = 1; idx < cnt; idx += 2)
for (idx = 1; idx < cnt; idx += FLATVIEW_INC)
{
nsRect *rect = (nsRect *)mFlatViews->ElementAt(idx);
@ -452,19 +473,51 @@ void nsViewManager :: Refresh(nsIView *aView, nsIRenderingContext *aContext, con
mPainting = PR_FALSE;
}
//states
#define FRONT_TO_BACK_RENDER 1
#define FRONT_TO_BACK_ACCUMULATE 2
#define BACK_TO_FRONT_TRANS 3
#define BACK_TO_FRONT_OPACITY 4
#define COMPOSITION_DONE 5
//bit shifts
#define TRANS_PROPERTY_TRANS 0
#define TRANS_PROPERTY_OPACITY 1
//flat view flags
#define VIEW_INCLUDED 0x0001
void nsViewManager :: RenderViews(nsIView *aRootView, nsIRenderingContext& aRC, const nsRect& aRect, PRBool &aResult)
{
#ifdef NEW_COMPOSITOR
PRInt32 flatlen = 0, cnt;
PRInt32 flatlen = 0, cnt;
PRInt32 state = FRONT_TO_BACK_RENDER;
PRInt32 transprop;
nsRect backfrontrect;
nsRect accumrect;
PRInt32 increment = FLATVIEW_INC;
PRInt32 loopstart = 0;
PRInt32 loopend;
PRInt32 accumstart;
float t2p;
nsDrawingSurface origsurf;
nsIRegion *transrgn = nsnull;
nsIRegion *temprgn = nsnull;
nsIRegion *rcrgn = nsnull;
if (nsnull != aRootView)
FlattenViewTree(aRootView, &flatlen);
FlattenViewTree(aRootView, &flatlen, &aRect);
loopend = flatlen;
mContext->GetAppUnitsToDevUnits(t2p);
aRC.GetDrawingSurface(&origsurf);
#if 0
printf("flatlen %d\n", flatlen);
for (cnt = 0; cnt < flatlen; cnt += 2)
for (cnt = 0; cnt < flatlen; cnt += FLATVIEW_INC)
{
nsRect *rect;
printf("view: %x\n", mFlatViews->ElementAt(cnt));
@ -478,57 +531,229 @@ for (cnt = 0; cnt < flatlen; cnt += 2)
}
#endif
for (cnt = 0; cnt < flatlen; cnt += 2)
while (state != COMPOSITION_DONE)
{
nsIView *curview = (nsIView *)mFlatViews->ElementAt(cnt);
nsRect *currect = (nsRect *)mFlatViews->ElementAt(cnt + 1);
if ((nsnull != curview) && (nsnull != currect))
for (cnt = loopstart; (increment > 0) ? (cnt < loopend) : (cnt > loopend); cnt += increment)
{
nsIWidget *widget;
PRBool hasWidget = PR_FALSE;
curview->GetWidget(widget);
if (nsnull != widget)
nsIView *curview = (nsIView *)mFlatViews->ElementAt(cnt);
nsRect *currect = (nsRect *)mFlatViews->ElementAt(cnt + 1);
PRUint32 curflags = (PRUint32)mFlatViews->ElementAt(cnt + 2);
if ((nsnull != curview) && (nsnull != currect))
{
void *nativewidget;
PRBool hasWidget = DoesViewHaveNativeWidget(*curview);
nativewidget = widget->GetNativeData(NS_NATIVE_WIDGET);
if ((PR_FALSE == hasWidget) || ((PR_TRUE == hasWidget) && (cnt == (flatlen - FLATVIEW_INC))))
{
PRBool trans;
float opacity;
NS_RELEASE(widget);
curview->HasTransparency(trans);
curview->GetOpacity(opacity);
if (nsnull != nativewidget)
hasWidget = PR_TRUE;
switch (state)
{
default:
case FRONT_TO_BACK_RENDER:
if ((PR_TRUE == trans) || (opacity < 1.0f))
{
//need to finish using back to front till this point
transprop = (trans << TRANS_PROPERTY_TRANS) | ((opacity < 1.0f) << TRANS_PROPERTY_OPACITY);
backfrontrect = accumrect = *currect;
state = FRONT_TO_BACK_ACCUMULATE;
accumstart = cnt;
mFlatViews->ReplaceElementAt((void *)VIEW_INCLUDED, cnt + 2);
//get a snapshot of the current clip so that we can exclude areas
//already excluded in it from the transparency region
aRC.GetClipRegion(&rcrgn);
}
else
{
RenderView(curview, aRC, aRect, *currect, aResult);
if (aResult == PR_FALSE)
aRC.SetClipRect(*currect, nsClipCombine_kSubtract, aResult);
}
break;
case FRONT_TO_BACK_ACCUMULATE:
if ((PR_TRUE == backfrontrect.Intersects(*currect)) &&
((PR_TRUE == trans) || (opacity < 1.0f)))
{
transprop |= (trans << TRANS_PROPERTY_TRANS) | ((opacity < 1.0f) << TRANS_PROPERTY_OPACITY);
accumrect.UnionRect(*currect, accumrect);
mFlatViews->ReplaceElementAt((void *)VIEW_INCLUDED, cnt + 2);
}
break;
case BACK_TO_FRONT_TRANS:
if (PR_TRUE == accumrect.Intersects(*currect))
{
PRBool clipstate;
RenderView(curview, aRC, aRect, *currect, clipstate);
//if this view is transparent, it has been accounted
//for, so we never have to look at it again.
if ((PR_TRUE == trans) && (curflags & VIEW_INCLUDED))
{
mFlatViews->ReplaceElementAt(nsnull, cnt);
mFlatViews->ReplaceElementAt(nsnull, cnt + 2);
}
}
break;
case BACK_TO_FRONT_OPACITY:
if (PR_TRUE == accumrect.Intersects(*currect))
{
PRBool clipstate;
if (opacity == 1.0f)
RenderView(curview, aRC, aRect, *currect, clipstate);
else
{
aRC.SelectOffScreenDrawingSurface(gRed);
RenderView(curview, aRC, aRect, *currect, clipstate);
nsRect brect;
brect.x = brect.y = 0;
brect.width = accumrect.width;
brect.height = accumrect.height;
static NS_DEFINE_IID(kBlenderCID, NS_BLENDER_CID);
static NS_DEFINE_IID(kIBlenderIID, NS_IBLENDER_IID);
nsIBlender *blender = nsnull;
nsresult rv;
rv = nsRepository::CreateInstance(kBlenderCID, nsnull, kIBlenderIID, (void **)&blender);
if (NS_OK == rv)
{
nscoord width, height;
width = NSToCoordRound(currect->width * t2p);
height = NSToCoordRound(currect->height * t2p);
blender->Init(mContext);
blender->Blend(0, 0, width, height, gRed, gOffScreen, 0, 0, opacity);
NS_RELEASE(blender);
}
aRC.SelectOffScreenDrawingSurface(gOffScreen);
}
//if this view is transparent or non-opaque, it has
//been accounted for, so we never have to look at it again.
if (((PR_TRUE == trans) || (opacity < 1.0f)) && (curflags & VIEW_INCLUDED))
{
mFlatViews->ReplaceElementAt(nsnull, cnt);
mFlatViews->ReplaceElementAt(nsnull, cnt + 2);
}
}
break;
}
}
else
aRC.SetClipRect(*currect, nsClipCombine_kSubtract, aResult);
if (aResult == PR_TRUE)
{
state = COMPOSITION_DONE;
break;
}
}
}
if ((PR_FALSE == hasWidget) || ((PR_TRUE == hasWidget) && (cnt == (flatlen - 2))))
{
nsRect lrect, drect, grect;
switch (state)
{
case FRONT_TO_BACK_ACCUMULATE:
loopstart = cnt - FLATVIEW_INC;
loopend = accumstart - FLATVIEW_INC;
increment = -FLATVIEW_INC;
state = (transprop & (1 << TRANS_PROPERTY_OPACITY)) ? BACK_TO_FRONT_OPACITY : BACK_TO_FRONT_TRANS;
grect = *currect;
curview->GetBounds(lrect);
if (state == BACK_TO_FRONT_OPACITY)
{
PRInt32 w, h;
nsRect bitrect;
aRC.PushState();
//prepare offscreen buffers
aRC.Translate(grect.x, grect.y);
w = NSToCoordRound(accumrect.width * t2p);
h = NSToCoordRound(accumrect.height * t2p);
drect.IntersectRect(aRect, grect);
if ((w > gBlendWidth) || (h > gBlendHeight))
{
bitrect.x = bitrect.y = 0;
bitrect.width = w;
bitrect.height = h;
drect.x -= grect.x;
drect.y -= grect.y;
if (nsnull != gOffScreen)
{
aRC.DestroyDrawingSurface(gOffScreen);
gOffScreen = nsnull;
}
curview->Paint(aRC, drect, NS_VIEW_FLAG_JUST_PAINT, aResult);
aRC.CreateDrawingSurface(&bitrect, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS, gOffScreen);
aRC.PopState(aResult);
if (nsnull != gRed)
{
aRC.DestroyDrawingSurface(gRed);
gRed = nsnull;
}
if (aResult == PR_FALSE)
aRC.SetClipRect(grect, nsClipCombine_kSubtract, aResult);
}
else
aRC.SetClipRect(*currect, nsClipCombine_kSubtract, aResult);
aRC.CreateDrawingSurface(&bitrect, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS, gRed);
if (aResult == PR_TRUE)
gBlendWidth = w;
gBlendHeight = h;
printf("offscr: %d, %d (%d, %d)\n", w, h, accumrect.width, accumrect.height);
}
if ((nsnull == gOffScreen) || (nsnull == gRed))
state = BACK_TO_FRONT_TRANS;
else
{
aRC.Translate(-accumrect.x, -accumrect.y);
aRC.SelectOffScreenDrawingSurface(gOffScreen);
}
}
break;
case BACK_TO_FRONT_OPACITY:
aRC.SelectOffScreenDrawingSurface(origsurf);
aRC.Translate(accumrect.x, accumrect.y);
aRC.CopyOffScreenBits(gOffScreen, 0, 0, accumrect, NS_COPYBITS_XFORM_DEST_VALUES | NS_COPYBITS_TO_BACK_BUFFER);
//falls through
case BACK_TO_FRONT_TRANS:
loopstart = accumstart + FLATVIEW_INC;
loopend = flatlen;
increment = FLATVIEW_INC;
state = FRONT_TO_BACK_RENDER;
//clip out what we just rendered
aRC.SetClipRect(accumrect, nsClipCombine_kSubtract, aResult);
//did that finish everything?
if (aResult == PR_TRUE)
state = COMPOSITION_DONE;
break;
case FRONT_TO_BACK_RENDER:
state = COMPOSITION_DONE;
break;
}
}
@ -541,6 +766,26 @@ for (cnt = 0; cnt < flatlen; cnt += 2)
#endif
}
void nsViewManager :: RenderView(nsIView *aView, nsIRenderingContext &aRC, const nsRect &aDamageRect, nsRect &aGlobalRect, PRBool &aResult)
{
nsRect drect;
NS_ASSERTION(!(nsnull == aView), "no view");
aRC.PushState();
aRC.Translate(aGlobalRect.x, aGlobalRect.y);
drect.IntersectRect(aDamageRect, aGlobalRect);
drect.x -= aGlobalRect.x;
drect.y -= aGlobalRect.y;
aView->Paint(aRC, drect, NS_VIEW_FLAG_JUST_PAINT, aResult);
aRC.PopState(aResult);
}
void nsViewManager :: UpdateDirtyViews(nsIView *aView, nsRect *aParentRect) const
{
nsRect pardamage;
@ -776,18 +1021,19 @@ NS_IMETHODIMP nsViewManager :: UpdateView(nsIView *aView, const nsRect &aRect, P
// Convert damage rect to coordinate space of containing view with
// a widget
// XXX Consolidate this code with the code above...
if (aView != widgetView)
{
// if (aView != widgetView)
// {
do
{
par->GetPosition(&x, &y);
trect.x += x;
trect.y += y;
par->GetParent(par);
if (par != widgetView)
par->GetParent(par);
}
while ((nsnull != par) && (par != widgetView));
}
// }
// Add this rect to the widgetView's dirty region.
@ -1447,11 +1693,21 @@ nsDrawingSurface nsViewManager :: GetDrawingSurface(nsIRenderingContext &aContex
NS_IMETHODIMP nsViewManager :: ShowQuality(PRBool aShow)
{
nsIScrollableView *scroller;
nsresult retval;
nsresult retval = NS_ERROR_FAILURE;
retval = mRootView->QueryInterface(kIScrollableViewIID, (void **)&scroller);
if (NS_SUCCEEDED(retval)) {
scroller->ShowQuality(aShow);
if (nsnull != mRootView)
{
nsIView *child;
mRootView->GetChild(0, child);
if (nsnull != child)
{
retval = child->QueryInterface(kIScrollableViewIID, (void **)&scroller);
if (NS_SUCCEEDED(retval))
scroller->ShowQuality(aShow);
}
}
return retval;
@ -1460,11 +1716,21 @@ NS_IMETHODIMP nsViewManager :: ShowQuality(PRBool aShow)
NS_IMETHODIMP nsViewManager :: GetShowQuality(PRBool &aResult)
{
nsIScrollableView *scroller;
nsresult retval;
nsresult retval = NS_ERROR_FAILURE;
retval = mRootView->QueryInterface(kIScrollableViewIID, (void **)&scroller);
if (NS_SUCCEEDED(retval)) {
scroller->GetShowQuality(aResult);
if (nsnull != mRootView)
{
nsIView *child;
mRootView->GetChild(0, child);
if (nsnull != child)
{
retval = child->QueryInterface(kIScrollableViewIID, (void **)&scroller);
if (NS_SUCCEEDED(retval))
scroller->GetShowQuality(aResult);
}
}
return retval;
@ -1473,12 +1739,21 @@ NS_IMETHODIMP nsViewManager :: GetShowQuality(PRBool &aResult)
NS_IMETHODIMP nsViewManager :: SetQuality(nsContentQuality aQuality)
{
nsIScrollableView *scroller;
nsresult retval;
nsresult retval = NS_ERROR_FAILURE;
retval = mRootView->QueryInterface(kIScrollableViewIID, (void **)&scroller);
if (NS_SUCCEEDED(retval))
if (nsnull != mRootView)
{
scroller->SetQuality(aQuality);
nsIView *child;
mRootView->GetChild(0, child);
if (nsnull != child)
{
retval = child->QueryInterface(kIScrollableViewIID, (void **)&scroller);
if (NS_SUCCEEDED(retval))
scroller->SetQuality(aQuality);
}
}
return retval;
@ -1611,6 +1886,18 @@ NS_IMETHODIMP nsViewManager :: EnableRefresh(void)
return NS_OK;
}
NS_IMETHODIMP nsViewManager :: SetRootScrollableView(nsIScrollableView *aScrollable)
{
mRootScrollable = aScrollable;
return NS_OK;
}
NS_IMETHODIMP nsViewManager :: GetRootScrollableView(nsIScrollableView **aScrollable)
{
*aScrollable = mRootScrollable;
return NS_OK;
}
NS_IMETHODIMP nsViewManager :: Display(nsIView* aView)
{
nsRect wrect;
@ -1658,7 +1945,7 @@ NS_IMETHODIMP nsViewManager :: Display(nsIView* aView)
return NS_OK;
}
void nsViewManager :: FlattenViewTree(nsIView *aView, PRInt32 *aIndex, nsIView *aTopView, nsVoidArray *aArray, nscoord aX, nscoord aY)
void nsViewManager :: FlattenViewTree(nsIView *aView, PRInt32 *aIndex, const nsRect *aDamageRect, nsIView *aTopView, nsVoidArray *aArray, nscoord aX, nscoord aY)
{
PRInt32 numkids, cnt;
@ -1696,22 +1983,7 @@ void nsViewManager :: FlattenViewTree(nsIView *aView, PRInt32 *aIndex, nsIView *
if (numkids > 0)
{
nsIWidget *widget;
PRBool hasWidget = PR_FALSE;
aView->GetWidget(widget);
if (nsnull != widget)
{
void *nativewidget;
nativewidget = widget->GetNativeData(NS_NATIVE_WIDGET);
NS_RELEASE(widget);
if (nsnull != nativewidget)
hasWidget = PR_TRUE;
}
PRBool hasWidget = DoesViewHaveNativeWidget(*aView);
if ((PR_FALSE == hasWidget) || ((PR_TRUE == hasWidget) && (aView == aTopView)))
{
@ -1720,29 +1992,68 @@ void nsViewManager :: FlattenViewTree(nsIView *aView, PRInt32 *aIndex, nsIView *
nsIView *child;
aView->GetChild(cnt, child);
FlattenViewTree(child, aIndex, aTopView, aArray, lrect.x, lrect.y);
FlattenViewTree(child, aIndex, aDamageRect, aTopView, aArray, lrect.x, lrect.y);
}
}
}
aArray->ReplaceElementAt(aView, (*aIndex)++);
nsViewVisibility vis;
float opacity;
PRBool overlap;
nsRect *grect = (nsRect *)aArray->ElementAt(*aIndex);
aView->GetVisibility(vis);
aView->GetOpacity(opacity);
if (nsnull == grect)
if (nsnull != aDamageRect)
overlap = lrect.Intersects(*aDamageRect);
else
overlap = PR_TRUE;
if ((nsViewVisibility_kShow == vis) && (opacity > 0.0f) && (PR_TRUE == overlap))
{
grect = new nsRect(lrect.x, lrect.y, lrect.width, lrect.height);
aArray->ReplaceElementAt(aView, (*aIndex)++);
nsRect *grect = (nsRect *)aArray->ElementAt(*aIndex);
if (nsnull == grect)
{
(*aIndex)--;
return;
grect = new nsRect(lrect.x, lrect.y, lrect.width, lrect.height);
if (nsnull == grect)
{
(*aIndex)--;
return;
}
aArray->ReplaceElementAt(grect, *aIndex);
}
else
*grect = lrect;
aArray->ReplaceElementAt(grect, *aIndex);
(*aIndex)++;
aArray->ReplaceElementAt(nsnull, (*aIndex)++);
}
else
*grect = lrect;
(*aIndex)++;
}
PRBool nsViewManager :: DoesViewHaveNativeWidget(nsIView &aView)
{
nsIWidget *widget;
PRBool retval = PR_FALSE;
aView.GetWidget(widget);
if (nsnull != widget)
{
void *nativewidget;
nativewidget = widget->GetNativeData(NS_NATIVE_WIDGET);
NS_RELEASE(widget);
if (nsnull != nativewidget)
retval = PR_TRUE;
}
return retval;
}

View File

@ -26,6 +26,7 @@
#include "nsITimer.h"
#include "prtime.h"
#include "nsVoidArray.h"
#include "nsIScrollableView.h"
class nsViewManager : public nsIViewManager
{
@ -109,6 +110,9 @@ public:
NS_IMETHOD DisableRefresh(void);
NS_IMETHOD EnableRefresh(void);
NS_IMETHOD SetRootScrollableView(nsIScrollableView *aScrollable);
NS_IMETHOD GetRootScrollableView(nsIScrollableView **aScrollable);
nsDrawingSurface GetDrawingSurface(nsIRenderingContext &aContext, nsRect& aBounds);
NS_IMETHOD Display(nsIView *aView);
@ -126,11 +130,14 @@ private:
nsIRegion *region, PRUint32 aUpdateFlags);
void Refresh(nsIView* aView, nsIRenderingContext *aContext,
const nsRect *rect, PRUint32 aUpdateFlags);
void FlattenViewTree(nsIView *aView, PRInt32 *aIndex,
nsIView *aTopView = nsnull, nsVoidArray *aArray = nsnull,
nscoord aX = 0, nscoord aY = 0);
void RenderViews(nsIView *aRootView, nsIRenderingContext& aRC, const nsRect& aRect,
PRBool &aResult);
void RenderView(nsIView *aView, nsIRenderingContext &aRC,
const nsRect &aDamageRect, nsRect &aGlobalRect, PRBool &aResult);
void FlattenViewTree(nsIView *aView, PRInt32 *aIndex, const nsRect *aDamageRect = nsnull,
nsIView *aTopView = nsnull, nsVoidArray *aArray = nsnull,
nscoord aX = 0, nscoord aY = 0);
PRBool DoesViewHaveNativeWidget(nsIView &aView);
nsIDeviceContext *mContext;
@ -144,11 +151,19 @@ private:
nsIView *mKeyGrabber;
PRInt32 mUpdateCnt;
nsVoidArray *mFlatViews;
nsIScrollableView *mRootScrollable;
static PRUint32 mVMCount; //number of viewmanagers
static nsDrawingSurface mDrawingSurface; //single drawing surface
static nsRect mDSBounds; //for all VMs
//blending buffers
nsDrawingSurface gOffScreen;
nsDrawingSurface gRed;
nsDrawingSurface gBlue;
PRInt32 gBlendWidth;
PRInt32 gBlendHeight;
public:
//these are public so that our timer callback can poke them.
nsITimer *mTimer;