зеркало из https://github.com/mozilla/pjs.git
Bug 607417 - Part 3: Visibility tricks for fixed items r=roc
--HG-- extra : rebase_source : 7545070d6af5ef10dd4d1504f0d456ece4fd8edb
This commit is contained in:
Родитель
24f8411f3d
Коммит
a985c968e0
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче