From b023404ef962e087f3181feeb721176d3c90fd08 Mon Sep 17 00:00:00 2001 From: "roc+%cs.cmu.edu" Date: Tue, 24 Jun 2003 01:00:46 +0000 Subject: [PATCH] Bug 109772. Cleanup views. Promote certain members of nsView and nsViewManager to stack variables. Provide non-COM versions of, and deprecate COM usage of, nsIView methods HasWidget, GetWidget, GetFloating, GetParent, GetFirstChild, GetNextSibling, GetOpacity, GetClientData, GetVisibility, GetViewManager, GetZIndex, GetPosition, and GetBounds. r+sr=dbaron git-svn-id: svn://10.0.0.236/trunk@144076 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/view/public/nsIView.h | 138 ++++++++-- mozilla/view/src/nsScrollPortView.cpp | 11 +- mozilla/view/src/nsView.cpp | 4 +- mozilla/view/src/nsView.h | 75 ++---- mozilla/view/src/nsViewManager.cpp | 366 +++++++++++--------------- mozilla/view/src/nsViewManager.h | 41 ++- 6 files changed, 313 insertions(+), 322 deletions(-) diff --git a/mozilla/view/public/nsIView.h b/mozilla/view/public/nsIView.h index e50d0611e30..2f413d00379 100644 --- a/mozilla/view/public/nsIView.h +++ b/mozilla/view/public/nsIView.h @@ -40,10 +40,14 @@ #include "nsISupports.h" #include "nsCoord.h" +#include "nsRect.h" +#include "nsPoint.h" #include #include "nsIWidget.h" class nsIViewManager; +class nsViewManager; +class nsView; struct nsRect; // Enumerated type to indicate the visibility of a layer. @@ -60,6 +64,47 @@ enum nsViewVisibility { { 0xf0a21c40, 0xa7e1, 0x11d1, \ { 0xa8, 0x24, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } } +//Flag to determine whether the view will check if events can be handled +//by its children or just handle the events itself +#define NS_VIEW_FLAG_DONT_CHECK_CHILDREN 0x0001 + +// indicates that the view is or contains a placeholder view +#define NS_VIEW_FLAG_CONTAINS_PLACEHOLDER 0x0002 + +//the view is transparent +#define NS_VIEW_FLAG_TRANSPARENT 0x0004 + +//indicates that the view should not be bitblt'd when moved +//or scrolled and instead must be repainted +#define NS_VIEW_FLAG_DONT_BITBLT 0x0010 + +// indicates that the view is using auto z-indexing +#define NS_VIEW_FLAG_AUTO_ZINDEX 0x0020 + +// indicates that the view is a floating view. +#define NS_VIEW_FLAG_FLOATING 0x0040 + +// set if our widget resized. +#define NS_VIEW_FLAG_WIDGET_RESIZED 0x0080 + +// set if our widget moved. +#define NS_VIEW_FLAG_WIDGET_MOVED 0x0100 +#define NS_VIEW_FLAG_CLIPCHILDREN 0x0200 + +// if set it indicates that this view should be +// displayed above z-index:auto views if this view +// is z-index:auto also +#define NS_VIEW_FLAG_TOPMOST 0x0400 + +struct nsViewZIndex { + PRBool mIsAuto; + PRInt32 mZIndex; + PRBool mIsTopmost; + + nsViewZIndex(PRBool aIsAuto, PRInt32 aZIndex, PRBool aIsTopmost) + : mIsAuto(aIsAuto), mZIndex(aZIndex), mIsTopmost(aIsTopmost) {} +}; + //---------------------------------------------------------------------- /** @@ -113,7 +158,8 @@ public: * view manager from somewhere else, do that instead. * @result the view manager */ - NS_IMETHOD GetViewManager(nsIViewManager *&aViewMgr) const = 0; + nsIViewManager* GetViewManager() const + { return NS_REINTERPRET_CAST(nsIViewManager*, mViewManager); } /** * Called to get the position of a view. @@ -122,7 +168,12 @@ public: * @param x out parameter for x position * @param y out parameter for y position */ - NS_IMETHOD GetPosition(nscoord *aX, nscoord *aY) const = 0; + nsPoint GetPosition() const { + // this assertion should go away once we're confident that it's not needed + NS_ASSERTION(!IsRoot() || (mPosX == 0 && mPosY == 0), + "root views should always have explicit position of (0,0)"); + return nsPoint(mPosX, mPosY); + } /** * Called to get the dimensions and position of the view's bounds. @@ -131,25 +182,31 @@ public: * if the view has content above or to the left of its origin. * @param aBounds out parameter for bounds */ - NS_IMETHOD GetBounds(nsRect &aBounds) const = 0; + nsRect GetBounds() const { + // this assertion should go away once we're confident that it's not needed + NS_ASSERTION(!IsRoot() || (mDimBounds.x == 0 && mDimBounds.y == 0), + "root views should always have explicit position of (0,0)"); + return mDimBounds; + } /** * Called to query the visibility state of a view. * @result current visibility state */ - NS_IMETHOD GetVisibility(nsViewVisibility &aVisibility) const = 0; + nsViewVisibility GetVisibility() const { return mVis; } /** * Called to query the z-index of a view. * The z-index is relative to all siblings of the view. - * @param aAuto PR_TRUE if the view is zindex:auto - * @param aZIndex explicit z-index value. - * @param aTopMost used when this view is zindex:auto - * PR_TRUE if the view is topmost when compared - * with another z-index:auto view - * + * @result mZIndex: explicit z-index value or 0 if none is set + * mIsAuto: PR_TRUE if the view is zindex:auto + * mIsTopMost: used when this view is zindex:auto + * PR_TRUE if the view is topmost when compared + * with another z-index:auto view */ - NS_IMETHOD GetZIndex(PRBool &aAuto, PRInt32 &aZIndex, PRBool &aTopMost) const = 0; + nsViewZIndex GetZIndex() const { return nsViewZIndex((mVFlags & NS_VIEW_FLAG_AUTO_ZINDEX) != 0, + mZIndex, + (mVFlags & NS_VIEW_FLAG_TOPMOST) != 0); } /** * Get whether the view "floats" above all other views, @@ -159,25 +216,25 @@ public: * views that need to be drawn in front of all other views. * @result PR_TRUE if the view floats, PR_FALSE otherwise. */ - NS_IMETHOD GetFloating(PRBool &aFloatingView) const = 0; + PRBool GetFloating() const { return (mVFlags & NS_VIEW_FLAG_FLOATING) != 0; } /** * Called to query the parent of the view. * @result view's parent */ - NS_IMETHOD GetParent(nsIView *&aParent) const = 0; + nsIView* GetParent() const { return NS_REINTERPRET_CAST(nsIView*, mParent); } /** * The view's first child is the child which is earliest in document order. * @result first child */ - NS_IMETHOD GetFirstChild(nsIView* &aChild) const = 0; + nsIView* GetFirstChild() const { return NS_REINTERPRET_CAST(nsIView*, mFirstChild); } /** * Called to query the next sibling of the view. * @result view's next sibling */ - NS_IMETHOD GetNextSibling(nsIView *&aNextSibling) const = 0; + nsIView* GetNextSibling() const { return NS_REINTERPRET_CAST(nsIView*, mNextSibling); } /** * Note: This didn't exist in 4.0. Called to get the opacity of a view. @@ -185,15 +242,7 @@ public: * completely opaque. * @result view's opacity value */ - NS_IMETHOD GetOpacity(float &aOpacity) const = 0; - - /** - * Used to ask a view if it has any areas within its bounding box - * that are transparent. This is not the same as opacity - opacity can - * be set externally, transparency is a quality of the view itself. - * @result Returns PR_TRUE if there are transparent areas, PR_FALSE otherwise. - */ - NS_IMETHOD HasTransparency(PRBool &aTransparent) const = 0; + float GetOpacity() const { return mOpacity; } /** * Set the view's link to client owned data. @@ -205,7 +254,7 @@ public: * Query the view for it's link to client owned data. * @result data associated with view or nsnull if there is none. */ - NS_IMETHOD GetClientData(void *&aData) const = 0; + void* GetClientData() const { return mClientData; } /** * Get the nearest widget in this view or a parent of this view and @@ -246,13 +295,12 @@ public: * @param aWidget out parameter for widget that this view contains, * or nsnull if there is none. */ - NS_IMETHOD GetWidget(nsIWidget *&aWidget) const = 0; + nsIWidget* GetWidget() const { return mWindow; } /** * Returns PR_TRUE if the view has a widget associated with it. - * @param aHasWidget out parameter that indicates whether a view has a widget. */ - NS_IMETHOD HasWidget(PRBool *aHasWidget) const = 0; + PRBool HasWidget() const { return mWindow != nsnull; } // XXX Temporary for Bug #19416 NS_IMETHOD IgnoreSetPosition(PRBool aShouldIgnore) = 0; @@ -264,9 +312,43 @@ public: */ NS_IMETHOD List(FILE* out, PRInt32 aIndent = 0) const = 0; + /** + * @result true iff this is the root view for its view manager + */ + virtual PRBool IsRoot() const = 0; + + // DEPRECATED METHODS to be removed by roc + NS_IMETHOD HasWidget(PRBool *aHasWidget) const = 0; + NS_IMETHOD GetWidget(nsIWidget *&aWidget) const = 0; + NS_IMETHOD GetFloating(PRBool &aFloatingView) const = 0; + NS_IMETHOD GetParent(nsIView *&aParent) const = 0; + NS_IMETHOD GetFirstChild(nsIView* &aChild) const = 0; + NS_IMETHOD GetNextSibling(nsIView *&aNextSibling) const = 0; + NS_IMETHOD GetOpacity(float &aOpacity) const = 0; + NS_IMETHOD GetClientData(void *&aData) const = 0; + NS_IMETHOD GetVisibility(nsViewVisibility &aVisibility) const = 0; + NS_IMETHOD GetViewManager(nsIViewManager *&aViewMgr) const = 0; + NS_IMETHOD GetZIndex(PRBool &aAuto, PRInt32 &aZIndex, PRBool &aTopMost) const = 0; + NS_IMETHOD GetPosition(nscoord *aX, nscoord *aY) const = 0; + NS_IMETHOD GetBounds(nsRect &aBounds) const = 0; + private: NS_IMETHOD_(nsrefcnt) AddRef(void) = 0; NS_IMETHOD_(nsrefcnt) Release(void) = 0; + +protected: + nsViewManager *mViewManager; + nsView *mParent; + nsIWidget *mWindow; + nsView *mNextSibling; + nsView *mFirstChild; + void *mClientData; + PRInt32 mZIndex; + nsViewVisibility mVis; + nscoord mPosX, mPosY; + nsRect mDimBounds; // relative to parent + float mOpacity; + PRUint32 mVFlags; }; #endif diff --git a/mozilla/view/src/nsScrollPortView.cpp b/mozilla/view/src/nsScrollPortView.cpp index e8f93ad6073..7901ea66c97 100644 --- a/mozilla/view/src/nsScrollPortView.cpp +++ b/mozilla/view/src/nsScrollPortView.cpp @@ -442,19 +442,16 @@ void nsScrollPortView::AdjustChildWidgets(nsScrollPortView *aScrolling, nsView * NS_IMETHODIMP nsScrollPortView::SetScrolledView(nsIView *aScrolledView) { - PRInt32 count = GetChildCount(); - - NS_ASSERTION(count <= 1,"Error scroll port has too many children"); + NS_ASSERTION(GetFirstChild() == nsnull || GetFirstChild()->GetNextSibling() == nsnull, + "Error scroll port has too many children"); // if there is already a child so remove it - if (count == 1) + if (GetFirstChild() != nsnull) { - nsView* child = GetFirstChild(); - mViewManager->RemoveChild(child); + mViewManager->RemoveChild(GetFirstChild()); } return mViewManager->InsertChild(this, aScrolledView, 0); - } NS_IMETHODIMP nsScrollPortView::GetScrolledView(nsIView *&aScrolledView) const diff --git a/mozilla/view/src/nsView.cpp b/mozilla/view/src/nsView.cpp index e873f56029d..ed18d5a78c4 100644 --- a/mozilla/view/src/nsView.cpp +++ b/mozilla/view/src/nsView.cpp @@ -640,7 +640,6 @@ void nsView::InsertChild(nsView *aChild, nsView *aSibling) mFirstChild = aChild; } aChild->SetParent(this); - mNumKids++; } } @@ -662,7 +661,6 @@ void nsView::RemoveChild(nsView *child) mFirstChild = kid->GetNextSibling(); } child->SetParent(nsnull); - mNumKids--; found = PR_TRUE; break; } @@ -943,7 +941,7 @@ nsresult nsView::GetDirtyRegion(nsIRegion*& aRegion) return NS_OK; } -PRBool nsView::IsRoot() +PRBool nsView::IsRoot() const { NS_ASSERTION(mViewManager != nsnull," View manager is null in nsView::IsRoot()"); return mViewManager->GetRootView() == this; diff --git a/mozilla/view/src/nsView.h b/mozilla/view/src/nsView.h index 47942de9ba3..308884fb3fb 100644 --- a/mozilla/view/src/nsView.h +++ b/mozilla/view/src/nsView.h @@ -66,37 +66,6 @@ public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICLIPVIEW_IID) }; -//Flag to determine whether the view will check if events can be handled -//by its children or just handle the events itself -#define NS_VIEW_FLAG_DONT_CHECK_CHILDREN 0x0001 - -// indicates that the view is or contains a placeholder view -#define NS_VIEW_FLAG_CONTAINS_PLACEHOLDER 0x0002 - -//the view is transparent -#define NS_VIEW_FLAG_TRANSPARENT 0x0004 - -//indicates that the view should not be bitblt'd when moved -//or scrolled and instead must be repainted -#define NS_VIEW_FLAG_DONT_BITBLT 0x0010 - -// indicates that the view is using auto z-indexing -#define NS_VIEW_FLAG_AUTO_ZINDEX 0x0020 - -// indicates that the view is a floating view. -#define NS_VIEW_FLAG_FLOATING 0x0040 - -// set if our widget resized. -#define NS_VIEW_FLAG_WIDGET_RESIZED 0x0080 - -// set if our widget moved. -#define NS_VIEW_FLAG_WIDGET_MOVED 0x0100 -#define NS_VIEW_FLAG_CLIPCHILDREN 0x0200 - -// if set it indicates that this view should be -// displayed above z-index:auto views if this view -// is z-index:auto also -#define NS_VIEW_FLAG_TOPMOST 0x0400 class nsView : public nsIView { @@ -118,13 +87,17 @@ public: NS_IMETHOD GetBounds(nsRect &aBounds) const; NS_IMETHOD GetVisibility(nsViewVisibility &aVisibility) const; NS_IMETHOD GetZIndex(PRBool &aAuto, PRInt32 &aZIndex, PRBool &aTopMost) const; - PRInt32 GetZIndex() const { return mZIndex; } - PRBool GetZIndexIsAuto() const { return (mVFlags & NS_VIEW_FLAG_AUTO_ZINDEX) != 0; } NS_IMETHOD GetFloating(PRBool &aFloatingView) const; NS_IMETHOD GetParent(nsIView *&aParent) const; NS_IMETHOD GetFirstChild(nsIView* &aChild) const; NS_IMETHOD GetNextSibling(nsIView *&aNextSibling) const; NS_IMETHOD GetOpacity(float &aOpacity) const; + /** + * Used to ask a view if it has any areas within its bounding box + * that are transparent. This is not the same as opacity - opacity can + * be set externally, transparency is a quality of the view itself. + * @result Returns PR_TRUE if there are transparent areas, PR_FALSE otherwise. + */ NS_IMETHOD HasTransparency(PRBool &aTransparent) const; NS_IMETHOD SetClientData(void *aData); NS_IMETHOD GetClientData(void *&aData) const; @@ -292,7 +265,7 @@ public: static nsView* GetViewFor(nsIWidget* aWidget); // Helper function to determine if the view instance is the root view - PRBool IsRoot(); + virtual PRBool IsRoot() const; // Helper function to determine if the view point is inside of a view PRBool PointIsInside(nsView& aView, nscoord x, nscoord y) const; @@ -301,17 +274,27 @@ public: // parent, if we can) void DropMouseGrabbing(); -public: // NOT in nsIView, so only available in view module +public: + // NOT in nsIView, so only available in view module + nsZPlaceholderView* GetZParent() const { return mZParent; } + // These are also present in nsIView, but these versions return nsView and nsViewManager + // instead of nsIView and nsIViewManager. nsView* GetFirstChild() const { return mFirstChild; } nsView* GetNextSibling() const { return mNextSibling; } nsView* GetParent() const { return mParent; } - nsZPlaceholderView* GetZParent() const { return mZParent; } nsViewManager* GetViewManager() const { return mViewManager; } - nsViewVisibility GetVisibility() const { return mVis; } - void* GetClientData() const { return mClientData; } + // These are superceded by a better interface in nsIView + PRInt32 GetZIndex() const { return mZIndex; } + PRBool GetZIndexIsAuto() const { return (mVFlags & NS_VIEW_FLAG_AUTO_ZINDEX) != 0; } + // This is a better interface than GetDimensions(nsRect&) above + nsRect GetDimensions() const { nsRect r = mDimBounds; r.MoveBy(-mPosX, -mPosY); return r; } + // These are defined exactly the same in nsIView, but for now they have to be redeclared + // here because of stupid C++ method hiding rules PRBool GetFloating() const { return (mVFlags & NS_VIEW_FLAG_FLOATING) != 0; } + float GetOpacity() const { return mOpacity; } + void* GetClientData() const { return mClientData; } + nsViewVisibility GetVisibility() const { return mVis; } - PRInt32 GetChildCount() const { return mNumKids; } nsView* GetChild(PRInt32 aIndex) const; void InsertChild(nsView *aChild, nsView *aSibling); @@ -335,24 +318,10 @@ protected: virtual nsresult LoadWidget(const nsCID &aClassIID); protected: - nsViewManager *mViewManager; - nsView *mParent; - nsIWidget *mWindow; - nsZPlaceholderView*mZParent; //XXX should there be pointers to last child so backward walking is fast? - nsView *mNextSibling; - nsView *mFirstChild; - void *mClientData; - PRInt32 mZIndex; - nsViewVisibility mVis; - PRInt32 mNumKids; - nscoord mPosX, mPosY; - nsRect mDimBounds; // relative to parent nsRect mChildClip; - float mOpacity; - PRUint32 mVFlags; nsIRegion* mDirtyRegion; // Bug #19416 PRPackedBool mShouldIgnoreSetPosition; diff --git a/mozilla/view/src/nsViewManager.cpp b/mozilla/view/src/nsViewManager.cpp index 888845371f1..edeb6f71c2a 100644 --- a/mozilla/view/src/nsViewManager.cpp +++ b/mozilla/view/src/nsViewManager.cpp @@ -67,7 +67,6 @@ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); XXX TODO XXX DeCOMify newly private methods - Fix opacity model to conform to SVG (requires backbuffer stack) Optimize view storage */ @@ -94,7 +93,9 @@ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); #define VIEW_TRANSLUCENT 0x00000010 #define VIEW_CLIPPED 0x00000020 // used only by CanScrollWithBitBlt -#define VIEW_ISSCROLLED 0x00000080 +#define VIEW_ISSCROLLED 0x00000040 +#define PUSH_FILTER 0x00000080 +#define POP_FILTER 0x00000100 #define SUPPORT_TRANSLUCENT_VIEWS @@ -477,8 +478,6 @@ NS_IMETHODIMP nsViewManager::Init(nsIDeviceContext* aContext) mContext->GetAppUnitsToDevUnits(mTwipsToPixels); mContext->GetDevUnitsToAppUnits(mPixelsToTwips); - mTransCnt = 0; - mRefreshEnabled = PR_TRUE; mMouseGrabber = nsnull; @@ -502,7 +501,6 @@ NS_IMETHODIMP nsViewManager::SetRootView(nsIView *aView, nsIWidget* aWidget) { nsView* view = NS_STATIC_CAST(nsView*, aView); - UpdateTransCnt(mRootView, view); // Do NOT destroy the current root view. It's the caller's responsibility // to destroy it mRootView = view; @@ -701,11 +699,8 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext, } mPainting = PR_TRUE; - //printf("refreshing region...\n"); - //force double buffering because of non-opaque views? - - if (mTransCnt > 0) - aUpdateFlags |= NS_VMREFRESH_DOUBLE_BUFFER; + // force double buffering in general + aUpdateFlags |= NS_VMREFRESH_DOUBLE_BUFFER; if (!DoDoubleBuffering()) aUpdateFlags &= ~NS_VMREFRESH_DOUBLE_BUFFER; @@ -775,7 +770,8 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext, } } - if ((aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER) && ds) { + PRBool usingDoubleBuffer = (aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER) && ds; + if (usingDoubleBuffer) { // Adjust translations because the backbuffer holds just the damaged area, // not the whole widget @@ -794,18 +790,18 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext, localcx->Translate(-viewRect.x, -viewRect.y); } - 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); + PRBool isClipped; + localcx->SetClipRegion(*aRegion, nsClipCombine_kReplace, isClipped); + localcx->SetClipRect(damageRect, nsClipCombine_kIntersect, isClipped); // painting will be done in aView's coordinates - RenderViews(aView, *localcx, damageRegion, result); + RenderViews(aView, *localcx, damageRegion, usingDoubleBuffer); - if ((aUpdateFlags & NS_VMREFRESH_DOUBLE_BUFFER) && ds) { + if (usingDoubleBuffer) { // Flush bits back to the screen // Restore aRegion to pixels-relative-to-widget-origin @@ -815,8 +811,8 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext, // Make damageRect twips-relative-to-widget-origin damageRect.MoveBy(-viewRect.x, -viewRect.y); // Reset clip region to widget-relative - localcx->SetClipRegion(*aRegion, nsClipCombine_kReplace, result); - localcx->SetClipRect(damageRect, nsClipCombine_kIntersect, result); + localcx->SetClipRegion(*aRegion, nsClipCombine_kReplace, isClipped); + localcx->SetClipRect(damageRect, nsClipCombine_kIntersect, isClipped); // neither source nor destination are transformed localcx->CopyOffScreenBits(ds, 0, 0, widgetDamageRectInPixels, NS_COPYBITS_USE_SOURCE_CLIP_REGION); } else { @@ -961,7 +957,8 @@ static void SortByZOrder(DisplayZTreeNode *aNode, nsVoidArray &aBuffer, nsVoidAr nsInt64 explicitZIndex = 0; if (nsnull != aNode->mView) { - autoZIndex = aNode->mView->GetZIndexIsAuto(); + // Hixie says only non-translucent elements can have z-index:auto + autoZIndex = aNode->mView->GetZIndexIsAuto() && aNode->mView->GetOpacity() == 1.0f; explicitZIndex = BuildExtendedZIndex(aNode->mView); } @@ -1135,19 +1132,20 @@ void nsViewManager::AddCoveringWidgetsToOpaqueRegion(nsRegion &aRgn, nsIDeviceCo } void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC, - const nsRegion& aRegion, PRBool &aResult) + const nsRegion& aRegion, PRBool aRCIsOffscreen) { - BuildDisplayList(aRootView, aRegion.GetBounds(), PR_FALSE, PR_FALSE); + nsAutoVoidArray displayList; - PRBool anyRendered; - nsRect finalTransparentRect; + BuildDisplayList(aRootView, aRegion.GetBounds(), PR_FALSE, PR_FALSE, &displayList); nsRegion opaqueRgn; AddCoveringWidgetsToOpaqueRegion(opaqueRgn, mContext, aRootView); - OptimizeDisplayList(aRegion, finalTransparentRect, opaqueRgn); + + nsRect finalTransparentRect; + OptimizeDisplayList(&displayList, aRegion, finalTransparentRect, opaqueRgn); #ifdef DEBUG_roc - // ShowDisplayList(mDisplayListCount); + // ShowDisplayList(&displayList); #endif if (!finalTransparentRect.IsEmpty()) { @@ -1161,13 +1159,27 @@ void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC, #endif } - // initialize various counters. These are updated in OptimizeDisplayListClipping. - mTranslucentViewCount = 0; - mTranslucentArea.SetRect(0, 0, 0, 0); - PRInt32 index = 0; nsRect fakeClipRect; - OptimizeDisplayListClipping(PR_FALSE, fakeClipRect, index, anyRendered); + PRBool anyRendered; + OptimizeDisplayListClipping(&displayList, PR_FALSE, fakeClipRect, index, anyRendered); + + PRInt32 translucentViewCount; + nsRect translucentArea(0, 0, 0, 0); + PRInt32 i; + // count number of translucent views, and + // accumulate a rectangle of all translucent + // views. this will be used to determine which + // views need to be rendered into the blending + // buffers. + for (i = displayList.Count() - 1; i >= 0; --i) { + DisplayListElement2* element = + NS_STATIC_CAST(DisplayListElement2*, displayList.ElementAt(i)); + if ((element->mFlags & VIEW_TRANSLUCENT) && (element->mFlags & VIEW_RENDERED)) { + translucentViewCount++; + translucentArea.UnionRect(translucentArea, element->mBounds); + } + } // We keep a list of all the rendering contexts whose clip rects // need to be updated. @@ -1184,21 +1196,23 @@ void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC, NS_WARNING("Transparent window enabled"); // for a translucent window, we'll pretend the whole area is // translucent. - mTranslucentArea = aRegion.GetBounds(); + translucentArea = aRegion.GetBounds(); } } BlendingBuffers* buffers = nsnull; // create blending buffers, if necessary. - if (mTranslucentViewCount > 0 || translucentWindow) { - buffers = CreateBlendingBuffers(&aRC, translucentWindow); + if (translucentViewCount > 0 || translucentWindow) { + buffers = CreateBlendingBuffers(&aRC, translucentWindow, + translucentViewCount > 0, translucentArea); NS_ASSERTION(buffers, "not enough memory to blend"); if (!buffers) { // fall back by just rendering with transparency. - mTranslucentViewCount = 0; - for (PRInt32 i = mDisplayListCount - 1; i>= 0; --i) { - DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, mDisplayList.ElementAt(i)); + translucentViewCount = 0; + for (i = displayList.Count() - 1; i >= 0; --i) { + DisplayListElement2* element = + NS_STATIC_CAST(DisplayListElement2*, displayList.ElementAt(i)); element->mFlags &= ~VIEW_TRANSLUCENT; } } else { @@ -1206,7 +1220,7 @@ void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC, if (translucentWindow) { RCList[RCCount++] = buffers->mOffScreenWhiteCX; } - if (mTranslucentViewCount > 0) { + if (translucentViewCount > 0) { RCList[RCCount++] = buffers->mBlackCX; RCList[RCCount++] = buffers->mWhiteCX; } @@ -1215,7 +1229,7 @@ void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC, // There are some bits that aren't going to be completely painted, so // make sure we don't leave garbage in the offscreen context buffers->mOffScreenCX->SetColor(NS_RGB(128, 128, 128)); - buffers->mOffScreenCX->FillRect(nsRect(0, 0, mTranslucentArea.width, mTranslucentArea.height)); + buffers->mOffScreenCX->FillRect(nsRect(0, 0, translucentArea.width, translucentArea.height)); } } @@ -1225,30 +1239,34 @@ void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC, } // draw all views in the display list, from back to front. - for (PRInt32 i = 0; i < mDisplayListCount; i++) { - DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, mDisplayList.ElementAt(i)); + for (i = 0; i < displayList.Count(); i++) { + DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, displayList.ElementAt(i)); + + if (element->mFlags & PUSH_CLIP) { + PushStateAndClip(RCList, RCCount, element->mBounds, translucentArea.x, translucentArea.y); + } + if (element->mFlags & PUSH_FILTER) { + // nothing here yet + } + if (element->mFlags & VIEW_RENDERED) { // typical case, just rendering a view. - // RenderView(element->mView, aRC, aRect, element->mBounds, aResult); if (element->mFlags & VIEW_CLIPPED) { //Render the view using the clip rect set by it's ancestors - PushStateAndClip(RCList, RCCount, element->mBounds, mTranslucentArea.x, mTranslucentArea.y); - RenderDisplayListElement(element, aRC, buffers); + PushStateAndClip(RCList, RCCount, element->mBounds, translucentArea.x, translucentArea.y); + RenderDisplayListElement(element, aRC, buffers, translucentArea); PopState(RCList, RCCount); } else { - RenderDisplayListElement(element, aRC, buffers); - } - - } else { - // special case, pushing or popping clipping. - if (element->mFlags & PUSH_CLIP) { - PushStateAndClip(RCList, RCCount, element->mBounds, mTranslucentArea.x, mTranslucentArea.y); - } else { - if (element->mFlags & POP_CLIP) { - PopState(RCList, RCCount); - } + RenderDisplayListElement(element, aRC, buffers, translucentArea); } } + + if (element->mFlags & POP_FILTER) { + // nothing here yet + } + if (element->mFlags & POP_CLIP) { + PopState(RCList, RCCount); + } delete element; } @@ -1258,7 +1276,7 @@ void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC, if (buffers) { if (translucentWindow) { // Set window alphas - nsRect r = mTranslucentArea; + nsRect r = translucentArea; r *= mTwipsToPixels; nsRect bufferRect(0, 0, r.width, r.height); PRUint8* alphas = nsnull; @@ -1273,23 +1291,22 @@ void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC, // DEBUG: is this getting through? // mOffScreenCX->SetColor(NS_RGB(177, 177, 0)); - // mOffScreenCX->FillRect(nsRect(1, 1, mTranslucentArea.width-2, mTranslucentArea.height-2)); - aRC.CopyOffScreenBits(buffers->mOffScreen, 0, 0, mTranslucentArea, + // mOffScreenCX->FillRect(nsRect(1, 1, translucentArea.width-2, translucentArea.height-2)); + aRC.CopyOffScreenBits(buffers->mOffScreen, 0, 0, translucentArea, NS_COPYBITS_XFORM_DEST_VALUES | NS_COPYBITS_TO_BACK_BUFFER); // DEBUG: what rectangle are we blitting? // aRC.SetColor(NS_RGB(0, 177, 177)); - // aRC.DrawRect(mTranslucentArea); + // aRC.DrawRect(translucentArea); delete buffers; } - - mDisplayList.Clear(); } void nsViewManager::RenderDisplayListElement(DisplayListElement2* element, nsIRenderingContext &aRC, - BlendingBuffers* aBuffers) + BlendingBuffers* aBuffers, + const nsRect& aTranslucentArea) { PRBool clipEmpty; nsRect r; @@ -1300,7 +1317,7 @@ void nsViewManager::RenderDisplayListElement(DisplayListElement2* element, // if this element is contained by the translucent area, then // there's no point in drawing it here because it will be // overwritten by the final copy of the composited offscreen area - if (!aBuffers || !mTranslucentArea.Contains(element->mBounds)) { + if (!aBuffers || !aTranslucentArea.Contains(element->mBounds)) { aRC.PushState(); nscoord x = element->mAbsX - r.x, y = element->mAbsY - r.y; @@ -1315,14 +1332,14 @@ void nsViewManager::RenderDisplayListElement(DisplayListElement2* element, } #if defined(SUPPORT_TRANSLUCENT_VIEWS) - if (aBuffers && mTranslucentArea.Intersects(element->mBounds)) { + if (aBuffers && aTranslucentArea.Intersects(element->mBounds)) { // compute the origin of the view, relative to the offscreen buffer, which has the - // same dimensions as mTranslucentArea. + // same dimensions as aTranslucentArea. nscoord x = element->mAbsX - r.x, y = element->mAbsY - r.y; - nscoord viewX = x - mTranslucentArea.x, viewY = y - mTranslucentArea.y; + nscoord viewX = x - aTranslucentArea.x, viewY = y - aTranslucentArea.y; nsRect damageRect(element->mBounds); - damageRect.IntersectRect(damageRect, mTranslucentArea); + damageRect.IntersectRect(damageRect, aTranslucentArea); // -> coordinates relative to element->mView origin damageRect.x -= x, damageRect.y -= y; @@ -1349,7 +1366,7 @@ void nsViewManager::RenderDisplayListElement(DisplayListElement2* element, float opacity; view->GetOpacity(opacity); - // -> coordinates relative to mTranslucentArea origin + // -> coordinates relative to aTranslucentArea origin damageRect.x += viewX, damageRect.y += viewY; // perform the blend itself. @@ -1448,7 +1465,9 @@ BlendingBuffers::~BlendingBuffers() { } BlendingBuffers* nsViewManager::CreateBlendingBuffers(nsIRenderingContext *aRC, - PRBool aTranslucentWindow) + PRBool aTranslucentWindow, + PRBool aTranslucentViews, + const nsRect& aTranslucentArea) { nsresult rv; @@ -1466,9 +1485,9 @@ BlendingBuffers* nsViewManager::CreateBlendingBuffers(nsIRenderingContext *aRC, if (!buffers) return nsnull; - nsRect offscreenBounds(0, 0, mTranslucentArea.width, mTranslucentArea.height); + nsRect offscreenBounds(0, 0, aTranslucentArea.width, aTranslucentArea.height); offscreenBounds.ScaleRoundOut(mTwipsToPixels); - nsSize offscreenSize(mTranslucentArea.width, mTranslucentArea.height); + nsSize offscreenSize(aTranslucentArea.width, aTranslucentArea.height); rv = aRC->CreateDrawingSurface(offscreenBounds, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS, buffers->mOffScreen); if (NS_FAILED(rv)) { @@ -1482,7 +1501,7 @@ BlendingBuffers* nsViewManager::CreateBlendingBuffers(nsIRenderingContext *aRC, return nsnull; } - if (mTranslucentViewCount > 0) { + if (aTranslucentViews) { rv = aRC->CreateDrawingSurface(offscreenBounds, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS, buffers->mBlack); if (NS_FAILED(rv)) { delete buffers; @@ -1507,7 +1526,7 @@ BlendingBuffers* nsViewManager::CreateBlendingBuffers(nsIRenderingContext *aRC, return nsnull; } - nsRect fillArea(0, 0, mTranslucentArea.width, mTranslucentArea.height); + nsRect fillArea(0, 0, aTranslucentArea.width, aTranslucentArea.height); buffers->mBlackCX->SetColor(NS_RGB(0, 0, 0)); buffers->mBlackCX->FillRect(fillArea); @@ -1528,7 +1547,7 @@ BlendingBuffers* nsViewManager::CreateBlendingBuffers(nsIRenderingContext *aRC, return nsnull; } - nsRect fillArea(0, 0, mTranslucentArea.width, mTranslucentArea.height); + nsRect fillArea(0, 0, aTranslucentArea.width, aTranslucentArea.height); buffers->mOffScreenCX->SetColor(NS_RGB(0, 0, 0)); buffers->mOffScreenCX->FillRect(fillArea); @@ -2144,7 +2163,7 @@ static PRBool ComputePlaceholderContainment(nsView* aView) { } /* - Fills mDisplayList with DisplayListElement2* pointers. The caller is responsible + Fills aDisplayList with DisplayListElement2* pointers. The caller is responsible for freeing these structs. The display list elements are ordered by z-order so that the first element of the array is at the bottom in z-order and the last element in the array is at the top in z-order. @@ -2157,7 +2176,7 @@ static PRBool ComputePlaceholderContainment(nsView* aView) { Set aCaptured if the event is being captured by the given view. */ void nsViewManager::BuildDisplayList(nsView* aView, const nsRect& aRect, PRBool aEventProcessing, - PRBool aCaptured) { + PRBool aCaptured, nsAutoVoidArray* aDisplayList) { // compute this view's origin nsPoint origin(0, 0); ComputeViewOffset(aView, &origin); @@ -2198,7 +2217,8 @@ void nsViewManager::BuildDisplayList(nsView* aView, const nsRect& aRect, PRBool displayRoot->GetFloating(paintFloaters); } CreateDisplayList(displayRoot, PR_FALSE, zTree, PR_FALSE, origin.x, origin.y, - aView, &aRect, nsnull, displayRootOrigin.x, displayRootOrigin.y, paintFloaters, aEventProcessing); + aView, &aRect, nsnull, displayRootOrigin.x, displayRootOrigin.y, + paintFloaters, aEventProcessing); // Reparent any views that need reparenting in the Z-order tree ReparentViews(zTree); @@ -2208,11 +2228,9 @@ void nsViewManager::BuildDisplayList(nsView* aView, const nsRect& aRect, PRBool // Apply proper Z-order handling nsAutoVoidArray mergeTmp; - SortByZOrder(zTree, mDisplayList, mergeTmp, PR_TRUE); + SortByZOrder(zTree, *aDisplayList, mergeTmp, PR_TRUE); } - mDisplayListCount = mDisplayList.Count(); - DestroyZTreeNode(zTree); } @@ -2224,25 +2242,23 @@ void nsViewManager::BuildEventTargetList(nsAutoVoidArray &aTargets, nsView* aVie } nsRect eventRect(aEvent->point.x, aEvent->point.y, 1, 1); - - BuildDisplayList(aView, eventRect, PR_TRUE, aCaptured); + nsAutoVoidArray displayList; + BuildDisplayList(aView, eventRect, PR_TRUE, aCaptured, &displayList); #ifdef DEBUG_roc - // ShowDisplayList(mDisplayListCount); + // ShowDisplayList(aDisplayList); #endif // The display list is in order from back to front. We return the target list in order from // front to back. - for (PRInt32 i = mDisplayListCount - 1; i >= 0; --i) { - DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, mDisplayList.ElementAt(i)); + for (PRInt32 i = displayList.Count() - 1; i >= 0; --i) { + DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, displayList.ElementAt(i)); if (element->mFlags & VIEW_RENDERED) { aTargets.AppendElement(element); } else { delete element; } } - - mDisplayList.Clear(); } nsEventStatus nsViewManager::HandleEvent(nsView* aView, nsGUIEvent* aEvent, PRBool aCaptured) { @@ -2521,8 +2537,6 @@ NS_IMETHODIMP nsViewManager::InsertChild(nsIView *aParent, nsIView *aChild, nsIV ReparentWidgets(child, parent); #endif - UpdateTransCnt(nsnull, child); - // if the parent view is marked as "floating", make the newly added view float as well. PRBool isFloating = PR_FALSE; parent->GetFloating(isFloating); @@ -2578,7 +2592,6 @@ NS_IMETHODIMP nsViewManager::RemoveChild(nsIView *aChild) if ((nsnull != parent) && (nsnull != child)) { - UpdateTransCnt(child, nsnull); UpdateView(child, NS_VMREFRESH_NO_SYNC); parent->RemoveChild(child); } @@ -2859,11 +2872,12 @@ PRBool nsViewManager::CanScrollWithBitBlt(nsView* aView) } aView->ConvertFromParentCoords(&r.x, &r.y); - BuildDisplayList(aView, r, PR_FALSE, PR_FALSE); + nsAutoVoidArray displayList; + BuildDisplayList(aView, r, PR_FALSE, PR_FALSE, &displayList); PRInt32 i; - for (i = 0; i < mDisplayListCount; i++) { - DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, mDisplayList.ElementAt(i)); + for (i = 0; i < displayList.Count(); i++) { + DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, displayList.ElementAt(i)); if ((element->mFlags & VIEW_RENDERED) != 0) { if (IsAncestorOf(aView, element->mView)) { element->mFlags |= (VIEW_ISSCROLLED | VIEW_TRANSPARENT); @@ -2917,13 +2931,13 @@ 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(nsRegion(r), finalTransparentRect, opaqueRegion); + OptimizeDisplayList(&displayList, nsRegion(r), finalTransparentRect, opaqueRegion); PRBool anyUnscrolledViews = PR_FALSE; PRBool anyUnblittableViews = PR_FALSE; - for (i = 0; i < mDisplayListCount; i++) { - DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, mDisplayList.ElementAt(i)); + for (i = 0; i < displayList.Count(); i++) { + DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, displayList.ElementAt(i)); if ((element->mFlags & VIEW_RENDERED) != 0) { if ((element->mFlags & VIEW_ISSCROLLED) == 0 && element->mView != aView) { anyUnscrolledViews = PR_TRUE; @@ -2935,8 +2949,6 @@ PRBool nsViewManager::CanScrollWithBitBlt(nsView* aView) delete element; } - mDisplayList.Clear(); - return !anyUnscrolledViews && !anyUnblittableViews; } @@ -3086,9 +3098,7 @@ NS_IMETHODIMP nsViewManager::SetViewContentTransparency(nsIView *aView, PRBool a view->HasTransparency(trans); if (trans != aTransparent) { - UpdateTransCnt(view, nsnull); view->SetContentTransparency(aTransparent); - UpdateTransCnt(nsnull, view); if (IsViewInserted(view)) { UpdateView(view, NS_VMREFRESH_NO_SYNC); @@ -3107,9 +3117,7 @@ NS_IMETHODIMP nsViewManager::SetViewOpacity(nsIView *aView, float aOpacity) if (opacity != aOpacity) { - UpdateTransCnt(view, nsnull); view->SetOpacity(aOpacity); - UpdateTransCnt(nsnull, view); if (IsViewInserted(view)) { UpdateView(view, NS_VMREFRESH_NO_SYNC); @@ -3258,33 +3266,6 @@ void nsViewManager::AddRectToDirtyRegion(nsView* aView, const nsRect &aRect) con } } -void nsViewManager::UpdateTransCnt(nsView *oldview, nsView *newview) -{ - if (nsnull != oldview) - { - PRBool hasTransparency; - float opacity; - - oldview->HasTransparency(hasTransparency); - oldview->GetOpacity(opacity); - - if (hasTransparency || (1.0f != opacity)) - mTransCnt--; - } - - if (nsnull != newview) - { - PRBool hasTransparency; - float opacity; - - newview->HasTransparency(hasTransparency); - newview->GetOpacity(opacity); - - if (hasTransparency || (1.0f != opacity)) - mTransCnt++; - } -} - NS_IMETHODIMP nsViewManager::DisableRefresh(void) { if (mUpdateBatchCnt > 0) @@ -3387,13 +3368,12 @@ NS_IMETHODIMP nsViewManager::Display(nsIView* aView, nscoord aX, nscoord aY, con localcx->Translate(aX, aY); - PRBool result; - - localcx->SetClipRect(aClipRect, nsClipCombine_kReplace, result); + PRBool isClipped; + localcx->SetClipRect(aClipRect, nsClipCombine_kReplace, isClipped); // 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, nsRegion(trect), result); + RenderViews(view, *localcx, nsRegion(trect), PR_FALSE); NS_RELEASE(localcx); @@ -3577,21 +3557,22 @@ PRBool nsViewManager::CreateDisplayList(nsView *aView, PRBool aReparentedViewsPr } } - PRInt32 childCount = aView->GetChildCount(); + PRBool anyChildren = aView->GetFirstChild() != nsnull; if (aEventProcessing && (aView->GetViewFlags() & NS_VIEW_FLAG_DONT_CHECK_CHILDREN) != 0) { - childCount = 0; + anyChildren = PR_FALSE; } - if (childCount > 0) { + if (anyChildren) { if (isClipView) { // -> to refresh-frame coordinates (relative to aRealView) bounds.x -= aOriginX; bounds.y -= aOriginY; // Add POP first because the z-tree is in reverse order - retval = AddToDisplayList(aView, aResult, bounds, bounds, POP_CLIP, aX - aOriginX, aY - aOriginY, PR_FALSE); + retval = AddToDisplayList(aView, aResult, bounds, bounds, + POP_CLIP, aX - aOriginX, aY - aOriginY, PR_FALSE); if (retval) return retval; @@ -3642,7 +3623,8 @@ PRBool nsViewManager::CreateDisplayList(nsView *aView, PRBool aReparentedViewsPr if (opacity < 1.0f) flags |= VIEW_TRANSLUCENT; #endif - retval = AddToDisplayList(aView, aResult, bounds, irect, flags, aX - aOriginX, aY - aOriginY, + retval = AddToDisplayList(aView, aResult, bounds, irect, flags, + aX - aOriginX, aY - aOriginY, aEventProcessing && aRealView == aView); } @@ -3657,12 +3639,13 @@ PRBool nsViewManager::CreateDisplayList(nsView *aView, PRBool aReparentedViewsPr } } - if (childCount > 0 && isClipView) { + if (anyChildren && isClipView) { // -> to refresh-frame coordinates (relative to aRealView) bounds.x -= aOriginX; bounds.y -= aOriginY; - if (AddToDisplayList(aView, aResult, bounds, bounds, PUSH_CLIP, aX - aOriginX, aY - aOriginY, PR_FALSE)) { + if (AddToDisplayList(aView, aResult, bounds, bounds, PUSH_CLIP, + aX - aOriginX, aY - aOriginY, PR_FALSE)) { retval = PR_TRUE; } } @@ -3670,9 +3653,11 @@ PRBool nsViewManager::CreateDisplayList(nsView *aView, PRBool aReparentedViewsPr return retval; } -PRBool nsViewManager::AddToDisplayList(nsView *aView, DisplayZTreeNode* &aParent, - nsRect &aClipRect, nsRect& aDirtyRect, PRUint32 aFlags,nscoord aAbsX, nscoord aAbsY, - PRBool aAssumeIntersection) +PRBool nsViewManager::AddToDisplayList(nsView *aView, + DisplayZTreeNode* &aParent, nsRect &aClipRect, + nsRect& aDirtyRect, PRUint32 aFlags, + nscoord aAbsX, nscoord aAbsY, + PRBool aAssumeIntersection) { PRBool empty; PRBool clipped; @@ -3724,40 +3709,6 @@ PRBool nsViewManager::AddToDisplayList(nsView *aView, DisplayZTreeNode* &aParent return PR_FALSE; } -// Make sure that all PUSH_CLIP/POP_CLIP pairs are honored. -// They might not be because of the Z-reparenting mess: a fixed-position view might have -// created a display element with bounds that do not reflect the clipping instructions that now -// surround the element. This would cause problems in the optimizer. -// XXX No longer used. REMOVE IN THE GREAT VIEW MANAGER PURGE -void nsViewManager::ReapplyClipInstructions(PRBool aHaveClip, nsRect& aClipRect, PRInt32& aIndex) -{ - while (aIndex < mDisplayListCount) { - DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, mDisplayList.ElementAt(aIndex)); - aIndex++; - - if (element->mFlags & VIEW_RENDERED) { - if (aHaveClip && !element->mBounds.IntersectRect(aClipRect, element->mBounds)) { - element->mFlags &= ~VIEW_RENDERED; - } - } - - if (element->mFlags & PUSH_CLIP) { - nsRect newClip; - if (aHaveClip) { - newClip.IntersectRect(aClipRect, element->mBounds); - } else { - newClip = element->mBounds; - } - - ReapplyClipInstructions(PR_TRUE, newClip, aIndex); - } - - if (element->mFlags & POP_CLIP) { - return; - } - } -} - /** Walk the display list, looking for opaque views, and remove any views that are behind them and totally occluded. @@ -3768,13 +3719,12 @@ 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 nsRegion& aDamageRegion, - nsRect& aFinalTransparentRect, - nsRegion &aOpaqueRegion) +void nsViewManager::OptimizeDisplayList(nsAutoVoidArray* aDisplayList, const nsRegion& aDamageRegion, + nsRect& aFinalTransparentRect, + nsRegion &aOpaqueRegion) { - PRInt32 count = mDisplayListCount; - for (PRInt32 i = count - 1; i >= 0; i--) { - DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, mDisplayList.ElementAt(i)); + for (PRInt32 i = aDisplayList->Count() - 1; i >= 0; i--) { + DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, aDisplayList->ElementAt(i)); if (element->mFlags & VIEW_RENDERED) { nsRegion tmpRgn; tmpRgn.Sub(element->mBounds, aOpaqueRegion); @@ -3796,36 +3746,21 @@ nsresult nsViewManager::OptimizeDisplayList(const nsRegion& aDamageRegion, nsRegion tmpRgn; tmpRgn.Sub(aDamageRegion, aOpaqueRegion); aFinalTransparentRect = tmpRgn.GetBounds(); - - return NS_OK; } // Remove redundant PUSH/POP_CLIP pairs. These could be expensive. -// We also count the translucent views and compute the translucency area in -// this pass. -void nsViewManager::OptimizeDisplayListClipping(PRBool aHaveClip, nsRect& aClipRect, PRInt32& aIndex, +void nsViewManager::OptimizeDisplayListClipping(nsAutoVoidArray* aDisplayList, + PRBool aHaveClip, nsRect& aClipRect, PRInt32& aIndex, PRBool& aAnyRendered) { aAnyRendered = PR_FALSE; - while (aIndex < mDisplayListCount) { - DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, mDisplayList.ElementAt(aIndex)); + while (aIndex < aDisplayList->Count()) { + DisplayListElement2* element = + NS_STATIC_CAST(DisplayListElement2*, aDisplayList->ElementAt(aIndex)); aIndex++; if (element->mFlags & VIEW_RENDERED) { - // count number of translucent views, and - // accumulate a rectangle of all translucent - // views. this will be used to determine which - // views need to be rendered into the blending - // buffers. - if (element->mFlags & VIEW_TRANSLUCENT) { - if (mTranslucentViewCount++ == 0) { - mTranslucentArea = element->mBounds; - } else { - mTranslucentArea.UnionRect(mTranslucentArea, element->mBounds); - } - } - aAnyRendered = PR_TRUE; if (aHaveClip && (element->mFlags & VIEW_CLIPPED)) { @@ -3847,8 +3782,9 @@ void nsViewManager::OptimizeDisplayListClipping(PRBool aHaveClip, nsRect& aClipR } PRBool anyRenderedViews = PR_FALSE; - OptimizeDisplayListClipping(PR_TRUE, newClip, aIndex, anyRenderedViews); - DisplayListElement2* popElement = NS_STATIC_CAST(DisplayListElement2*, mDisplayList.ElementAt(aIndex - 1)); + OptimizeDisplayListClipping(aDisplayList, PR_TRUE, newClip, aIndex, anyRenderedViews); + DisplayListElement2* popElement = + NS_STATIC_CAST(DisplayListElement2*, aDisplayList->ElementAt(aIndex - 1)); NS_ASSERTION(popElement->mFlags & POP_CLIP, "Must end with POP!"); if (anyRenderedViews) { @@ -3868,19 +3804,19 @@ void nsViewManager::OptimizeDisplayListClipping(PRBool aHaveClip, nsRect& aClipR } } -#ifdef NS_DEBUG -void nsViewManager::ShowDisplayList(PRInt32 flatlen) +void nsViewManager::ShowDisplayList(nsAutoVoidArray* aDisplayList) { +#ifdef NS_DEBUG char nest[400]; PRInt32 newnestcnt, nestcnt = 0, cnt; for (cnt = 0; cnt < 400; cnt++) nest[cnt] = ' '; - printf("### display list length=%d ###\n", flatlen); + printf("### display list length=%d ###\n", aDisplayList->Count()); - for (cnt = 0; cnt < flatlen; cnt++) { - DisplayListElement2* element = (DisplayListElement2*) mDisplayList.ElementAt(cnt); + for (cnt = 0; cnt < aDisplayList->Count(); cnt++) { + DisplayListElement2* element = (DisplayListElement2*)aDisplayList->ElementAt(cnt); nsView* view = element->mView; nsRect rect = element->mBounds; PRUint32 flags = element->mFlags; @@ -3920,6 +3856,16 @@ void nsViewManager::ShowDisplayList(PRInt32 flatlen) newnestcnt++; } + if (flags & POP_FILTER) { + printf("POP_FILTER "); + newnestcnt--; + } + + if (flags & PUSH_FILTER) { + printf("PUSH_FILTER "); + newnestcnt++; + } + if (flags & VIEW_RENDERED) printf("VIEW_RENDERED "); @@ -3945,8 +3891,8 @@ void nsViewManager::ShowDisplayList(PRInt32 flatlen) nestcnt = newnestcnt; } -} #endif +} void nsViewManager::ComputeViewOffset(nsView *aView, nsPoint *aOrigin) { diff --git a/mozilla/view/src/nsViewManager.h b/mozilla/view/src/nsViewManager.h index 26df759ffe1..c2512c3e3a1 100644 --- a/mozilla/view/src/nsViewManager.h +++ b/mozilla/view/src/nsViewManager.h @@ -244,7 +244,6 @@ private: void ReparentWidgets(nsIView* aView, nsIView *aParent); nsIRenderingContext *CreateRenderingContext(nsView &aView); void AddRectToDirtyRegion(nsView* aView, const nsRect &aRect) const; - void UpdateTransCnt(nsView *oldview, nsView *newview); PRBool UpdateWidgetArea(nsView *aWidgetView, const nsRect &aDamagedRect, nsView* aIgnoreWidgetView); @@ -254,11 +253,11 @@ private: nsIRegion *region, PRUint32 aUpdateFlags); void DefaultRefresh(nsView* aView, const nsRect* aRect); void RenderViews(nsView *aRootView, nsIRenderingContext& aRC, const nsRegion& aRegion, - PRBool &aResult); + PRBool aRCIsOffscreen); void RenderDisplayListElement(DisplayListElement2* element, nsIRenderingContext &aRC, - BlendingBuffers* aBuffers); + BlendingBuffers* aBuffers, const nsRect& aTranslucentArea); void PaintView(nsView *aView, nsIRenderingContext &aRC, nscoord x, nscoord y, const nsRect &aDamageRect); @@ -268,20 +267,26 @@ private: PRUint32 aUpdateFlags, nscoord aY1, nscoord aY2, PRBool aInCutOut); BlendingBuffers* CreateBlendingBuffers(nsIRenderingContext *aRC, - PRBool aTranslucentWindow); + PRBool aTranslucentWindow, PRBool aTranslucentViews, + const nsRect& aTranslucentArea); void ReparentViews(DisplayZTreeNode* aNode); - void BuildDisplayList(nsView* aView, const nsRect& aRect, PRBool aEventProcessing, PRBool aCaptured); + void BuildDisplayList(nsView* aView, const nsRect& aRect, PRBool aEventProcessing, + PRBool aCaptured, nsAutoVoidArray* aDisplayList); void BuildEventTargetList(nsAutoVoidArray &aTargets, nsView* aView, nsGUIEvent* aEvent, PRBool aCaptured); - PRBool CreateDisplayList(nsView *aView, PRBool aReparentedViewsPresent, DisplayZTreeNode* &aResult, nscoord aOriginX, nscoord aOriginY, + PRBool CreateDisplayList(nsView *aView, + PRBool aReparentedViewsPresent, DisplayZTreeNode* &aResult, + nscoord aOriginX, nscoord aOriginY, PRBool aInsideRealView, nsView *aRealView, const nsRect *aDamageRect, - nsView *aTopView, nscoord aX, nscoord aY, PRBool aPaintFloaters, PRBool aEventProcessing); - 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 nsRegion& aDirtyRegion, - nsRect& aFinalTransparentRect, nsRegion& aOpaqueRgn); + nsView *aTopView, nscoord aX, nscoord aY, + PRBool aPaintFloaters, PRBool aEventProcessing); + PRBool AddToDisplayList(nsView *aView, + DisplayZTreeNode* &aParent, nsRect &aClipRect, + nsRect& aDirtyRect, PRUint32 aFlags, nscoord aAbsX, nscoord aAbsY, + PRBool aAssumeIntersection); + void OptimizeDisplayList(nsAutoVoidArray* aDisplayList, const nsRegion& aDirtyRegion, + nsRect& aFinalTransparentRect, nsRegion& aOpaqueRgn); // Remove redundant PUSH/POP_CLIP pairs. void ComputeViewOffset(nsView *aView, nsPoint *aOrigin); @@ -294,11 +299,10 @@ private: void PauseTimer(void); void RestartTimer(void); - void OptimizeDisplayListClipping(PRBool aHaveClip, nsRect& aClipRect, PRInt32& aIndex, + void OptimizeDisplayListClipping(nsAutoVoidArray* aDisplayList, PRBool aHaveClip, + nsRect& aClipRect, PRInt32& aIndex, PRBool& aAnyRendered); -#ifdef NS_DEBUG - void ShowDisplayList(PRInt32 flatlen); -#endif + void ShowDisplayList(nsAutoVoidArray* aDisplayList); // Utilities @@ -375,7 +379,6 @@ private: float mPixelsToTwips; nsIViewObserver *mObserver; nsIWidget *mRootWindow; - PRInt32 mTransCnt; PRBool mRefreshEnabled; PRBool mPainting; PRBool mRecursiveRefreshPending; @@ -383,10 +386,6 @@ private: nsView *mKeyGrabber; PRInt32 mUpdateCnt; PRInt32 mUpdateBatchCnt; - PRInt32 mDisplayListCount; - nsAutoVoidArray mDisplayList; - PRInt32 mTranslucentViewCount; - nsRect mTranslucentArea; // bounding box of all translucent views. nsIScrollableView *mRootScrollable; PRInt32 mCachingWidgetChanges; nscolor mDefaultBackgroundColor;