Bug 607417 - Part 3: Visibility tricks for fixed items r=roc

--HG--
extra : rebase_source : 7545070d6af5ef10dd4d1504f0d456ece4fd8edb
This commit is contained in:
Tatiana Meshkova 2011-04-08 09:35:16 -07:00
Родитель 24f8411f3d
Коммит a985c968e0
3 изменённых файлов: 87 добавлений и 8 удалений

Просмотреть файл

@ -64,6 +64,7 @@
#include "nsIInterfaceRequestorUtils.h"
#include "BasicLayers.h"
#include "nsBoxFrame.h"
#include "nsViewportFrame.h"
using namespace mozilla;
using namespace mozilla::layers;
@ -86,7 +87,10 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mInTransform(PR_FALSE),
mSyncDecodeImages(PR_FALSE),
mIsPaintingToWindow(PR_FALSE),
mSnappingEnabled(PR_TRUE) {
mSnappingEnabled(PR_TRUE),
mHasDisplayPort(PR_FALSE),
mHasFixedItems(PR_FALSE)
{
MOZ_COUNT_CTOR(nsDisplayListBuilder);
PL_InitArenaPool(&mPool, "displayListArena", 1024,
NS_MAX(NS_ALIGNMENT_OF(void*),NS_ALIGNMENT_OF(double))-1);
@ -101,6 +105,13 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
}
}
if(mReferenceFrame->GetType() == nsGkAtoms::viewportFrame) {
ViewportFrame* viewportFrame = static_cast<ViewportFrame*>(mReferenceFrame);
if (!viewportFrame->GetChildList(nsGkAtoms::fixedList).IsEmpty()) {
mHasFixedItems = PR_TRUE;
}
}
LayerBuilder()->Init(this);
PR_STATIC_ASSERT(nsDisplayItem::TYPE_MAX < (1 << nsDisplayItem::TYPE_BITS));
@ -121,10 +132,38 @@ static void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) {
}
}
static void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
const nsRect& aDirtyRect) {
static PRBool IsFixedFrame(nsIFrame* aFrame)
{
return aFrame && aFrame->GetParent() && !aFrame->GetParent()->GetParent();
}
static PRBool IsFixedItem(nsDisplayItem *aItem, nsDisplayListBuilder* aBuilder)
{
nsIFrame* activeScrolledRoot =
nsLayoutUtils::GetActiveScrolledRootFor(aItem, aBuilder);
return activeScrolledRoot &&
!nsLayoutUtils::ScrolledByViewportScrolling(activeScrolledRoot,
aBuilder);
}
static PRBool ForceVisiblityForFixedItem(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem)
{
return aBuilder->GetHasDisplayPort() && aBuilder->GetHasFixedItems() &&
IsFixedItem(aItem, aBuilder);
}
void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
nsIFrame* aFrame,
const nsRect& aDirtyRect)
{
nsRect dirty = aDirtyRect - aFrame->GetOffsetTo(aDirtyFrame);
nsRect overflowRect = aFrame->GetVisualOverflowRect();
if (mHasDisplayPort && IsFixedFrame(aFrame)) {
dirty = overflowRect;
}
if (!dirty.IntersectRect(dirty, overflowRect))
return;
aFrame->Properties().Set(nsDisplayListBuilder::OutOfFlowDirtyRectProperty(),
@ -430,6 +469,10 @@ nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
itemVisible.And(*aVisibleRegion, bounds);
item->mVisibleRect = itemVisible.GetBounds();
if (ForceVisiblityForFixedItem(aBuilder, item)) {
item->mVisibleRect = bounds;
}
PRBool containsRootContentDocBG = PR_FALSE;
if (item->ComputeVisibility(aBuilder, aVisibleRegion, aAllowVisibleRegionExpansion,
containsRootContentDocBG)) {
@ -757,6 +800,10 @@ PRBool nsDisplayItem::RecomputeVisibility(nsDisplayListBuilder* aBuilder,
itemVisible.And(*aVisibleRegion, bounds);
mVisibleRect = itemVisible.GetBounds();
if (ForceVisiblityForFixedItem(aBuilder, this)) {
mVisibleRect = bounds;
}
// When we recompute visibility within layers we don't need to
// expand the visible region for content behind plugins (the plugin
// is not in the layer).
@ -819,12 +866,21 @@ nsDisplayBackground::nsDisplayBackground(nsDisplayListBuilder* aBuilder,
const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
mIsThemed = mFrame->IsThemed(disp, &mThemeTransparency);
if (mIsThemed) {
// Perform necessary RegisterThemeGeometry
if (mIsThemed &&
(disp->mAppearance == NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR ||
disp->mAppearance == NS_THEME_TOOLBAR)) {
if (disp->mAppearance == NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR ||
disp->mAppearance == NS_THEME_TOOLBAR) {
RegisterThemeGeometry(aBuilder, aFrame);
}
} else {
// Set HasFixedItems if we construct a background-attachment:fixed item
nsPresContext* presContext = mFrame->PresContext();
nsStyleContext* bgSC;
PRBool hasBG = nsCSSRendering::FindBackground(presContext, mFrame, &bgSC);
if (hasBG && bgSC->GetStyleBackground()->HasFixedBackground()) {
aBuilder->SetHasFixedItems();
}
}
}
// Helper for RoundedRectIntersectsRect.

Просмотреть файл

@ -292,6 +292,20 @@ public:
*/
void SetInTransform(PRBool aInTransform) { mInTransform = aInTransform; }
/**
* Call this if using display port for scrolling.
*/
void SetHasDisplayPort() { mHasDisplayPort = PR_TRUE; }
PRBool GetHasDisplayPort() { return mHasDisplayPort; }
/**
* Call this if ReferenceFrame() is a viewport frame with fixed-position
* children, or when we construct an item which will return true from
* ShouldFixToViewport()
*/
void SetHasFixedItems() { mHasFixedItems = PR_TRUE; }
PRBool GetHasFixedItems() { return mHasFixedItems; }
/**
* Returns true if snapping is enabled for the final drawing context.
* The default is true.
@ -456,6 +470,9 @@ public:
}
private:
void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
const nsRect& aDirtyRect);
struct PresShellState {
nsIPresShell* mPresShell;
nsIFrame* mCaretFrame;
@ -492,6 +509,8 @@ private:
PRPackedBool mSyncDecodeImages;
PRPackedBool mIsPaintingToWindow;
PRPackedBool mSnappingEnabled;
PRPackedBool mHasDisplayPort;
PRPackedBool mHasFixedItems;
};
class nsDisplayItem;

Просмотреть файл

@ -1451,6 +1451,10 @@ nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFra
nsDisplayListBuilder builder(aFrame, nsDisplayListBuilder::PAINTING,
!(aFlags & PAINT_HIDE_CARET));
if (usingDisplayPort) {
builder.SetHasDisplayPort();
}
nsDisplayList list;
if (aFlags & PAINT_IN_TRANSFORM) {
builder.SetInTransform(PR_TRUE);