зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1201330 - Keep scroll handler induced layer activity active until the scroll frame becomes inactive. r=roc
--HG-- extra : commitid : K9ntCNQz1Fx extra : rebase_source : ed8a567f22626d7074bbc58eb5e61baa251fe2c3
This commit is contained in:
Родитель
d4830adc3d
Коммит
ef4655be32
|
@ -97,6 +97,13 @@ public:
|
||||||
// Previous scale due to the CSS transform property.
|
// Previous scale due to the CSS transform property.
|
||||||
Maybe<gfxSize> mPreviousTransformScale;
|
Maybe<gfxSize> mPreviousTransformScale;
|
||||||
|
|
||||||
|
// The scroll frame during for which we most recently received a call to
|
||||||
|
// NotifyAnimatedFromScrollHandler.
|
||||||
|
nsWeakFrame mAnimatingScrollHandlerFrame;
|
||||||
|
// The set of activities that were triggered during
|
||||||
|
// mAnimatingScrollHandlerFrame's scroll event handler.
|
||||||
|
EnumSet<ActivityIndex> mScrollHandlerInducedActivity;
|
||||||
|
|
||||||
// Number of restyle operations detected
|
// Number of restyle operations detected
|
||||||
uint8_t mRestyleCounts[ACTIVITY_COUNT];
|
uint8_t mRestyleCounts[ACTIVITY_COUNT];
|
||||||
bool mContentActive;
|
bool mContentActive;
|
||||||
|
@ -109,12 +116,20 @@ public:
|
||||||
LayerActivityTracker()
|
LayerActivityTracker()
|
||||||
: nsExpirationTracker<LayerActivity,4>(GENERATION_MS,
|
: nsExpirationTracker<LayerActivity,4>(GENERATION_MS,
|
||||||
"LayerActivityTracker")
|
"LayerActivityTracker")
|
||||||
|
, mDestroying(false)
|
||||||
{}
|
{}
|
||||||
~LayerActivityTracker() {
|
~LayerActivityTracker() {
|
||||||
|
mDestroying = true;
|
||||||
AgeAllGenerations();
|
AgeAllGenerations();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void NotifyExpired(LayerActivity* aObject);
|
virtual void NotifyExpired(LayerActivity* aObject);
|
||||||
|
|
||||||
|
public:
|
||||||
|
nsWeakFrame mCurrentScrollHandlerFrame;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool mDestroying;
|
||||||
};
|
};
|
||||||
|
|
||||||
static LayerActivityTracker* gLayerActivityTracker = nullptr;
|
static LayerActivityTracker* gLayerActivityTracker = nullptr;
|
||||||
|
@ -133,6 +148,13 @@ NS_DECLARE_FRAME_PROPERTY(LayerActivityProperty, DeleteValue<LayerActivity>)
|
||||||
void
|
void
|
||||||
LayerActivityTracker::NotifyExpired(LayerActivity* aObject)
|
LayerActivityTracker::NotifyExpired(LayerActivity* aObject)
|
||||||
{
|
{
|
||||||
|
if (!mDestroying && aObject->mAnimatingScrollHandlerFrame.IsAlive()) {
|
||||||
|
// Reset the restyle counts, but let the layer activity survive.
|
||||||
|
PodArrayZero(aObject->mRestyleCounts);
|
||||||
|
MarkUsed(aObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RemoveObject(aObject);
|
RemoveObject(aObject);
|
||||||
|
|
||||||
nsIFrame* f = aObject->mFrame;
|
nsIFrame* f = aObject->mFrame;
|
||||||
|
@ -294,6 +316,27 @@ ActiveLayerTracker::NotifyAnimated(nsIFrame* aFrame, nsCSSProperty aProperty)
|
||||||
mutationCount = 0xFF;
|
mutationCount = 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
ActiveLayerTracker::NotifyAnimatedFromScrollHandler(nsIFrame* aFrame, nsCSSProperty aProperty,
|
||||||
|
nsIFrame* aScrollFrame)
|
||||||
|
{
|
||||||
|
if (aFrame->PresContext() != aScrollFrame->PresContext()) {
|
||||||
|
// Don't allow cross-document dependencies.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LayerActivity* layerActivity = GetLayerActivityForUpdate(aFrame);
|
||||||
|
LayerActivity::ActivityIndex activityIndex = LayerActivity::GetActivityIndexForProperty(aProperty);
|
||||||
|
|
||||||
|
if (layerActivity->mAnimatingScrollHandlerFrame.GetFrame() != aScrollFrame) {
|
||||||
|
// Discard any activity of a different scroll frame. We only track the
|
||||||
|
// most recent scroll handler induced activity.
|
||||||
|
layerActivity->mScrollHandlerInducedActivity.clear();
|
||||||
|
layerActivity->mAnimatingScrollHandlerFrame = aScrollFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
layerActivity->mScrollHandlerInducedActivity += activityIndex;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
IsPresContextInScriptAnimationCallback(nsPresContext* aPresContext)
|
IsPresContextInScriptAnimationCallback(nsPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
|
@ -310,10 +353,14 @@ IsPresContextInScriptAnimationCallback(nsPresContext* aPresContext)
|
||||||
ActiveLayerTracker::NotifyInlineStyleRuleModified(nsIFrame* aFrame,
|
ActiveLayerTracker::NotifyInlineStyleRuleModified(nsIFrame* aFrame,
|
||||||
nsCSSProperty aProperty)
|
nsCSSProperty aProperty)
|
||||||
{
|
{
|
||||||
if (!IsPresContextInScriptAnimationCallback(aFrame->PresContext())) {
|
if (IsPresContextInScriptAnimationCallback(aFrame->PresContext())) {
|
||||||
return;
|
NotifyAnimated(aFrame, aProperty);
|
||||||
|
}
|
||||||
|
if (gLayerActivityTracker &&
|
||||||
|
gLayerActivityTracker->mCurrentScrollHandlerFrame.IsAlive()) {
|
||||||
|
NotifyAnimatedFromScrollHandler(aFrame, aProperty,
|
||||||
|
gLayerActivityTracker->mCurrentScrollHandlerFrame.GetFrame());
|
||||||
}
|
}
|
||||||
NotifyAnimated(aFrame, aProperty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
|
@ -322,6 +369,29 @@ ActiveLayerTracker::IsStyleMaybeAnimated(nsIFrame* aFrame, nsCSSProperty aProper
|
||||||
return IsStyleAnimated(nullptr, aFrame, aProperty);
|
return IsStyleAnimated(nullptr, aFrame, aProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
CheckScrollInducedActivity(LayerActivity* aLayerActivity,
|
||||||
|
LayerActivity::ActivityIndex aActivityIndex,
|
||||||
|
nsDisplayListBuilder* aBuilder)
|
||||||
|
{
|
||||||
|
if (!aLayerActivity->mScrollHandlerInducedActivity.contains(aActivityIndex) ||
|
||||||
|
!aLayerActivity->mAnimatingScrollHandlerFrame.IsAlive()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIScrollableFrame* scrollFrame =
|
||||||
|
do_QueryFrame(aLayerActivity->mAnimatingScrollHandlerFrame.GetFrame());
|
||||||
|
if (scrollFrame && (!aBuilder || scrollFrame->IsScrollingActive(aBuilder))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The scroll frame has been destroyed or has become inactive. Clear it from
|
||||||
|
// the layer activity so that it can expire.
|
||||||
|
aLayerActivity->mAnimatingScrollHandlerFrame = nullptr;
|
||||||
|
aLayerActivity->mScrollHandlerInducedActivity.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
ActiveLayerTracker::IsStyleAnimated(nsDisplayListBuilder* aBuilder,
|
ActiveLayerTracker::IsStyleAnimated(nsDisplayListBuilder* aBuilder,
|
||||||
nsIFrame* aFrame, nsCSSProperty aProperty)
|
nsIFrame* aFrame, nsCSSProperty aProperty)
|
||||||
|
@ -340,7 +410,11 @@ ActiveLayerTracker::IsStyleAnimated(nsDisplayListBuilder* aBuilder,
|
||||||
|
|
||||||
LayerActivity* layerActivity = GetLayerActivity(aFrame);
|
LayerActivity* layerActivity = GetLayerActivity(aFrame);
|
||||||
if (layerActivity) {
|
if (layerActivity) {
|
||||||
if (layerActivity->RestyleCountForProperty(aProperty) >= 2) {
|
LayerActivity::ActivityIndex activityIndex = LayerActivity::GetActivityIndexForProperty(aProperty);
|
||||||
|
if (layerActivity->mRestyleCounts[activityIndex] >= 2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (CheckScrollInducedActivity(layerActivity, activityIndex, aBuilder)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -458,6 +532,15 @@ ActiveLayerTracker::IsContentActive(nsIFrame* aFrame)
|
||||||
return layerActivity && layerActivity->mContentActive;
|
return layerActivity && layerActivity->mContentActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
ActiveLayerTracker::SetCurrentScrollHandlerFrame(nsIFrame* aFrame)
|
||||||
|
{
|
||||||
|
if (!gLayerActivityTracker) {
|
||||||
|
gLayerActivityTracker = new LayerActivityTracker();
|
||||||
|
}
|
||||||
|
gLayerActivityTracker->mCurrentScrollHandlerFrame = aFrame;
|
||||||
|
}
|
||||||
|
|
||||||
/* static */ void
|
/* static */ void
|
||||||
ActiveLayerTracker::Shutdown()
|
ActiveLayerTracker::Shutdown()
|
||||||
{
|
{
|
||||||
|
|
|
@ -49,6 +49,12 @@ public:
|
||||||
* Any such marking will time out after a short period.
|
* Any such marking will time out after a short period.
|
||||||
*/
|
*/
|
||||||
static void NotifyAnimated(nsIFrame* aFrame, nsCSSProperty aProperty);
|
static void NotifyAnimated(nsIFrame* aFrame, nsCSSProperty aProperty);
|
||||||
|
/**
|
||||||
|
* Notify aFrame as being known to have an animation of aProperty through an
|
||||||
|
* inline style modification during aScrollFrame's scroll event handler.
|
||||||
|
*/
|
||||||
|
static void NotifyAnimatedFromScrollHandler(nsIFrame* aFrame, nsCSSProperty aProperty,
|
||||||
|
nsIFrame* aScrollFrame);
|
||||||
/**
|
/**
|
||||||
* Notify that a property in the inline style rule of aFrame's element
|
* Notify that a property in the inline style rule of aFrame's element
|
||||||
* has been modified.
|
* has been modified.
|
||||||
|
@ -107,6 +113,13 @@ public:
|
||||||
* Return true if this frame's content is still marked as active.
|
* Return true if this frame's content is still marked as active.
|
||||||
*/
|
*/
|
||||||
static bool IsContentActive(nsIFrame* aFrame);
|
static bool IsContentActive(nsIFrame* aFrame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called before and after a scroll event handler is executed, with the
|
||||||
|
* scrollframe or nullptr, respectively. This acts as a hint to treat
|
||||||
|
* inline style changes during the handler differently.
|
||||||
|
*/
|
||||||
|
static void SetCurrentScrollHandlerFrame(nsIFrame* aFrame);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -4206,6 +4206,7 @@ ScrollFrameHelper::FireScrollEvent()
|
||||||
{
|
{
|
||||||
mScrollEvent.Forget();
|
mScrollEvent.Forget();
|
||||||
|
|
||||||
|
ActiveLayerTracker::SetCurrentScrollHandlerFrame(mOuter);
|
||||||
WidgetGUIEvent event(true, eScroll, nullptr);
|
WidgetGUIEvent event(true, eScroll, nullptr);
|
||||||
nsEventStatus status = nsEventStatus_eIgnore;
|
nsEventStatus status = nsEventStatus_eIgnore;
|
||||||
nsIContent* content = mOuter->GetContent();
|
nsIContent* content = mOuter->GetContent();
|
||||||
|
@ -4223,6 +4224,7 @@ ScrollFrameHelper::FireScrollEvent()
|
||||||
event.mFlags.mBubbles = false;
|
event.mFlags.mBubbles = false;
|
||||||
EventDispatcher::Dispatch(content, prescontext, &event, nullptr, &status);
|
EventDispatcher::Dispatch(content, prescontext, &event, nullptr, &status);
|
||||||
}
|
}
|
||||||
|
ActiveLayerTracker::SetCurrentScrollHandlerFrame(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -127,6 +127,14 @@ public:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear
|
||||||
|
*/
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
mBitField = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Intersection
|
* Intersection
|
||||||
*/
|
*/
|
||||||
|
|
Загрузка…
Ссылка в новой задаче