--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -32,16 +32,23 @@ ServoRestyleManager::PostRestyleEvent(El
{
MOZ_ASSERT(!(aMinChangeHint & nsChangeHint_NeutralChange),
"Didn't expect explicit change hints to be neutral!");
if (MOZ_UNLIKELY(IsDisconnected()) ||
MOZ_UNLIKELY(PresContext()->PresShell()->IsDestroying())) {
return;
}
+ if (mInStyleRefresh && aRestyleHint == eRestyle_CSSAnimations) {
+ // FIXME: This is the initial restyle for CSS animations when the animation
+ // is created. We have to process this restyle if necessary. Currently we
+ // skip it here and will do this restyle in the next tick.
+ return;
+ }
+
if (aRestyleHint == 0 && !aMinChangeHint && !HasPendingRestyles()) {
return; // Nothing to do.
}
// We allow posting change hints during restyling, but not restyle hints
// themselves, since those would require us to re-traverse the tree.
MOZ_ASSERT_IF(mInStyleRefresh, aRestyleHint == 0);
@@ -164,17 +171,17 @@ ServoRestyleManager::RecreateStyleContex
// pointer during the replacement. In practice it's not a huge deal (on
// GetNextContinuationWithSameStyle the pointer is not dereferenced, only
// compared), but better not playing with dangling pointers if not needed.
RefPtr<nsStyleContext> oldStyleContext = primaryFrame->StyleContext();
MOZ_ASSERT(oldStyleContext);
RefPtr<nsStyleContext> newContext =
aStyleSet->GetContext(computedValues.forget(), aParentContext, nullptr,
- CSSPseudoElementType::NotPseudo);
+ CSSPseudoElementType::NotPseudo, aElement);
// XXX This could not always work as expected: there are kinds of content
// with the first split and the last sharing style, but others not. We
// should handle those properly.
for (nsIFrame* f = primaryFrame; f;
f = GetNextContinuationWithSameStyle(f, oldStyleContext)) {
f->SetStyleContext(newContext);
}
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -6,16 +6,17 @@
#include "mozilla/ServoStyleSet.h"
#include "mozilla/DocumentStyleRootIterator.h"
#include "mozilla/ServoRestyleManager.h"
#include "mozilla/dom/ChildIterator.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ElementInlines.h"
+#include "nsAnimationManager.h"
#include "nsCSSAnonBoxes.h"
#include "nsCSSPseudoElements.h"
#include "nsIDocumentInlines.h"
#include "nsPrintfCString.h"
#include "nsStyleContext.h"
#include "nsStyleSet.h"
using namespace mozilla;
@@ -130,33 +131,54 @@ ServoStyleSet::GetContext(nsIContent* aC
if (aMayCompute == LazyComputeBehavior::Allow) {
computedValues =
Servo_ResolveStyleLazily(element, nullptr, mRawSet.get()).Consume();
} else {
computedValues = ResolveServoStyle(element);
}
MOZ_ASSERT(computedValues);
- return GetContext(computedValues.forget(), aParentContext, aPseudoTag, aPseudoType);
+ return GetContext(computedValues.forget(), aParentContext, aPseudoTag, aPseudoType,
+ element);
}
already_AddRefed<nsStyleContext>
ServoStyleSet::GetContext(already_AddRefed<ServoComputedValues> aComputedValues,
nsStyleContext* aParentContext,
nsIAtom* aPseudoTag,
- CSSPseudoElementType aPseudoType)
+ CSSPseudoElementType aPseudoType,
+ Element* aElementForAnimation)
{
// XXXbholley: nsStyleSet does visited handling here.
// XXXbholley: Figure out the correct thing to pass here. Does this fixup
// duplicate something that servo already does?
bool skipFixup = false;
- return NS_NewStyleContext(aParentContext, mPresContext, aPseudoTag,
- aPseudoType, Move(aComputedValues), skipFixup);
+ RefPtr<nsStyleContext> result =
+ NS_NewStyleContext(aParentContext, mPresContext, aPseudoTag,
+ aPseudoType, Move(aComputedValues), skipFixup);
+
+ // Ignore animations for print or print preview, and for elements
+ // that are not attached to the document tree.
+ if (mPresContext->IsDynamic() &&
+ aElementForAnimation &&
+ aElementForAnimation->IsInComposedDoc()) {
+ // Update/build CSS animations in the case where animation properties are
+ // changed.
+ // FIXME: This isn't right place to update CSS animations. We should do it
+ // , presumably, in cascade_node() in servo side and process the initial
+ // restyle there too.
+ // To do that we need to make updating CSS animations process independent
+ // from nsStyleContext. Also we need to make the process thread safe.
+ mPresContext->AnimationManager()->UpdateAnimations(result,
+ aElementForAnimation);
+ }
+
+ return result.forget();
}
already_AddRefed<nsStyleContext>
ServoStyleSet::ResolveStyleFor(Element* aElement,
nsStyleContext* aParentContext,
LazyComputeBehavior aMayCompute,
TreeMatchContext& aTreeMatchContext)
{
@@ -179,33 +201,35 @@ ServoStyleSet::ResolveStyleForText(nsICo
// enough to do on the main thread, which means that the parallel style system
// can avoid worrying about text nodes.
const ServoComputedValues* parentComputedValues =
aParentContext->StyleSource().AsServoComputedValues();
RefPtr<ServoComputedValues> computedValues =
Servo_ComputedValues_Inherit(mRawSet.get(), parentComputedValues).Consume();
return GetContext(computedValues.forget(), aParentContext,
- nsCSSAnonBoxes::mozText, CSSPseudoElementType::AnonBox);
+ nsCSSAnonBoxes::mozText, CSSPseudoElementType::AnonBox,
+ nullptr);
}
already_AddRefed<nsStyleContext>
ServoStyleSet::ResolveStyleForOtherNonElement(nsStyleContext* aParentContext)
{
// The parent context can be null if the non-element share a style context
// with the root of an anonymous subtree.
const ServoComputedValues* parent =
aParentContext ? aParentContext->StyleSource().AsServoComputedValues() : nullptr;
RefPtr<ServoComputedValues> computedValues =
Servo_ComputedValues_Inherit(mRawSet.get(), parent).Consume();
MOZ_ASSERT(computedValues);
return GetContext(computedValues.forget(), aParentContext,
nsCSSAnonBoxes::mozOtherNonElement,
- CSSPseudoElementType::AnonBox);
+ CSSPseudoElementType::AnonBox,
+ nullptr);
}
already_AddRefed<nsStyleContext>
ServoStyleSet::ResolvePseudoElementStyle(Element* aOriginatingElement,
CSSPseudoElementType aType,
nsStyleContext* aParentContext,
Element* aPseudoElement)
{
@@ -219,31 +243,35 @@ ServoStyleSet::ResolvePseudoElementStyle
MOZ_ASSERT(aType < CSSPseudoElementType::Count);
nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
RefPtr<ServoComputedValues> computedValues =
Servo_ResolvePseudoStyle(aOriginatingElement, pseudoTag,
/* is_probe = */ false, mRawSet.get()).Consume();
MOZ_ASSERT(computedValues);
- return GetContext(computedValues.forget(), aParentContext, pseudoTag, aType);
+ bool isBeforeOrAfter = aType == CSSPseudoElementType::before ||
+ aType == CSSPseudoElementType::after;
+ return GetContext(computedValues.forget(), aParentContext, pseudoTag, aType,
+ isBeforeOrAfter ? aOriginatingElement : nullptr);
}
already_AddRefed<nsStyleContext>
ServoStyleSet::ResolveTransientStyle(Element* aElement, CSSPseudoElementType aType)
{
nsIAtom* pseudoTag = nullptr;
if (aType != CSSPseudoElementType::NotPseudo) {
pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
}
RefPtr<ServoComputedValues> computedValues =
Servo_ResolveStyleLazily(aElement, pseudoTag, mRawSet.get()).Consume();
- return GetContext(computedValues.forget(), nullptr, pseudoTag, aType);
+ return GetContext(computedValues.forget(), nullptr, pseudoTag, aType,
+ nullptr);
}
// aFlags is an nsStyleSet flags bitfield
already_AddRefed<nsStyleContext>
ServoStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag,
nsStyleContext* aParentContext,
uint32_t aFlags)
{
@@ -453,29 +481,30 @@ ServoStyleSet::ProbePseudoElementStyle(E
/* is_probe = */ true, mRawSet.get()).Consume();
if (!computedValues) {
return nullptr;
}
// For :before and :after pseudo-elements, having display: none or no
// 'content' property is equivalent to not having the pseudo-element
// at all.
- if (computedValues &&
- (pseudoTag == nsCSSPseudoElements::before ||
- pseudoTag == nsCSSPseudoElements::after)) {
+ bool isBeforeOrAfter = pseudoTag == nsCSSPseudoElements::before ||
+ pseudoTag == nsCSSPseudoElements::after;
+ if (isBeforeOrAfter) {
const nsStyleDisplay *display = Servo_GetStyleDisplay(computedValues);
const nsStyleContent *content = Servo_GetStyleContent(computedValues);
// XXXldb What is contentCount for |content: ""|?
if (display->mDisplay == StyleDisplay::None ||
content->ContentCount() == 0) {
return nullptr;
}
}
- return GetContext(computedValues.forget(), aParentContext, pseudoTag, aType);
+ return GetContext(computedValues.forget(), aParentContext, pseudoTag, aType,
+ isBeforeOrAfter ? aOriginatingElement : nullptr);
}
already_AddRefed<nsStyleContext>
ServoStyleSet::ProbePseudoElementStyle(Element* aOriginatingElement,
CSSPseudoElementType aType,
nsStyleContext* aParentContext,
TreeMatchContext& aTreeMatchContext,
Element* aPseudoElement)
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -185,17 +185,18 @@ public:
const nsTimingFunction& aTimingFunction,
const ServoComputedValues* aComputedValues,
nsTArray<Keyframe>& aKeyframes);
private:
already_AddRefed<nsStyleContext> GetContext(already_AddRefed<ServoComputedValues>,
nsStyleContext* aParentContext,
nsIAtom* aPseudoTag,
- CSSPseudoElementType aPseudoType);
+ CSSPseudoElementType aPseudoType,
+ dom::Element* aElementForAnimation);
already_AddRefed<nsStyleContext> GetContext(nsIContent* aContent,
nsStyleContext* aParentContext,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType,
LazyComputeBehavior aMayCompute);
nsPresContext* mPresContext;