Bug 607417. Improve definition of the 'fixed layer' flag. r=tnikkel

This commit is contained in:
Robert O'Callahan 2012-05-04 17:00:57 +12:00
parent 72cb8a16b2
commit a567b26b6f
8 changed files with 61 additions and 18 deletions

View File

@ -723,6 +723,12 @@ public:
Mutated();
}
/**
* CONSTRUCTION PHASE ONLY
* A layer is "fixed position" when it draws content from a content
* (not chrome) document, the topmost content document has a root scrollframe
* with a displayport, but the layer does not move when that displayport scrolls.
*/
void SetIsFixedPosition(bool aFixedPosition) { mIsFixedPosition = aFixedPosition; }
// These getters can be used anytime.

View File

@ -1664,7 +1664,8 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
ownLayer->SetTransform(transform);
}
ownLayer->SetIsFixedPosition(!nsLayoutUtils::ScrolledByViewportScrolling(
ownLayer->SetIsFixedPosition(
!nsLayoutUtils::IsScrolledByRootContentDocumentDisplayportScrolling(
activeScrolledRoot, mBuilder));
// Update that layer's clip and visible rects.
@ -1716,8 +1717,9 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
FindThebesLayerFor(item, itemVisibleRect, itemDrawRect, aClip,
activeScrolledRoot);
data->mLayer->SetIsFixedPosition(!nsLayoutUtils::ScrolledByViewportScrolling(
activeScrolledRoot, mBuilder));
data->mLayer->SetIsFixedPosition(
!nsLayoutUtils::IsScrolledByRootContentDocumentDisplayportScrolling(
activeScrolledRoot, mBuilder));
InvalidateForLayerChange(item, data->mLayer);

View File

@ -116,8 +116,7 @@ static bool IsFixedItem(nsDisplayItem *aItem, nsDisplayListBuilder* aBuilder)
nsIFrame* activeScrolledRoot =
nsLayoutUtils::GetActiveScrolledRootFor(aItem, aBuilder);
return activeScrolledRoot &&
!nsLayoutUtils::ScrolledByViewportScrolling(activeScrolledRoot,
aBuilder);
!nsLayoutUtils::IsScrolledByRootContentDocumentDisplayportScrolling(activeScrolledRoot, aBuilder);
}
static bool ForceVisiblityForFixedItem(nsDisplayListBuilder* aBuilder,

View File

@ -163,8 +163,7 @@ protected:
typedef mozilla::layers::LayerManager LayerManager;
enum eRenderFlag {
STATE_IGNORING_VIEWPORT_SCROLLING = 0x1,
STATE_USING_DISPLAYPORT = 0x2
STATE_IGNORING_VIEWPORT_SCROLLING = 0x1
};
typedef PRUint8 RenderFlags; // for storing the above flags

View File

@ -859,11 +859,17 @@ nsLayoutUtils::GetActiveScrolledRootFor(nsDisplayItem* aItem,
}
bool
nsLayoutUtils::ScrolledByViewportScrolling(nsIFrame* aActiveScrolledRoot,
nsDisplayListBuilder* aBuilder)
nsLayoutUtils::IsScrolledByRootContentDocumentDisplayportScrolling(nsIFrame* aActiveScrolledRoot,
nsDisplayListBuilder* aBuilder)
{
nsIFrame* rootScrollFrame =
aBuilder->ReferenceFrame()->PresContext()->GetPresShell()->GetRootScrollFrame();
nsPresContext* presContext = aActiveScrolledRoot->PresContext()->
GetToplevelContentDocumentPresContext();
if (!presContext)
return false;
nsIFrame* rootScrollFrame = presContext->GetPresShell()->GetRootScrollFrame();
if (!rootScrollFrame || !nsLayoutUtils::GetDisplayPort(rootScrollFrame->GetContent(), nsnull))
return false;
return nsLayoutUtils::IsAncestorFrameCrossDoc(rootScrollFrame, aActiveScrolledRoot);
}

View File

@ -306,8 +306,13 @@ public:
nsDisplayListBuilder* aBuilder,
bool* aShouldFixToViewport = nsnull);
static bool ScrolledByViewportScrolling(nsIFrame* aActiveScrolledRoot,
nsDisplayListBuilder* aBuilder);
/**
* Returns true if aActiveScrolledRoot is in a content document,
* and its topmost content document ancestor has a root scroll frame with
* a displayport set, and aActiveScrolledRoot is scrolled by that scrollframe.
*/
static bool IsScrolledByRootContentDocumentDisplayportScrolling(nsIFrame* aActiveScrolledRoot,
nsDisplayListBuilder* aBuilder);
/**
* GetScrollableFrameFor returns the scrollable frame for a scrolled frame

View File

@ -1167,10 +1167,10 @@ nsPresContext::Observe(nsISupports* aSubject,
return NS_ERROR_FAILURE;
}
static nsPresContext*
GetParentPresContext(nsPresContext* aPresContext)
nsPresContext*
nsPresContext::GetParentPresContext()
{
nsIPresShell* shell = aPresContext->GetPresShell();
nsIPresShell* shell = GetPresShell();
if (shell) {
nsIFrame* rootFrame = shell->FrameManager()->GetRootFrame();
if (rootFrame) {
@ -1182,13 +1182,27 @@ GetParentPresContext(nsPresContext* aPresContext)
return nsnull;
}
nsPresContext*
nsPresContext::GetToplevelContentDocumentPresContext()
{
if (IsChrome())
return nsnull;
nsPresContext* pc = this;
for (;;) {
nsPresContext* parent = pc->GetParentPresContext();
if (!parent || parent->IsChrome())
return pc;
pc = parent;
}
}
// We may want to replace this with something faster, maybe caching the root prescontext
nsRootPresContext*
nsPresContext::GetRootPresContext()
{
nsPresContext* pc = this;
for (;;) {
nsPresContext* parent = GetParentPresContext(pc);
nsPresContext* parent = pc->GetParentPresContext();
if (!parent)
break;
pc = parent;
@ -2138,7 +2152,7 @@ nsPresContext::NotifyInvalidation(const nsRect& aRect, PRUint32 aFlags)
return;
nsPresContext* pc;
for (pc = this; pc; pc = GetParentPresContext(pc)) {
for (pc = this; pc; pc = pc->GetParentPresContext()) {
if (pc->mFireAfterPaintEvents)
break;
pc->mFireAfterPaintEvents = true;

View File

@ -169,6 +169,18 @@ public:
nsIPresShell* GetPresShell() const { return mShell; }
/**
* Returns the parent prescontext for this one. Returns null if this is a
* root.
*/
nsPresContext* GetParentPresContext();
/**
* Returns the prescontext of the toplevel content document that contains
* this presentation, or null if there isn't one.
*/
nsPresContext* GetToplevelContentDocumentPresContext();
/**
* Return the presentation context for the root of the view manager
* hierarchy that contains this presentation context, or nsnull if it can't