Bug 1382078 Part 3 - Support media changes for XBL stylesheets. r=emilio

MozReview-Commit-ID: EJp8EMyanBT

--HG--
extra : rebase_source : 524aaa95070c7708b3c24a0c9ee8a24344be2645
This commit is contained in:
Ting-Yu Lin 2017-09-02 15:25:45 +08:00
Родитель 6d69dabd0c
Коммит d537ea001c
7 изменённых файлов: 138 добавлений и 30 удалений

Просмотреть файл

@ -50,6 +50,7 @@
#include "nsThreadUtils.h"
#include "mozilla/dom/NodeListBinding.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/ServoStyleSet.h"
#include "mozilla/Unused.h"
using namespace mozilla;
@ -745,19 +746,59 @@ nsBindingManager::MediumFeaturesChanged(nsPresContext* aPresContext)
{
bool rulesChanged = false;
RefPtr<nsPresContext> presContext = aPresContext;
bool isStyledByServo = mDocument->IsStyledByServo();
EnumerateBoundContentBindings([=, &rulesChanged](nsXBLBinding* aBinding) {
nsIStyleRuleProcessor* ruleProcessor =
aBinding->PrototypeBinding()->GetRuleProcessor();
if (ruleProcessor) {
bool thisChanged = ruleProcessor->MediumFeaturesChanged(presContext);
rulesChanged = rulesChanged || thisChanged;
if (isStyledByServo) {
ServoStyleSet* styleSet = aBinding->PrototypeBinding()->GetServoStyleSet();
if (styleSet) {
bool styleSetChanged = false;
if (styleSet->IsPresContextChanged(presContext)) {
styleSetChanged = true;
} else {
// PresContext is not changed. This means aPresContext is still
// alive since the last time it initialized this XBL styleset.
// It's safe to check whether medium features changed.
bool viewportUnitsUsed = false;
styleSetChanged =
styleSet->MediumFeaturesChangedRules(&viewportUnitsUsed);
MOZ_ASSERT(!viewportUnitsUsed,
"Non-master stylesets shouldn't get flagged as using "
"viewport units!");
}
rulesChanged = rulesChanged || styleSetChanged;
}
} else {
nsIStyleRuleProcessor* ruleProcessor =
aBinding->PrototypeBinding()->GetRuleProcessor();
if (ruleProcessor) {
bool thisChanged = ruleProcessor->MediumFeaturesChanged(presContext);
rulesChanged = rulesChanged || thisChanged;
}
}
});
return rulesChanged;
}
void
nsBindingManager::UpdateBoundContentBindingsForServo(nsPresContext* aPresContext)
{
MOZ_ASSERT(mDocument->IsStyledByServo(),
"This should be called only by servo-backend!");
RefPtr<nsPresContext> presContext = aPresContext;
EnumerateBoundContentBindings([=](nsXBLBinding* aBinding) {
nsXBLPrototypeBinding* protoBinding = aBinding->PrototypeBinding();
ServoStyleSet* styleSet = protoBinding->GetServoStyleSet();
if (styleSet && styleSet->StyleSheetsHaveChanged()) {
protoBinding->ComputeServoStyleSet(presContext);
}
});
}
void
nsBindingManager::AppendAllSheets(nsTArray<StyleSheet*>& aArray)
{

Просмотреть файл

@ -130,13 +130,17 @@ public:
void WalkAllRules(nsIStyleRuleProcessor::EnumFunc aFunc,
ElementDependentRuleProcessorData* aData);
/**
* Do any processing that needs to happen as a result of a change in
* the characteristics of the medium, and return whether this rule
* processor's rules have changed (e.g., because of media queries).
*/
// Do any processing that needs to happen as a result of a change in the
// characteristics of the medium, and return whether this rule processor's
// rules or the servo style set have changed (e.g., because of media
// queries).
bool MediumFeaturesChanged(nsPresContext* aPresContext);
// Update the content bindings in mBoundContentSet due to medium features
// changed.
void UpdateBoundContentBindingsForServo(nsPresContext* aPresContext);
void AppendAllSheets(nsTArray<mozilla::StyleSheet*>& aArray);
void Traverse(nsIContent *aContent,

Просмотреть файл

@ -569,6 +569,14 @@ nsXBLPrototypeBinding::GetRuleProcessor()
return nullptr;
}
void
nsXBLPrototypeBinding::ComputeServoStyleSet(nsPresContext* aPresContext)
{
if (mResources) {
mResources->ComputeServoStyleSet(aPresContext);
}
}
ServoStyleSet*
nsXBLPrototypeBinding::GetServoStyleSet() const
{

Просмотреть файл

@ -131,6 +131,7 @@ public:
void AppendStyleSheetsTo(nsTArray<mozilla::StyleSheet*>& aResult) const;
nsIStyleRuleProcessor* GetRuleProcessor();
void ComputeServoStyleSet(nsPresContext* aPresContext);
mozilla::ServoStyleSet* GetServoStyleSet() const;
nsresult FlushSkinSheets();

Просмотреть файл

@ -109,6 +109,8 @@ void
ServoStyleSet::Init(nsPresContext* aPresContext, nsBindingManager* aBindingManager)
{
mPresContext = aPresContext;
mPresContextInitXBLStyleSet = aPresContext;
mRawSet.reset(Servo_StyleSet_Init(aPresContext));
mBindingManager = aBindingManager;
@ -168,11 +170,15 @@ nsRestyleHint
ServoStyleSet::MediumFeaturesChanged(bool aViewportChanged)
{
bool viewportUnitsUsed = false;
const OriginFlags rulesChanged = static_cast<OriginFlags>(
Servo_StyleSet_MediumFeaturesChanged(mRawSet.get(), &viewportUnitsUsed));
bool rulesChanged = MediumFeaturesChangedRules(&viewportUnitsUsed);
if (rulesChanged != OriginFlags(0)) {
MarkOriginsDirty(rulesChanged);
if (mBindingManager &&
mBindingManager->MediumFeaturesChanged(mPresContext)) {
SetStylistXBLStyleSheetsDirty();
rulesChanged = true;
}
if (rulesChanged) {
return eRestyle_Subtree;
}
@ -183,6 +189,22 @@ ServoStyleSet::MediumFeaturesChanged(bool aViewportChanged)
return nsRestyleHint(0);
}
bool
ServoStyleSet::MediumFeaturesChangedRules(bool* aViewportUnitsUsed)
{
MOZ_ASSERT(aViewportUnitsUsed);
const OriginFlags rulesChanged = static_cast<OriginFlags>(
Servo_StyleSet_MediumFeaturesChanged(mRawSet.get(), aViewportUnitsUsed));
if (rulesChanged != OriginFlags(0)) {
MarkOriginsDirty(rulesChanged);
return true;
}
return false;
}
MOZ_DEFINE_MALLOC_SIZE_OF(ServoStyleSetMallocSizeOf)
void
@ -1372,13 +1394,21 @@ ServoStyleSet::UpdateStylist()
{
MOZ_ASSERT(StylistNeedsUpdate());
// There's no need to compute invalidations and such for an XBL styleset,
// since they are loaded and unloaded synchronously, and they don't have to
// deal with dynamic content changes.
Element* root =
IsMaster() ? mPresContext->Document()->GetDocumentElement() : nullptr;
if (mStylistState & StylistState::StyleSheetsDirty) {
// There's no need to compute invalidations and such for an XBL styleset,
// since they are loaded and unloaded synchronously, and they don't have to
// deal with dynamic content changes.
Element* root =
IsMaster() ? mPresContext->Document()->GetDocumentElement() : nullptr;
Servo_StyleSet_FlushStyleSheets(mRawSet.get(), root);
}
if (MOZ_UNLIKELY(mStylistState & StylistState::XBLStyleSheetsDirty)) {
MOZ_ASSERT(IsMaster(), "Only master styleset can mark XBL stylesets dirty!");
mBindingManager->UpdateBoundContentBindingsForServo(mPresContext);
}
Servo_StyleSet_FlushStyleSheets(mRawSet.get(), root);
mStylistState = StylistState::NotDirty;
}

Просмотреть файл

@ -46,18 +46,22 @@ struct TreeMatchContext;
namespace mozilla {
/**
* A few flags used to track which kind of stylist state we may need to
* update.
*/
// A few flags used to track which kind of stylist state we may need to
// update.
enum class StylistState : uint8_t {
/** The stylist is not dirty, we should do nothing */
// The stylist is not dirty, we should do nothing.
NotDirty = 0,
/** The style sheets have changed, so we need to update the style data. */
StyleSheetsDirty,
// The style sheets have changed, so we need to update the style data.
StyleSheetsDirty = 1 << 0,
// Some of the style sheets of the bound elements in binding manager have
// changed, so we need to tell the binding manager to update style data.
XBLStyleSheetsDirty = 1 << 1,
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(StylistState)
// Bitfield type to represent Servo stylesheet origins.
enum class OriginFlags : uint8_t {
UserAgent = 0x01,
@ -133,6 +137,9 @@ public:
nsRestyleHint MediumFeaturesChanged(bool aViewportChanged);
// aViewportChanged outputs whether any viewport units is used.
bool MediumFeaturesChangedRules(bool* aViewportUnitsUsed);
void InvalidateStyleForCSSRuleChanges();
void AddSizeOfIncludingThis(nsWindowSizes& aSizes) const;
@ -433,6 +440,11 @@ public:
mPresContext = nullptr;
}
// Return whether this is the PresContext that initialized us.
bool IsPresContextChanged(nsPresContext* aPresContext) const {
return aPresContext != mPresContextInitXBLStyleSet;
}
/**
* Returns true if a modification to an an attribute with the specified
* local name might require us to restyle the element.
@ -525,7 +537,12 @@ private:
*/
void SetStylistStyleSheetsDirty()
{
mStylistState = StylistState::StyleSheetsDirty;
mStylistState |= StylistState::StyleSheetsDirty;
}
void SetStylistXBLStyleSheetsDirty()
{
mStylistState |= StylistState::XBLStyleSheetsDirty;
}
bool StylistNeedsUpdate() const
@ -565,7 +582,15 @@ private:
ServoStyleSheet* aSheet);
const Kind mKind;
nsPresContext* mPresContext;
// Nullptr if this is an XBL style set.
nsPresContext* MOZ_NON_OWNING_REF mPresContext = nullptr;
// Because XBL style set could be used by multiple PresContext, we need to
// store the PresContext pointer which initializes this style set for
// computing medium rule changes.
void* MOZ_NON_OWNING_REF mPresContextInitXBLStyleSet = nullptr;
UniquePtr<RawServoStyleSet> mRawSet;
EnumeratedArray<SheetType, SheetType::Count,
nsTArray<RefPtr<ServoStyleSheet>>> mSheets;

Просмотреть файл

@ -242,7 +242,6 @@ skip-if = !stylo
skip-if = android_version == '18' #debug-only failure; timed out #Android 4.3 aws only; bug 1030419
[test_media_queries_dynamic.html]
[test_media_queries_dynamic_xbl.html]
fail-if = stylo # bug 1382078
[test_media_query_list.html]
[test_media_query_serialization.html]
[test_moz_device_pixel_ratio.html]