mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
Bug 1435939: Process all the MediumFeatureChanges at the same time. r=xidorn
This avoids resetting the computed values all the time, and paves the way to avoid using a StyleSet on XBL bindings / Shadow DOM, which we should really really do because it's super overkill. There are some XBL bits that are kind of hacky, in particular the mStylistDirty, but they'll go away soon, since I want to redo how we store styles in XBL. The alternative, which was returning an array of indices or something was even more hacky I think. MozReview-Commit-ID: 6tEl5gebXVF
This commit is contained in:
parent
75abcdb1ca
commit
c2f6e9ff37
@ -767,47 +767,24 @@ bool
|
||||
nsBindingManager::MediumFeaturesChanged(nsPresContext* aPresContext,
|
||||
mozilla::MediaFeatureChangeReason aReason)
|
||||
{
|
||||
MOZ_ASSERT(!mDocument->IsStyledByServo());
|
||||
#ifdef MOZ_OLD_STYLE
|
||||
bool rulesChanged = false;
|
||||
RefPtr<nsPresContext> presContext = aPresContext;
|
||||
bool isStyledByServo = mDocument->IsStyledByServo();
|
||||
|
||||
EnumerateBoundContentBindings([=, &rulesChanged](nsXBLBinding* aBinding) {
|
||||
if (isStyledByServo) {
|
||||
ServoStyleSet* styleSet = aBinding->PrototypeBinding()->GetServoStyleSet();
|
||||
if (styleSet) {
|
||||
bool styleSetChanged = false;
|
||||
|
||||
if (styleSet->IsPresContextChanged(presContext)) {
|
||||
styleSetChanged = styleSet->SetPresContext(presContext);
|
||||
} 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, aReason);
|
||||
MOZ_ASSERT(!viewportUnitsUsed,
|
||||
"Non-master stylesets shouldn't get flagged as using "
|
||||
"viewport units!");
|
||||
}
|
||||
rulesChanged = rulesChanged || styleSetChanged;
|
||||
}
|
||||
} else {
|
||||
#ifdef MOZ_OLD_STYLE
|
||||
nsIStyleRuleProcessor* ruleProcessor =
|
||||
aBinding->PrototypeBinding()->GetRuleProcessor();
|
||||
if (ruleProcessor) {
|
||||
bool thisChanged = ruleProcessor->MediumFeaturesChanged(presContext);
|
||||
rulesChanged = rulesChanged || thisChanged;
|
||||
}
|
||||
#else
|
||||
MOZ_CRASH("old style system disabled");
|
||||
#endif
|
||||
nsIStyleRuleProcessor* ruleProcessor =
|
||||
aBinding->PrototypeBinding()->GetRuleProcessor();
|
||||
if (ruleProcessor) {
|
||||
bool thisChanged = ruleProcessor->MediumFeaturesChanged(presContext);
|
||||
rulesChanged = rulesChanged || thisChanged;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return rulesChanged;
|
||||
#else
|
||||
MOZ_CRASH("old style system disabled");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -86,14 +86,14 @@ SERVO_BINDING_FUNC(Servo_StyleSet_RebuildCachedData, void,
|
||||
// We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
|
||||
// work as return values with the Linux 32-bit ABI at the moment because
|
||||
// they wrap the value in a struct.
|
||||
SERVO_BINDING_FUNC(Servo_StyleSet_MediumFeaturesChanged, uint8_t,
|
||||
RawServoStyleSetBorrowed set, bool* viewport_units_used,
|
||||
SERVO_BINDING_FUNC(Servo_StyleSet_MediumFeaturesChanged,
|
||||
MediumFeaturesChangedResult,
|
||||
RawServoStyleSetBorrowed document_set,
|
||||
const nsTArray<mozilla::ServoStyleSet*>* non_document_sets,
|
||||
bool may_affect_default_style)
|
||||
// We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
|
||||
// work as return values with the Linux 32-bit ABI at the moment because
|
||||
// they wrap the value in a struct.
|
||||
SERVO_BINDING_FUNC(Servo_StyleSet_SetDevice, uint8_t,
|
||||
RawServoStyleSetBorrowed set, RawGeckoPresContextOwned pres_context)
|
||||
SERVO_BINDING_FUNC(Servo_StyleSet_Drop, void, RawServoStyleSetOwned set)
|
||||
SERVO_BINDING_FUNC(Servo_StyleSet_CompatModeChanged, void,
|
||||
RawServoStyleSetBorrowed raw_data)
|
||||
|
@ -146,6 +146,12 @@ struct FontSizePrefs
|
||||
nscoord mDefaultFantasySize;
|
||||
};
|
||||
|
||||
struct MediumFeaturesChangedResult {
|
||||
bool mAffectsDocumentRules;
|
||||
bool mAffectsNonDocumentRules;
|
||||
bool mUsesViewportUnits;
|
||||
};
|
||||
|
||||
// DOM Traversal.
|
||||
void Gecko_RecordTraversalStatistics(uint32_t total, uint32_t parallel,
|
||||
uint32_t total_t, uint32_t parallel_t,
|
||||
|
@ -267,6 +267,7 @@ whitelist-types = [
|
||||
"Image",
|
||||
"ImageURL",
|
||||
"Keyframe",
|
||||
"MediumFeaturesChangedResult",
|
||||
"nsAttrName",
|
||||
"nsAttrValue",
|
||||
"nscolor",
|
||||
@ -468,6 +469,7 @@ structs-types = [
|
||||
"mozilla::AnonymousCounterStyle",
|
||||
"mozilla::AtomArray",
|
||||
"mozilla::MallocSizeOf",
|
||||
"mozilla::ServoStyleSet",
|
||||
"mozilla::OriginFlags",
|
||||
"mozilla::UniquePtr",
|
||||
"ServoRawOffsetArc",
|
||||
@ -475,6 +477,7 @@ structs-types = [
|
||||
"nsIDocument",
|
||||
"nsIDocument_DocumentTheme",
|
||||
"nsSimpleContentList",
|
||||
"MediumFeaturesChangedResult",
|
||||
"RawGeckoAnimationPropertySegment",
|
||||
"RawGeckoComputedTiming",
|
||||
"RawGeckoCSSPropertyIDList",
|
||||
|
@ -133,6 +133,10 @@ ServoStyleSet::CreateXBLServoStyleSet(
|
||||
set->ReplaceSheets(SheetType::Doc, aNewSheets);
|
||||
|
||||
// Update stylist immediately.
|
||||
//
|
||||
// NOTE(emilio): that this _needs_ to be the only call to UpdateStylist for
|
||||
// XBL bindings, otherwise the Servo-side Device may have stale pres context
|
||||
// pointers and such, which are not great.
|
||||
set->UpdateStylist();
|
||||
|
||||
// XBL resources are shared for a given URL, even across documents, so we
|
||||
@ -163,8 +167,6 @@ ServoStyleSet::Init(nsPresContext* aPresContext)
|
||||
mDocument = aPresContext->Document();
|
||||
MOZ_ASSERT(GetPresContext() == aPresContext);
|
||||
|
||||
mLastPresContextUsesXBLStyleSet = aPresContext;
|
||||
|
||||
mRawSet.reset(Servo_StyleSet_Init(aPresContext));
|
||||
|
||||
aPresContext->DeviceContext()->InitFontCache();
|
||||
@ -209,24 +211,6 @@ ServoStyleSet::InvalidateStyleForCSSRuleChanges()
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ServoStyleSet::SetPresContext(nsPresContext* aPresContext)
|
||||
{
|
||||
MOZ_ASSERT(IsForXBL(), "Only XBL styleset can set PresContext!");
|
||||
|
||||
mLastPresContextUsesXBLStyleSet = aPresContext;
|
||||
|
||||
const OriginFlags rulesChanged = static_cast<OriginFlags>(
|
||||
Servo_StyleSet_SetDevice(mRawSet.get(), aPresContext));
|
||||
|
||||
if (rulesChanged != OriginFlags(0)) {
|
||||
MarkOriginsDirty(rulesChanged);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ServoStyleSet::InvalidateStyleForDocumentStateChanges(EventStates aStatesChanged)
|
||||
{
|
||||
@ -264,33 +248,6 @@ ServoStyleSet::InvalidateStyleForDocumentStateChanges(EventStates aStatesChanged
|
||||
root, &styleSets, aStatesChanged.ServoValue());
|
||||
}
|
||||
|
||||
nsRestyleHint
|
||||
ServoStyleSet::MediumFeaturesChanged(MediaFeatureChangeReason aReason)
|
||||
{
|
||||
bool viewportUnitsUsed = false;
|
||||
bool rulesChanged = MediumFeaturesChangedRules(&viewportUnitsUsed, aReason);
|
||||
|
||||
if (nsPresContext* pc = GetPresContext()) {
|
||||
if (mDocument->BindingManager()->MediumFeaturesChanged(pc, aReason)) {
|
||||
// TODO(emilio): We could technically just restyle the bound elements.
|
||||
SetStylistXBLStyleSheetsDirty();
|
||||
rulesChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (rulesChanged) {
|
||||
return eRestyle_Subtree;
|
||||
}
|
||||
|
||||
const bool viewportChanged =
|
||||
bool(aReason & MediaFeatureChangeReason::ViewportChange);
|
||||
if (viewportUnitsUsed && viewportChanged) {
|
||||
return eRestyle_ForceDescendants;
|
||||
}
|
||||
|
||||
return nsRestyleHint(0);
|
||||
}
|
||||
|
||||
static const MediaFeatureChangeReason kMediaFeaturesAffectingDefaultStyle =
|
||||
// Zoom changes change the meaning of em units.
|
||||
MediaFeatureChangeReason::ZoomChange |
|
||||
@ -303,26 +260,51 @@ static const MediaFeatureChangeReason kMediaFeaturesAffectingDefaultStyle =
|
||||
// the pres context (bug 1418159).
|
||||
MediaFeatureChangeReason::ResolutionChange;
|
||||
|
||||
bool
|
||||
ServoStyleSet::MediumFeaturesChangedRules(
|
||||
bool* aViewportUnitsUsed,
|
||||
MediaFeatureChangeReason aReason)
|
||||
nsRestyleHint
|
||||
ServoStyleSet::MediumFeaturesChanged(MediaFeatureChangeReason aReason)
|
||||
{
|
||||
MOZ_ASSERT(aViewportUnitsUsed);
|
||||
AutoTArray<ServoStyleSet*, 20> nonDocumentStyleSets;
|
||||
// FIXME(emilio): When bug 1425759 is fixed we need to enumerate ShadowRoots
|
||||
// too.
|
||||
//
|
||||
// FIXME(emilio): This is broken for XBL. See bug 1406875.
|
||||
mDocument->BindingManager()->EnumerateBoundContentBindings(
|
||||
[&](nsXBLBinding* aBinding) {
|
||||
if (ServoStyleSet* set = aBinding->PrototypeBinding()->GetServoStyleSet()) {
|
||||
nonDocumentStyleSets.AppendElement(set);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
bool mayAffectDefaultStyle =
|
||||
bool(aReason & kMediaFeaturesAffectingDefaultStyle);
|
||||
|
||||
const OriginFlags rulesChanged = static_cast<OriginFlags>(
|
||||
const MediumFeaturesChangedResult result =
|
||||
Servo_StyleSet_MediumFeaturesChanged(
|
||||
mRawSet.get(), aViewportUnitsUsed, mayAffectDefaultStyle));
|
||||
mRawSet.get(), &nonDocumentStyleSets, mayAffectDefaultStyle);
|
||||
|
||||
if (rulesChanged != OriginFlags(0)) {
|
||||
MarkOriginsDirty(rulesChanged);
|
||||
return true;
|
||||
const bool rulesChanged =
|
||||
result.mAffectsDocumentRules || result.mAffectsNonDocumentRules;
|
||||
|
||||
if (result.mAffectsDocumentRules) {
|
||||
SetStylistStyleSheetsDirty();
|
||||
}
|
||||
|
||||
return false;
|
||||
if (result.mAffectsNonDocumentRules) {
|
||||
SetStylistXBLStyleSheetsDirty();
|
||||
}
|
||||
|
||||
if (rulesChanged) {
|
||||
return eRestyle_Subtree;
|
||||
}
|
||||
|
||||
const bool viewportChanged =
|
||||
bool(aReason & MediaFeatureChangeReason::ViewportChange);
|
||||
if (result.mUsesViewportUnits && viewportChanged) {
|
||||
return eRestyle_ForceDescendants;
|
||||
}
|
||||
|
||||
return nsRestyleHint(0);
|
||||
}
|
||||
|
||||
MOZ_DEFINE_MALLOC_SIZE_OF(ServoStyleSetMallocSizeOf)
|
||||
@ -1125,6 +1107,10 @@ ServoStyleSet::MarkOriginsDirty(OriginFlags aChangedOrigins)
|
||||
void
|
||||
ServoStyleSet::SetStylistStyleSheetsDirty()
|
||||
{
|
||||
// Note that there's another hidden mutator of mStylistState for XBL style
|
||||
// sets in MediumFeaturesChanged...
|
||||
//
|
||||
// We really need to stop using a full-blown StyleSet there...
|
||||
mStylistState |= StylistState::StyleSheetsDirty;
|
||||
|
||||
// We need to invalidate cached style in getComputedStyle for undisplayed
|
||||
@ -1468,6 +1454,9 @@ ServoStyleSet::UpdateStylist()
|
||||
if (MOZ_UNLIKELY(mStylistState & StylistState::XBLStyleSheetsDirty)) {
|
||||
MOZ_ASSERT(IsMaster(), "Only master styleset can mark XBL stylesets dirty!");
|
||||
MOZ_ASSERT(GetPresContext(), "How did they get dirty?");
|
||||
// NOTE(emilio): This right now rebuilds the stylist in the prototype
|
||||
// binding. That is fine, and if we wanted to be more incremental, which we
|
||||
// probably should, we need to move away from using a StyleSet for XBL.
|
||||
mDocument->BindingManager()->UpdateBoundContentBindingsForServo(GetPresContext());
|
||||
}
|
||||
|
||||
|
@ -160,9 +160,6 @@ public:
|
||||
return Servo_SourceSizeList_Evaluate(mRawSet.get(), aSourceSizeList);
|
||||
}
|
||||
|
||||
// aViewportChanged outputs whether any viewport units is used.
|
||||
bool MediumFeaturesChangedRules(bool* aViewportUnitsUsed, MediaFeatureChangeReason);
|
||||
|
||||
void InvalidateStyleForCSSRuleChanges();
|
||||
|
||||
void AddSizeOfIncludingThis(nsWindowSizes& aSizes) const;
|
||||
@ -448,15 +445,6 @@ public:
|
||||
// Returns the style rule map.
|
||||
ServoStyleRuleMap* StyleRuleMap();
|
||||
|
||||
// Return whether this is the last PresContext which uses this XBL styleset.
|
||||
bool IsPresContextChanged(nsPresContext* aPresContext) const {
|
||||
return aPresContext != mLastPresContextUsesXBLStyleSet;
|
||||
}
|
||||
|
||||
// Set PresContext (i.e. Device) for mRawSet. This should be called only
|
||||
// by XBL stylesets. Returns true if there is any rule changing.
|
||||
bool SetPresContext(nsPresContext* aPresContext);
|
||||
|
||||
/**
|
||||
* Returns true if a modification to an an attribute with the specified
|
||||
* local name might require us to restyle the element.
|
||||
@ -608,13 +596,6 @@ private:
|
||||
*/
|
||||
nsPresContext* GetPresContext();
|
||||
|
||||
// Because XBL style set could be used by multiple PresContext, we need to
|
||||
// store the last PresContext pointer which uses this XBL styleset for
|
||||
// computing medium rule changes.
|
||||
//
|
||||
// FIXME(emilio): This is a hack, and is broken. See bug 1406875.
|
||||
void* MOZ_NON_OWNING_REF mLastPresContextUsesXBLStyleSet = nullptr;
|
||||
|
||||
UniquePtr<RawServoStyleSet> mRawSet;
|
||||
EnumeratedArray<SheetType, SheetType::Count,
|
||||
nsTArray<RefPtr<ServoStyleSheet>>> mSheets;
|
||||
|
Loading…
Reference in New Issue
Block a user