зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1009478 - Make LayerActivity properties survive across reframes of an element. r=roc
This commit is contained in:
Родитель
2bf68f16b6
Коммит
a772659b8d
|
@ -505,6 +505,7 @@ GK_ATOM(lang, "lang")
|
|||
GK_ATOM(language, "language")
|
||||
GK_ATOM(last, "last")
|
||||
GK_ATOM(layer, "layer")
|
||||
GK_ATOM(LayerActivity, "LayerActivity")
|
||||
GK_ATOM(layout, "layout")
|
||||
GK_ATOM(leading, "leading")
|
||||
GK_ATOM(leaf, "leaf")
|
||||
|
|
|
@ -29,6 +29,7 @@ class LayerActivity {
|
|||
public:
|
||||
LayerActivity(nsIFrame* aFrame)
|
||||
: mFrame(aFrame)
|
||||
, mContent(nullptr)
|
||||
, mOpacityRestyleCount(0)
|
||||
, mTransformRestyleCount(0)
|
||||
, mLeftRestyleCount(0)
|
||||
|
@ -60,7 +61,13 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// While tracked, exactly one of mFrame or mContent is non-null, depending
|
||||
// on whether this property is stored on a frame or on a content node.
|
||||
// When this property is expired by the layer activity tracker, both mFrame
|
||||
// and mContent are nulled-out and the property is deleted.
|
||||
nsIFrame* mFrame;
|
||||
nsIContent* mContent;
|
||||
|
||||
nsExpirationState mState;
|
||||
// Number of restyle operations detected
|
||||
uint8_t mOpacityRestyleCount;
|
||||
|
@ -93,7 +100,7 @@ static LayerActivityTracker* gLayerActivityTracker = nullptr;
|
|||
|
||||
LayerActivity::~LayerActivity()
|
||||
{
|
||||
if (mFrame) {
|
||||
if (mFrame || mContent) {
|
||||
NS_ASSERTION(gLayerActivityTracker, "Should still have a tracker");
|
||||
gLayerActivityTracker->RemoveObject(this);
|
||||
}
|
||||
|
@ -113,15 +120,24 @@ LayerActivityTracker::NotifyExpired(LayerActivity* aObject)
|
|||
RemoveObject(aObject);
|
||||
|
||||
nsIFrame* f = aObject->mFrame;
|
||||
nsIContent* c = aObject->mContent;
|
||||
aObject->mFrame = nullptr;
|
||||
aObject->mContent = nullptr;
|
||||
|
||||
// The pres context might have been detached during the delay -
|
||||
// that's fine, just skip the paint.
|
||||
if (f->PresContext()->GetContainerWeak()) {
|
||||
f->SchedulePaint();
|
||||
MOZ_ASSERT((f == nullptr) != (c == nullptr),
|
||||
"A LayerActivity object should always have a reference to either its frame or its content");
|
||||
|
||||
if (f) {
|
||||
// The pres context might have been detached during the delay -
|
||||
// that's fine, just skip the paint.
|
||||
if (f->PresContext()->GetContainerWeak()) {
|
||||
f->SchedulePaint();
|
||||
}
|
||||
f->RemoveStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY);
|
||||
f->Properties().Delete(LayerActivityProperty());
|
||||
} else {
|
||||
c->DeleteProperty(nsGkAtoms::LayerActivity);
|
||||
}
|
||||
f->RemoveStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY);
|
||||
f->Properties().Delete(LayerActivityProperty());
|
||||
}
|
||||
|
||||
static LayerActivity*
|
||||
|
@ -160,6 +176,39 @@ IncrementMutationCount(uint8_t* aCount)
|
|||
*aCount = uint8_t(std::min(0xFF, *aCount + 1));
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ActiveLayerTracker::TransferActivityToContent(nsIFrame* aFrame, nsIContent* aContent)
|
||||
{
|
||||
if (!aFrame->HasAnyStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY)) {
|
||||
return;
|
||||
}
|
||||
FrameProperties properties = aFrame->Properties();
|
||||
LayerActivity* layerActivity =
|
||||
static_cast<LayerActivity*>(properties.Remove(LayerActivityProperty()));
|
||||
aFrame->RemoveStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY);
|
||||
if (!layerActivity) {
|
||||
return;
|
||||
}
|
||||
layerActivity->mFrame = nullptr;
|
||||
layerActivity->mContent = aContent;
|
||||
aContent->SetProperty(nsGkAtoms::LayerActivity, layerActivity,
|
||||
nsINode::DeleteProperty<LayerActivity>, true);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ActiveLayerTracker::TransferActivityToFrame(nsIContent* aContent, nsIFrame* aFrame)
|
||||
{
|
||||
LayerActivity* layerActivity = static_cast<LayerActivity*>(
|
||||
aContent->UnsetProperty(nsGkAtoms::LayerActivity));
|
||||
if (!layerActivity) {
|
||||
return;
|
||||
}
|
||||
layerActivity->mContent = nullptr;
|
||||
layerActivity->mFrame = aFrame;
|
||||
aFrame->AddStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY);
|
||||
aFrame->Properties().Set(LayerActivityProperty(), layerActivity);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ActiveLayerTracker::NotifyRestyle(nsIFrame* aFrame, nsCSSProperty aProperty)
|
||||
{
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "nsCSSProperty.h"
|
||||
|
||||
class nsIFrame;
|
||||
class nsIContent;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -64,6 +65,18 @@ public:
|
|||
* as being animated for constructing active layers.
|
||||
*/
|
||||
static bool IsOffsetOrMarginStyleAnimated(nsIFrame* aFrame);
|
||||
/**
|
||||
* Transfer the LayerActivity property to the frame's content node when the
|
||||
* frame is about to be destroyed so that layer activity can be tracked
|
||||
* throughout reframes of an element. Only call this when aFrame is the
|
||||
* primary frame of aContent.
|
||||
*/
|
||||
static void TransferActivityToContent(nsIFrame* aFrame, nsIContent* aContent);
|
||||
/**
|
||||
* Transfer the LayerActivity property back to the content node's primary
|
||||
* frame after the frame has been created.
|
||||
*/
|
||||
static void TransferActivityToFrame(nsIContent* aContent, nsIFrame* aFrame);
|
||||
|
||||
/*
|
||||
* We track modifications to the content of certain frames (i.e. canvas frames)
|
||||
|
|
|
@ -93,6 +93,7 @@
|
|||
#include "nsRefreshDriver.h"
|
||||
#include "nsRuleProcessorData.h"
|
||||
#include "nsTextNode.h"
|
||||
#include "ActiveLayerTracker.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -3828,6 +3829,7 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
|
|||
!aItem.mContent->GetPrimaryFrame())) &&
|
||||
!(bits & FCDATA_SKIP_FRAMESET)) {
|
||||
aItem.mContent->SetPrimaryFrame(primaryFrame);
|
||||
ActiveLayerTracker::TransferActivityToFrame(aItem.mContent, primaryFrame);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
#include "mozilla/css/ImageLoader.h"
|
||||
#include "mozilla/gfx/Tools.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "ActiveLayerTracker.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::css;
|
||||
|
@ -648,6 +649,13 @@ nsFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
|||
}
|
||||
}
|
||||
|
||||
// This needs to happen before shell->NotifyDestroyingFrame because that
|
||||
// clears our Properties() table.
|
||||
bool isPrimaryFrame = (mContent && mContent->GetPrimaryFrame() == this);
|
||||
if (isPrimaryFrame) {
|
||||
ActiveLayerTracker::TransferActivityToContent(this, mContent);
|
||||
}
|
||||
|
||||
shell->NotifyDestroyingFrame(this);
|
||||
|
||||
if (mState & NS_FRAME_EXTERNAL_REFERENCE) {
|
||||
|
@ -663,7 +671,7 @@ nsFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
|||
}
|
||||
|
||||
// Make sure that our deleted frame can't be returned from GetPrimaryFrame()
|
||||
if (mContent && mContent->GetPrimaryFrame() == this) {
|
||||
if (isPrimaryFrame) {
|
||||
mContent->SetPrimaryFrame(nullptr);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче