mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-12 06:52:25 +00:00
Bug 822721: Call CalcStyleDifference and process the style change list resulting from the miniflush we do to update throttled animations prior to seeing if we need to start transitions. r=bzbarsky a=blocking-basecamp
The CalcStyleDifference call is absolutely necessary even if we didn't need to process the change list, because it causes the new style context to have cached structs that we might need for a later comparison. This is important because, as an optimization, we only compare structs that have been retrieved. This optimization requires that when we replace a style context, we fetch all the structs on the new style context that had been fetched on the old style context (which is normally necessary anyway in order to do comparison so we can process the changes appropriately). However, actually processing the change list is also necessary to fix the bug; it's the actual change from the miniflush that matters here. Based on dholbert's debugging information, I think it's mostly likely because we were failing to process the UpdateOverflow hint.
This commit is contained in:
parent
efcbedeeba
commit
d4f14d0985
@ -28,6 +28,7 @@
|
||||
#include "Layers.h"
|
||||
#include "FrameLayerBuilder.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsStyleChangeList.h"
|
||||
|
||||
using mozilla::TimeStamp;
|
||||
using mozilla::TimeDuration;
|
||||
@ -251,7 +252,8 @@ ForceLayerRerendering(nsIFrame* aFrame, CommonElementAnimationData* aData)
|
||||
|
||||
nsStyleContext*
|
||||
nsTransitionManager::UpdateThrottledStyle(dom::Element* aElement,
|
||||
nsStyleContext* aParentStyle)
|
||||
nsStyleContext* aParentStyle,
|
||||
nsStyleChangeList& aChangeList)
|
||||
{
|
||||
NS_ASSERTION(GetElementTransitions(aElement,
|
||||
nsCSSPseudoElements::ePseudo_NotPseudoElement,
|
||||
@ -283,6 +285,7 @@ nsTransitionManager::UpdateThrottledStyle(dom::Element* aElement,
|
||||
mPresContext->AnimationManager()->EnsureStyleRuleFor(ea);
|
||||
curRule.mRule = ea->mStyleRule;
|
||||
|
||||
// FIXME: maybe not needed anymore:
|
||||
ForceLayerRerendering(primaryFrame, ea);
|
||||
} else if (curRule.mLevel == nsStyleSet::eTransitionSheet) {
|
||||
ElementTransitions *et =
|
||||
@ -292,6 +295,7 @@ nsTransitionManager::UpdateThrottledStyle(dom::Element* aElement,
|
||||
et->EnsureStyleRuleFor(mPresContext->RefreshDriver()->MostRecentRefresh());
|
||||
curRule.mRule = et->mStyleRule;
|
||||
|
||||
// FIXME: maybe not needed anymore:
|
||||
ForceLayerRerendering(primaryFrame, et);
|
||||
} else {
|
||||
curRule.mRule = ruleNode->GetRule();
|
||||
@ -304,6 +308,21 @@ nsTransitionManager::UpdateThrottledStyle(dom::Element* aElement,
|
||||
|
||||
nsRefPtr<nsStyleContext> newStyle = mPresContext->PresShell()->StyleSet()->
|
||||
ResolveStyleForRules(aParentStyle, oldStyle, rules);
|
||||
|
||||
// We absolutely must call CalcStyleDifference in order to ensure the
|
||||
// new context has all the structs cached that the old context had.
|
||||
// We also need it for processing of the changes.
|
||||
nsChangeHint styleChange =
|
||||
oldStyle->CalcStyleDifference(newStyle, nsChangeHint(0));
|
||||
// This isn't particularly dangerous, but I want to catch if it happens:
|
||||
NS_ABORT_IF_FALSE(NS_IsHintSubset(styleChange,
|
||||
NS_CombineHint(nsChangeHint_UpdateOpacityLayer,
|
||||
NS_CombineHint(nsChangeHint_UpdateTransformLayer,
|
||||
nsChangeHint_UpdateOverflow))),
|
||||
"unexpected change hint");
|
||||
aChangeList.AppendChange(primaryFrame, primaryFrame->GetContent(),
|
||||
styleChange);
|
||||
|
||||
primaryFrame->SetStyleContextWithoutNotification(newStyle);
|
||||
|
||||
ReparentBeforeAndAfter(aElement, primaryFrame, newStyle, mPresContext->PresShell()->StyleSet());
|
||||
@ -313,7 +332,8 @@ nsTransitionManager::UpdateThrottledStyle(dom::Element* aElement,
|
||||
|
||||
void
|
||||
nsTransitionManager::UpdateThrottledStylesForSubtree(nsIContent* aContent,
|
||||
nsStyleContext* aParentStyle)
|
||||
nsStyleContext* aParentStyle,
|
||||
nsStyleChangeList& aChangeList)
|
||||
{
|
||||
dom::Element* element;
|
||||
if (aContent->IsElement()) {
|
||||
@ -330,7 +350,7 @@ nsTransitionManager::UpdateThrottledStylesForSubtree(nsIContent* aContent,
|
||||
nsCSSPseudoElements::ePseudo_NotPseudoElement,
|
||||
false))) {
|
||||
// re-resolve our style
|
||||
newStyle = UpdateThrottledStyle(element, aParentStyle);
|
||||
newStyle = UpdateThrottledStyle(element, aParentStyle, aChangeList);
|
||||
// remove the current transition from the working set
|
||||
et->mFlushGeneration = mPresContext->RefreshDriver()->MostRecentRefresh();
|
||||
} else {
|
||||
@ -351,7 +371,7 @@ nsTransitionManager::UpdateThrottledStylesForSubtree(nsIContent* aContent,
|
||||
if (newStyle) {
|
||||
for (nsIContent *child = aContent->GetFirstChild(); child;
|
||||
child = child->GetNextSibling()) {
|
||||
UpdateThrottledStylesForSubtree(child, newStyle);
|
||||
UpdateThrottledStylesForSubtree(child, newStyle, aChangeList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -373,6 +393,8 @@ nsTransitionManager::UpdateAllThrottledStyles()
|
||||
mPresContext->TickLastUpdateThrottledStyle();
|
||||
TimeStamp now = mPresContext->RefreshDriver()->MostRecentRefresh();
|
||||
|
||||
nsStyleChangeList changeList;
|
||||
|
||||
// update each transitioning element by finding its root-most ancestor with a
|
||||
// transition, and flushing the style on that ancestor and all its descendants
|
||||
PRCList *next = PR_LIST_HEAD(&mElementData);
|
||||
@ -409,9 +431,12 @@ nsTransitionManager::UpdateAllThrottledStyles()
|
||||
if (element &&
|
||||
(primaryFrame = element->GetPrimaryFrame())) {
|
||||
UpdateThrottledStylesForSubtree(element,
|
||||
primaryFrame->GetStyleContext()->GetParent());
|
||||
primaryFrame->GetStyleContext()->GetParent(), changeList);
|
||||
}
|
||||
}
|
||||
|
||||
mPresContext->PresShell()->FrameConstructor()->
|
||||
ProcessRestyledFrames(changeList);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIStyleRule>
|
||||
|
@ -220,12 +220,14 @@ private:
|
||||
// If the element has a transition, it is flushed back to its primary frame.
|
||||
// If the element does not have a transition, then its style is reparented.
|
||||
void UpdateThrottledStylesForSubtree(nsIContent* aContent,
|
||||
nsStyleContext* aParentStyle);
|
||||
nsStyleContext* aParentStyle,
|
||||
nsStyleChangeList &aChangeList);
|
||||
// Update the style on aElement from the transition stored in this manager and
|
||||
// the new parent style - aParentStyle. aElement must be transitioning or
|
||||
// animated. Returns the updated style.
|
||||
nsStyleContext* UpdateThrottledStyle(mozilla::dom::Element* aElement,
|
||||
nsStyleContext* aParentStyle);
|
||||
nsStyleContext* aParentStyle,
|
||||
nsStyleChangeList &aChangeList);
|
||||
};
|
||||
|
||||
#endif /* !defined(nsTransitionManager_h_) */
|
||||
|
Loading…
x
Reference in New Issue
Block a user