зеркало из 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(language, "language")
|
||||||
GK_ATOM(last, "last")
|
GK_ATOM(last, "last")
|
||||||
GK_ATOM(layer, "layer")
|
GK_ATOM(layer, "layer")
|
||||||
|
GK_ATOM(LayerActivity, "LayerActivity")
|
||||||
GK_ATOM(layout, "layout")
|
GK_ATOM(layout, "layout")
|
||||||
GK_ATOM(leading, "leading")
|
GK_ATOM(leading, "leading")
|
||||||
GK_ATOM(leaf, "leaf")
|
GK_ATOM(leaf, "leaf")
|
||||||
|
|
|
@ -29,6 +29,7 @@ class LayerActivity {
|
||||||
public:
|
public:
|
||||||
LayerActivity(nsIFrame* aFrame)
|
LayerActivity(nsIFrame* aFrame)
|
||||||
: mFrame(aFrame)
|
: mFrame(aFrame)
|
||||||
|
, mContent(nullptr)
|
||||||
, mOpacityRestyleCount(0)
|
, mOpacityRestyleCount(0)
|
||||||
, mTransformRestyleCount(0)
|
, mTransformRestyleCount(0)
|
||||||
, mLeftRestyleCount(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;
|
nsIFrame* mFrame;
|
||||||
|
nsIContent* mContent;
|
||||||
|
|
||||||
nsExpirationState mState;
|
nsExpirationState mState;
|
||||||
// Number of restyle operations detected
|
// Number of restyle operations detected
|
||||||
uint8_t mOpacityRestyleCount;
|
uint8_t mOpacityRestyleCount;
|
||||||
|
@ -93,7 +100,7 @@ static LayerActivityTracker* gLayerActivityTracker = nullptr;
|
||||||
|
|
||||||
LayerActivity::~LayerActivity()
|
LayerActivity::~LayerActivity()
|
||||||
{
|
{
|
||||||
if (mFrame) {
|
if (mFrame || mContent) {
|
||||||
NS_ASSERTION(gLayerActivityTracker, "Should still have a tracker");
|
NS_ASSERTION(gLayerActivityTracker, "Should still have a tracker");
|
||||||
gLayerActivityTracker->RemoveObject(this);
|
gLayerActivityTracker->RemoveObject(this);
|
||||||
}
|
}
|
||||||
|
@ -113,15 +120,24 @@ LayerActivityTracker::NotifyExpired(LayerActivity* aObject)
|
||||||
RemoveObject(aObject);
|
RemoveObject(aObject);
|
||||||
|
|
||||||
nsIFrame* f = aObject->mFrame;
|
nsIFrame* f = aObject->mFrame;
|
||||||
|
nsIContent* c = aObject->mContent;
|
||||||
aObject->mFrame = nullptr;
|
aObject->mFrame = nullptr;
|
||||||
|
aObject->mContent = nullptr;
|
||||||
|
|
||||||
// The pres context might have been detached during the delay -
|
MOZ_ASSERT((f == nullptr) != (c == nullptr),
|
||||||
// that's fine, just skip the paint.
|
"A LayerActivity object should always have a reference to either its frame or its content");
|
||||||
if (f->PresContext()->GetContainerWeak()) {
|
|
||||||
f->SchedulePaint();
|
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*
|
static LayerActivity*
|
||||||
|
@ -160,6 +176,39 @@ IncrementMutationCount(uint8_t* aCount)
|
||||||
*aCount = uint8_t(std::min(0xFF, *aCount + 1));
|
*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
|
/* static */ void
|
||||||
ActiveLayerTracker::NotifyRestyle(nsIFrame* aFrame, nsCSSProperty aProperty)
|
ActiveLayerTracker::NotifyRestyle(nsIFrame* aFrame, nsCSSProperty aProperty)
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "nsCSSProperty.h"
|
#include "nsCSSProperty.h"
|
||||||
|
|
||||||
class nsIFrame;
|
class nsIFrame;
|
||||||
|
class nsIContent;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
@ -64,6 +65,18 @@ public:
|
||||||
* as being animated for constructing active layers.
|
* as being animated for constructing active layers.
|
||||||
*/
|
*/
|
||||||
static bool IsOffsetOrMarginStyleAnimated(nsIFrame* aFrame);
|
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)
|
* We track modifications to the content of certain frames (i.e. canvas frames)
|
||||||
|
|
|
@ -93,6 +93,7 @@
|
||||||
#include "nsRefreshDriver.h"
|
#include "nsRefreshDriver.h"
|
||||||
#include "nsRuleProcessorData.h"
|
#include "nsRuleProcessorData.h"
|
||||||
#include "nsTextNode.h"
|
#include "nsTextNode.h"
|
||||||
|
#include "ActiveLayerTracker.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
@ -3828,6 +3829,7 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
|
||||||
!aItem.mContent->GetPrimaryFrame())) &&
|
!aItem.mContent->GetPrimaryFrame())) &&
|
||||||
!(bits & FCDATA_SKIP_FRAMESET)) {
|
!(bits & FCDATA_SKIP_FRAMESET)) {
|
||||||
aItem.mContent->SetPrimaryFrame(primaryFrame);
|
aItem.mContent->SetPrimaryFrame(primaryFrame);
|
||||||
|
ActiveLayerTracker::TransferActivityToFrame(aItem.mContent, primaryFrame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,7 @@
|
||||||
#include "mozilla/css/ImageLoader.h"
|
#include "mozilla/css/ImageLoader.h"
|
||||||
#include "mozilla/gfx/Tools.h"
|
#include "mozilla/gfx/Tools.h"
|
||||||
#include "nsPrintfCString.h"
|
#include "nsPrintfCString.h"
|
||||||
|
#include "ActiveLayerTracker.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::css;
|
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);
|
shell->NotifyDestroyingFrame(this);
|
||||||
|
|
||||||
if (mState & NS_FRAME_EXTERNAL_REFERENCE) {
|
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()
|
// Make sure that our deleted frame can't be returned from GetPrimaryFrame()
|
||||||
if (mContent && mContent->GetPrimaryFrame() == this) {
|
if (isPrimaryFrame) {
|
||||||
mContent->SetPrimaryFrame(nullptr);
|
mContent->SetPrimaryFrame(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче