From 16fa19c5d57946e1a78ce582d633f2c4397cd792 Mon Sep 17 00:00:00 2001 From: "kmcclusk%netscape.com" Date: Tue, 2 Jul 2002 02:53:35 +0000 Subject: [PATCH] Place position:absolute, fixed, relative elements above non positioned elements. b=137853 r=roc+moz sr=kin git-svn-id: svn://10.0.0.236/trunk@124460 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/generic/nsContainerFrame.cpp | 11 +++-- .../layout/generic/nsHTMLContainerFrame.cpp | 13 +++-- .../layout/html/base/src/nsContainerFrame.cpp | 11 +++-- .../html/base/src/nsHTMLContainerFrame.cpp | 13 +++-- mozilla/view/public/nsIView.h | 9 +++- mozilla/view/public/nsIViewManager.h | 8 +++- mozilla/view/src/nsScrollingView.cpp | 12 ++--- mozilla/view/src/nsScrollingView.h | 2 +- mozilla/view/src/nsView.cpp | 10 ++-- mozilla/view/src/nsView.h | 11 ++++- mozilla/view/src/nsViewManager.cpp | 48 ++++++++++++++----- mozilla/view/src/nsViewManager.h | 3 +- 12 files changed, 109 insertions(+), 42 deletions(-) diff --git a/mozilla/layout/generic/nsContainerFrame.cpp b/mozilla/layout/generic/nsContainerFrame.cpp index 623182eebed..290dbc2ae2a 100644 --- a/mozilla/layout/generic/nsContainerFrame.cpp +++ b/mozilla/layout/generic/nsContainerFrame.cpp @@ -650,18 +650,23 @@ nsContainerFrame::SyncFrameViewAfterReflow(nsIPresContext* aPresContext, // Make sure z-index is correct PRInt32 zIndex = 0; + PRInt32 oldZIndex; + PRBool oldAutoZIndex; + PRBool oldTopMost; PRBool autoZIndex = PR_FALSE; const nsStylePosition* position; + aView->GetZIndex(oldZIndex, oldAutoZIndex, oldTopMost); + aFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)position); if (position->mZIndex.GetUnit() == eStyleUnit_Integer) { zIndex = position->mZIndex.GetIntValue(); } else if (position->mZIndex.GetUnit() == eStyleUnit_Auto) { autoZIndex = PR_TRUE; - } - - vm->SetViewZIndex(aView, autoZIndex, zIndex); + } + + vm->SetViewZIndex(aView, autoZIndex, zIndex, oldTopMost); // There are two types of clipping: // - 'clip' which only applies to absolutely positioned elements, and is diff --git a/mozilla/layout/generic/nsHTMLContainerFrame.cpp b/mozilla/layout/generic/nsHTMLContainerFrame.cpp index 5674a0ab0df..9b84b7f13a0 100644 --- a/mozilla/layout/generic/nsHTMLContainerFrame.cpp +++ b/mozilla/layout/generic/nsHTMLContainerFrame.cpp @@ -449,6 +449,7 @@ nsHTMLContainerFrame::CreateViewForFrame(nsIPresContext* aPresContext, nsIFrame* aContentParentFrame, PRBool aForce) { + PRBool isTopMostView = PR_FALSE; nsIView* view; aFrame->GetView(aPresContext, &view); // If we don't yet have a view, see if we need a view @@ -489,12 +490,18 @@ nsHTMLContainerFrame::CreateViewForFrame(nsIPresContext* aPresContext, ("nsHTMLContainerFrame::CreateViewForFrame: frame=%p relatively positioned", aFrame)); aForce = PR_TRUE; + isTopMostView = PR_TRUE; } else if (display->IsAbsolutelyPositioned()) { NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, ("nsHTMLContainerFrame::CreateViewForFrame: frame=%p absolutely positioned", aFrame)); aForce = PR_TRUE; - } + isTopMostView = PR_TRUE; + } + } + + if (NS_STYLE_POSITION_FIXED == display->mPosition) { + isTopMostView = PR_TRUE; } // See if the frame is a scrolled frame @@ -585,7 +592,7 @@ nsHTMLContainerFrame::CreateViewForFrame(nsIPresContext* aPresContext, autoZIndex = PR_TRUE; } - viewManager->SetViewZIndex(view, autoZIndex, zIndex); + viewManager->SetViewZIndex(view, autoZIndex, zIndex, isTopMostView); // XXX Drop it at the end of the document order until we can do better viewManager->InsertChild(parentView, view, nsnull, PR_TRUE); @@ -600,7 +607,7 @@ nsHTMLContainerFrame::CreateViewForFrame(nsIPresContext* aPresContext, if (nsnull == zParentView) { nsIFrame* zParentFrame = nsnull; - + aContentParentFrame->GetParentWithView(aPresContext, &zParentFrame); NS_ASSERTION(zParentFrame, "GetParentWithView failed"); zParentFrame->GetView(aPresContext, &zParentView); diff --git a/mozilla/layout/html/base/src/nsContainerFrame.cpp b/mozilla/layout/html/base/src/nsContainerFrame.cpp index 623182eebed..290dbc2ae2a 100644 --- a/mozilla/layout/html/base/src/nsContainerFrame.cpp +++ b/mozilla/layout/html/base/src/nsContainerFrame.cpp @@ -650,18 +650,23 @@ nsContainerFrame::SyncFrameViewAfterReflow(nsIPresContext* aPresContext, // Make sure z-index is correct PRInt32 zIndex = 0; + PRInt32 oldZIndex; + PRBool oldAutoZIndex; + PRBool oldTopMost; PRBool autoZIndex = PR_FALSE; const nsStylePosition* position; + aView->GetZIndex(oldZIndex, oldAutoZIndex, oldTopMost); + aFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)position); if (position->mZIndex.GetUnit() == eStyleUnit_Integer) { zIndex = position->mZIndex.GetIntValue(); } else if (position->mZIndex.GetUnit() == eStyleUnit_Auto) { autoZIndex = PR_TRUE; - } - - vm->SetViewZIndex(aView, autoZIndex, zIndex); + } + + vm->SetViewZIndex(aView, autoZIndex, zIndex, oldTopMost); // There are two types of clipping: // - 'clip' which only applies to absolutely positioned elements, and is diff --git a/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp b/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp index 5674a0ab0df..9b84b7f13a0 100644 --- a/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp +++ b/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp @@ -449,6 +449,7 @@ nsHTMLContainerFrame::CreateViewForFrame(nsIPresContext* aPresContext, nsIFrame* aContentParentFrame, PRBool aForce) { + PRBool isTopMostView = PR_FALSE; nsIView* view; aFrame->GetView(aPresContext, &view); // If we don't yet have a view, see if we need a view @@ -489,12 +490,18 @@ nsHTMLContainerFrame::CreateViewForFrame(nsIPresContext* aPresContext, ("nsHTMLContainerFrame::CreateViewForFrame: frame=%p relatively positioned", aFrame)); aForce = PR_TRUE; + isTopMostView = PR_TRUE; } else if (display->IsAbsolutelyPositioned()) { NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, ("nsHTMLContainerFrame::CreateViewForFrame: frame=%p absolutely positioned", aFrame)); aForce = PR_TRUE; - } + isTopMostView = PR_TRUE; + } + } + + if (NS_STYLE_POSITION_FIXED == display->mPosition) { + isTopMostView = PR_TRUE; } // See if the frame is a scrolled frame @@ -585,7 +592,7 @@ nsHTMLContainerFrame::CreateViewForFrame(nsIPresContext* aPresContext, autoZIndex = PR_TRUE; } - viewManager->SetViewZIndex(view, autoZIndex, zIndex); + viewManager->SetViewZIndex(view, autoZIndex, zIndex, isTopMostView); // XXX Drop it at the end of the document order until we can do better viewManager->InsertChild(parentView, view, nsnull, PR_TRUE); @@ -600,7 +607,7 @@ nsHTMLContainerFrame::CreateViewForFrame(nsIPresContext* aPresContext, if (nsnull == zParentView) { nsIFrame* zParentFrame = nsnull; - + aContentParentFrame->GetParentWithView(aPresContext, &zParentFrame); NS_ASSERTION(zParentFrame, "GetParentWithView failed"); zParentFrame->GetView(aPresContext, &zParentView); diff --git a/mozilla/view/public/nsIView.h b/mozilla/view/public/nsIView.h index bb258d67884..a36caab43ba 100644 --- a/mozilla/view/public/nsIView.h +++ b/mozilla/view/public/nsIView.h @@ -144,9 +144,14 @@ public: /** * Called to query the z-index of a view. * The z-index is relative to all siblings of the view. - * @result current z depth + * @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 + * */ - NS_IMETHOD GetZIndex(PRBool &aAuto, PRInt32 &aZIndex) const = 0; + NS_IMETHOD GetZIndex(PRBool &aAuto, PRInt32 &aZIndex, PRBool &aTopMost) const = 0; /** * Get whether the view "floats" above all other views, diff --git a/mozilla/view/public/nsIViewManager.h b/mozilla/view/public/nsIViewManager.h index b4dcf8bbf4a..b57450c9773 100644 --- a/mozilla/view/public/nsIViewManager.h +++ b/mozilla/view/public/nsIViewManager.h @@ -288,9 +288,13 @@ public: * which means that the z-indicies of the view's children are * relative to the view's siblings. * @param aView view to change z depth of - * @param zindex new z depth + * @param aZindex explicit z depth + * @param aTopMost used when this view is z-index:auto to compare against + * other z-index:auto views. + * PR_TRUE if the view should be topmost when compared with + * other z-index:auto views. */ - NS_IMETHOD SetViewZIndex(nsIView *aView, PRBool aAutoZIndex, PRInt32 aZindex) = 0; + NS_IMETHOD SetViewZIndex(nsIView *aView, PRBool aAutoZIndex, PRInt32 aZindex, PRBool aTopMost = PR_FALSE) = 0; /** * Set whether the view "floats" above all other views, diff --git a/mozilla/view/src/nsScrollingView.cpp b/mozilla/view/src/nsScrollingView.cpp index c35e1e8a0af..69e9938acd0 100644 --- a/mozilla/view/src/nsScrollingView.cpp +++ b/mozilla/view/src/nsScrollingView.cpp @@ -950,17 +950,17 @@ NS_IMETHODIMP nsScrollingView::SetWidget(nsIWidget *aWidget) return NS_OK; } -NS_IMETHODIMP nsScrollingView::SetZIndex(PRBool aAuto, PRInt32 aZIndex) +NS_IMETHODIMP nsScrollingView::SetZIndex(PRBool aAuto, PRInt32 aZIndex, PRBool aTopMost) { - nsView::SetZIndex(aAuto, aZIndex); + nsView::SetZIndex(aAuto, aZIndex, aTopMost); // inform all views that the z-index has changed. // XXX why are we doing this? they're all a child of this view, so they // shouldn't need to be re-z-indexed. - if (mClipView) mViewManager->SetViewZIndex(mClipView, aAuto, aZIndex); - if (mCornerView) mViewManager->SetViewZIndex(mCornerView, aAuto, aZIndex); - if (mVScrollBarView) mViewManager->SetViewZIndex(mVScrollBarView, aAuto, aZIndex); - if (mHScrollBarView) mViewManager->SetViewZIndex(mHScrollBarView, aAuto, aZIndex); + if (mClipView) mViewManager->SetViewZIndex(mClipView, aAuto, aZIndex, aTopMost); + if (mCornerView) mViewManager->SetViewZIndex(mCornerView, aAuto, aZIndex, aTopMost); + if (mVScrollBarView) mViewManager->SetViewZIndex(mVScrollBarView, aAuto, aZIndex, aTopMost); + if (mHScrollBarView) mViewManager->SetViewZIndex(mHScrollBarView, aAuto, aZIndex, aTopMost); return NS_OK; } diff --git a/mozilla/view/src/nsScrollingView.h b/mozilla/view/src/nsScrollingView.h index 2a9bb667829..cfa48ae437e 100644 --- a/mozilla/view/src/nsScrollingView.h +++ b/mozilla/view/src/nsScrollingView.h @@ -68,7 +68,7 @@ public: NS_IMETHOD SetVisibility(nsViewVisibility visibility); NS_IMETHOD SetWidget(nsIWidget *aWidget); - NS_IMETHOD SetZIndex(PRBool aAuto, PRInt32 aZIndex); + NS_IMETHOD SetZIndex(PRBool aAuto, PRInt32 aZIndex, PRBool aTopMost); //nsIScrollableView interface NS_IMETHOD CreateScrollControls(nsNativeWidget aNative = nsnull); diff --git a/mozilla/view/src/nsView.cpp b/mozilla/view/src/nsView.cpp index 17741c5baea..537b02db7c4 100644 --- a/mozilla/view/src/nsView.cpp +++ b/mozilla/view/src/nsView.cpp @@ -607,10 +607,11 @@ NS_IMETHODIMP nsView::GetVisibility(nsViewVisibility &aVisibility) const return NS_OK; } -NS_IMETHODIMP nsView::GetZIndex(PRBool &aAuto, PRInt32 &aZIndex) const +NS_IMETHODIMP nsView::GetZIndex(PRBool &aAuto, PRInt32 &aZIndex, PRBool &aTopMost) const { - aAuto = (mVFlags & NS_VIEW_FLAG_AUTO_ZINDEX) != 0; + aAuto = (mVFlags & NS_VIEW_FLAG_AUTO_ZINDEX) != 0; aZIndex = mZIndex; + aTopMost = (mVFlags & NS_VIEW_FLAG_TOPMOST) != 0; return NS_OK; } @@ -825,11 +826,12 @@ NS_IMETHODIMP nsView::CreateWidget(const nsIID &aWindowIID, return NS_OK; } -void nsView::SetZIndex(PRBool aAuto, PRInt32 aZIndex) +void nsView::SetZIndex(PRBool aAuto, PRInt32 aZIndex, PRBool aTopMost) { mVFlags = (mVFlags & ~NS_VIEW_FLAG_AUTO_ZINDEX) | (aAuto ? NS_VIEW_FLAG_AUTO_ZINDEX : 0); mZIndex = aZIndex; - + SetTopMost(aTopMost); + if (nsnull != mWindow) { mWindow->SetZIndex(aZIndex); } diff --git a/mozilla/view/src/nsView.h b/mozilla/view/src/nsView.h index ea0b7d09e91..72eebcbe92c 100644 --- a/mozilla/view/src/nsView.h +++ b/mozilla/view/src/nsView.h @@ -84,6 +84,10 @@ public: // 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 //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 @@ -110,7 +114,7 @@ public: NS_IMETHOD GetPosition(nscoord *x, nscoord *y) const; NS_IMETHOD GetBounds(nsRect &aBounds) const; NS_IMETHOD GetVisibility(nsViewVisibility &aVisibility) const; - NS_IMETHOD GetZIndex(PRBool &aAuto, PRInt32 &aZIndex) 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; @@ -218,7 +222,7 @@ public: * relative to the view's siblings. * @param zindex new z depth */ - void SetZIndex(PRBool aAuto, PRInt32 aZIndex); + void SetZIndex(PRBool aAuto, PRInt32 aZIndex, PRBool aTopMost); /** * Set/Get whether the view "floats" above all other views, @@ -315,6 +319,9 @@ public: // NOT in nsIView, so only available in view module PRUint32 GetViewFlags() const { return mVFlags; } void SetViewFlags(PRUint32 aFlags) { mVFlags = aFlags; } + void SetTopMost(PRBool aTopMost) { aTopMost ? mVFlags |= NS_VIEW_FLAG_TOPMOST : mVFlags &= ~NS_VIEW_FLAG_TOPMOST; } + PRBool IsTopMost() { return((mVFlags & NS_VIEW_FLAG_TOPMOST) != 0); } + void ConvertToParentCoords(nscoord* aX, nscoord* aY) const { *aX += mPosX; *aY += mPosY; } void ConvertFromParentCoords(nscoord* aX, nscoord* aY) const { *aX -= mPosX; *aY -= mPosY; } diff --git a/mozilla/view/src/nsViewManager.cpp b/mozilla/view/src/nsViewManager.cpp index 173bcd15e6e..283a044fd69 100644 --- a/mozilla/view/src/nsViewManager.cpp +++ b/mozilla/view/src/nsViewManager.cpp @@ -252,6 +252,26 @@ nsInvalidateEvent::nsInvalidateEvent(nsViewManager* aViewManager) //-------------- End Invalidate Event Definition --------------------------- +// Compare two Z-index values taking into account topmost and +// auto flags. the topmost flag is only used when both views are +// zindex:auto. +// +// returns 0 if equal +// > 0 if first z-index is greater than the second +// < 0 if first z-index is less than the second + +static PRInt32 CompareZIndex(PRInt32 aZIndex1, PRBool aTopMost1, PRBool aIsAuto1, + PRInt32 aZIndex2, PRBool aTopMost2, PRBool aIsAuto2) +{ + NS_ASSERTION(!aIsAuto1 || aZIndex1 == 0,"auto is set and the z-index is not 0"); + NS_ASSERTION(!aIsAuto2 || aZIndex2 == 0,"auto is set and the z-index is not 0"); + + if (aZIndex1 != aZIndex2) { + return aZIndex1 - aZIndex2; + } else { + return aTopMost1 - aTopMost2; + } +} void nsViewManager::PostInvalidateEvent() @@ -526,7 +546,7 @@ NS_IMETHODIMP nsViewManager::SetRootView(nsIView *aView, nsIWidget* aWidget) parent->InsertChild(mRootView, nsnull); } - mRootView->SetZIndex(PR_FALSE, 0); + mRootView->SetZIndex(PR_FALSE, 0, PR_FALSE); mRootView->GetWidget(mRootWindow); if (nsnull != mRootWindow) { @@ -1807,7 +1827,7 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS obs->HandleEvent(view, aEvent, aStatus, PR_TRUE, handled); } } - break; + break; default: { @@ -2205,7 +2225,8 @@ NS_IMETHODIMP nsViewManager::InsertChild(nsIView *aParent, nsIView *aChild, nsIV { PRInt32 idx = kid->GetZIndex(); - if (zIndex >= idx) + if (CompareZIndex(zIndex, child->IsTopMost(), child->GetZIndexIsAuto(), + idx, kid->IsTopMost(), kid->GetZIndexIsAuto()) >= 0) break; prev = kid; @@ -2248,7 +2269,7 @@ NS_IMETHODIMP nsViewManager::InsertZPlaceholder(nsIView *aParent, nsIView *aChil // mark the placeholder as "shown" so that it will be included in a built display list placeholder->Init(this, bounds, parent, nsViewVisibility_kShow); placeholder->SetReparentedView(child); - placeholder->SetZIndex(child->GetZIndexIsAuto(), child->GetZIndex()); + placeholder->SetZIndex(child->GetZIndexIsAuto(), child->GetZIndex(), child->IsTopMost()); child->SetZParent(placeholder); return InsertChild(parent, placeholder, aSibling, aAfter); @@ -2273,8 +2294,10 @@ NS_IMETHODIMP nsViewManager::InsertChild(nsIView *aParent, nsIView *aChild, PRIn { PRInt32 idx = kid->GetZIndex(); - if (aZIndex >= idx) + if (CompareZIndex(aZIndex, child->IsTopMost(), child->GetZIndexIsAuto(), + idx, kid->IsTopMost(), kid->GetZIndexIsAuto()) >= 0) { break; + } //get the next sibling view @@ -2284,7 +2307,7 @@ NS_IMETHODIMP nsViewManager::InsertChild(nsIView *aParent, nsIView *aChild, PRIn //in case this hasn't been set yet... maybe we should not do this? MMP - child->SetZIndex(child->GetZIndexIsAuto(), aZIndex); + child->SetZIndex(child->GetZIndexIsAuto(), aZIndex, child->IsTopMost()); parent->InsertChild(child, prev); UpdateTransCnt(nsnull, child); @@ -2704,7 +2727,7 @@ PRBool nsViewManager::IsViewInserted(nsView *aView) } } -NS_IMETHODIMP nsViewManager::SetViewZIndex(nsIView *aView, PRBool aAutoZIndex, PRInt32 aZIndex) +NS_IMETHODIMP nsViewManager::SetViewZIndex(nsIView *aView, PRBool aAutoZIndex, PRInt32 aZIndex, PRBool aTopMost) { nsView* view = NS_STATIC_CAST(nsView*, aView); nsresult rv = NS_OK; @@ -2717,16 +2740,19 @@ NS_IMETHODIMP nsViewManager::SetViewZIndex(nsIView *aView, PRBool aAutoZIndex, P return rv; } + PRBool oldTopMost = view->IsTopMost(); + PRBool oldIsAuto = view->GetZIndexIsAuto(); + if (aAutoZIndex) { aZIndex = 0; } PRInt32 oldidx = view->GetZIndex(); - - view->SetZIndex(aAutoZIndex, aZIndex); + view->SetZIndex(aAutoZIndex, aZIndex, aTopMost); if (IsViewInserted(view)) { - if (oldidx != aZIndex) { + if (CompareZIndex(oldidx, oldTopMost, oldIsAuto, + aZIndex, aTopMost, aAutoZIndex) != 0) { nsView *parent = view->GetParent(); if (nsnull != parent) { //we don't just call the view manager's RemoveChild() @@ -2748,7 +2774,7 @@ NS_IMETHODIMP nsViewManager::SetViewZIndex(nsIView *aView, PRBool aAutoZIndex, P nsZPlaceholderView* zParentView = view->GetZParent(); if (nsnull != zParentView) { - SetViewZIndex(zParentView, aAutoZIndex, aZIndex); + SetViewZIndex(zParentView, aAutoZIndex, aZIndex, aTopMost); } } diff --git a/mozilla/view/src/nsViewManager.h b/mozilla/view/src/nsViewManager.h index 701ff3e1456..db43ee70ce8 100644 --- a/mozilla/view/src/nsViewManager.h +++ b/mozilla/view/src/nsViewManager.h @@ -180,8 +180,7 @@ public: NS_IMETHOD SetViewVisibility(nsIView *aView, nsViewVisibility aVisible); - NS_IMETHOD SetViewZIndex(nsIView *aView, PRBool aAuto, PRInt32 aZIndex); - + NS_IMETHOD SetViewZIndex(nsIView *aView, PRBool aAuto, PRInt32 aZIndex, PRBool aTopMost=PR_FALSE); NS_IMETHOD SetViewContentTransparency(nsIView *aView, PRBool aTransparent); NS_IMETHOD SetViewOpacity(nsIView *aView, float aOpacity);