зеркало из https://github.com/mozilla/gecko-dev.git
Implement media queries, part 3: infrastructure for dynamic change handling at the rule processor and style set level. (Bug 156716) r+sr=bzbarsky
This commit is contained in:
Родитель
907424839d
Коммит
8cd01e114a
|
@ -731,8 +731,9 @@ RuleCascadeData::AttributeListFor(nsIAtom* aAttribute)
|
|||
//
|
||||
|
||||
nsCSSRuleProcessor::nsCSSRuleProcessor(const nsCOMArray<nsICSSStyleSheet>& aSheets)
|
||||
: mSheets(aSheets),
|
||||
mRuleCascades(nsnull)
|
||||
: mSheets(aSheets)
|
||||
, mRuleCascades(nsnull)
|
||||
, mLastPresContext(nsnull)
|
||||
{
|
||||
for (PRInt32 i = mSheets.Count() - 1; i >= 0; --i)
|
||||
mSheets[i]->AddRuleProcessor(this);
|
||||
|
@ -2085,6 +2086,16 @@ nsCSSRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCSSRuleProcessor::MediumFeaturesChanged(nsPresContext* aPresContext,
|
||||
PRBool* aRulesChanged)
|
||||
{
|
||||
RuleCascadeData *old = mRuleCascades;
|
||||
RefreshRuleCascade(aPresContext);
|
||||
*aRulesChanged = (old != mRuleCascades);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCSSRuleProcessor::ClearRuleCascades()
|
||||
{
|
||||
|
@ -2346,6 +2357,24 @@ FillWeightArray(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
|||
|
||||
RuleCascadeData*
|
||||
nsCSSRuleProcessor::GetRuleCascade(nsPresContext* aPresContext)
|
||||
{
|
||||
// If anything changes about the presentation context, we will be
|
||||
// notified. Otherwise, our cache is valid if mLastPresContext
|
||||
// matches aPresContext. (The only rule processors used for multiple
|
||||
// pres contexts are for XBL. These rule processors are probably less
|
||||
// likely to have @media rules, and thus the cache is pretty likely to
|
||||
// hit instantly even when we're switching between pres contexts.)
|
||||
|
||||
if (!mRuleCascades || aPresContext != mLastPresContext) {
|
||||
RefreshRuleCascade(aPresContext);
|
||||
}
|
||||
mLastPresContext = aPresContext;
|
||||
|
||||
return mRuleCascades;
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSRuleProcessor::RefreshRuleCascade(nsPresContext* aPresContext)
|
||||
{
|
||||
// Having RuleCascadeData objects be per-medium (over all variation
|
||||
// caused by media queries, handled through mCacheKey) works for now
|
||||
|
@ -2353,12 +2382,16 @@ nsCSSRuleProcessor::GetRuleCascade(nsPresContext* aPresContext)
|
|||
// set of stylesheets they can vary based on medium (@media) or
|
||||
// document (@-moz-document).)
|
||||
|
||||
RuleCascadeData **cascadep = &mRuleCascades;
|
||||
RuleCascadeData *cascade;
|
||||
while ((cascade = *cascadep)) {
|
||||
if (cascade->mCacheKey.Matches(aPresContext))
|
||||
return cascade;
|
||||
cascadep = &cascade->mNext;
|
||||
for (RuleCascadeData **cascadep = &mRuleCascades, *cascade;
|
||||
(cascade = *cascadep); cascadep = &cascade->mNext) {
|
||||
if (cascade->mCacheKey.Matches(aPresContext)) {
|
||||
// Ensure that the current one is always mRuleCascades.
|
||||
*cascadep = cascade->mNext;
|
||||
cascade->mNext = mRuleCascades;
|
||||
mRuleCascades = cascade;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mSheets.Count() != 0) {
|
||||
|
@ -2369,9 +2402,9 @@ nsCSSRuleProcessor::GetRuleCascade(nsPresContext* aPresContext)
|
|||
CascadeEnumData data(aPresContext, newCascade->mCacheKey,
|
||||
newCascade->mRuleHash.Arena());
|
||||
if (!data.mRulesByWeight.ops)
|
||||
return nsnull;
|
||||
return; /* out of memory */
|
||||
if (!mSheets.EnumerateForwards(CascadeSheetRulesInto, &data))
|
||||
return nsnull;
|
||||
return; /* out of memory */
|
||||
|
||||
// Sort the hash table of per-weight linked lists by weight.
|
||||
PRUint32 weightCount = data.mRulesByWeight.entryCount;
|
||||
|
@ -2393,16 +2426,17 @@ nsCSSRuleProcessor::GetRuleCascade(nsPresContext* aPresContext)
|
|||
// Calling |AddRule| reuses mNext!
|
||||
RuleValue *next = ruleValue->mNext;
|
||||
if (!AddRule(ruleValue, newCascade))
|
||||
return nsnull;
|
||||
return; /* out of memory */
|
||||
ruleValue = next;
|
||||
} while (ruleValue);
|
||||
}
|
||||
|
||||
*cascadep = newCascade;
|
||||
cascade = newCascade.forget();
|
||||
// Ensure that the current one is always mRuleCascades.
|
||||
newCascade->mNext = mRuleCascades;
|
||||
mRuleCascades = newCascade.forget();
|
||||
}
|
||||
}
|
||||
return cascade;
|
||||
return;
|
||||
}
|
||||
|
||||
/* static */ PRBool
|
||||
|
|
|
@ -93,13 +93,21 @@ public:
|
|||
NS_IMETHOD HasAttributeDependentStyle(AttributeRuleProcessorData* aData,
|
||||
nsReStyleHint* aResult);
|
||||
|
||||
NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext,
|
||||
PRBool* aRulesChanged);
|
||||
|
||||
protected:
|
||||
RuleCascadeData* GetRuleCascade(nsPresContext* aPresContext);
|
||||
void RefreshRuleCascade(nsPresContext* aPresContext);
|
||||
|
||||
// The sheet order here is the same as in nsStyleSet::mSheets
|
||||
nsCOMArray<nsICSSStyleSheet> mSheets;
|
||||
|
||||
// active first, then cached (most recent first)
|
||||
RuleCascadeData* mRuleCascades;
|
||||
|
||||
// The last pres context for which GetRuleCascades was called.
|
||||
nsPresContext *mLastPresContext;
|
||||
};
|
||||
|
||||
#endif /* nsCSSRuleProcessor_h_ */
|
||||
|
|
|
@ -366,6 +366,8 @@ public:
|
|||
|
||||
NS_IMETHOD HasAttributeDependentStyle(AttributeRuleProcessorData* aData,
|
||||
nsReStyleHint* aResult);
|
||||
NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext,
|
||||
PRBool* aResult);
|
||||
|
||||
#ifdef DEBUG
|
||||
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
||||
|
@ -492,6 +494,13 @@ HTMLCSSStyleSheetImpl::HasAttributeDependentStyle(AttributeRuleProcessorData* aD
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLCSSStyleSheetImpl::MediumFeaturesChanged(nsPresContext* aPresContext,
|
||||
PRBool* aRulesChanged)
|
||||
{
|
||||
*aRulesChanged = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -562,6 +562,14 @@ nsHTMLStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLStyleSheet::MediumFeaturesChanged(nsPresContext* aPresContext,
|
||||
PRBool* aRulesChanged)
|
||||
{
|
||||
*aRulesChanged = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLStyleSheet::RulesMatching(PseudoRuleProcessorData* aData)
|
||||
|
|
|
@ -83,6 +83,8 @@ public:
|
|||
nsReStyleHint* aResult);
|
||||
NS_IMETHOD HasAttributeDependentStyle(AttributeRuleProcessorData* aData,
|
||||
nsReStyleHint* aResult);
|
||||
NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext,
|
||||
PRBool* aRulesChanged);
|
||||
|
||||
nsresult Init(nsIURI* aURL, nsIDocument* aDocument);
|
||||
nsresult Reset(nsIURI* aURL);
|
||||
|
|
|
@ -273,6 +273,14 @@ public:
|
|||
*/
|
||||
NS_IMETHOD HasAttributeDependentStyle(AttributeRuleProcessorData* aData,
|
||||
nsReStyleHint* aResult) = 0;
|
||||
|
||||
/**
|
||||
* 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).
|
||||
*/
|
||||
NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext,
|
||||
PRBool* aRulesChanged) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIStyleRuleProcessor,
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* Contributor(s):
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -962,3 +963,22 @@ nsStyleSet::HasAttributeDependentStyle(nsPresContext* aPresContext,
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsStyleSet::MediumFeaturesChanged(nsPresContext* aPresContext)
|
||||
{
|
||||
// We can't use WalkRuleProcessors without a content node.
|
||||
// XXX We don't notify mBindingManager. Should we?
|
||||
PRBool stylesChanged = PR_FALSE;
|
||||
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(mRuleProcessors); ++i) {
|
||||
nsIStyleRuleProcessor *processor = mRuleProcessors[i];
|
||||
if (!processor) {
|
||||
continue;
|
||||
}
|
||||
PRBool thisChanged = PR_FALSE;
|
||||
processor->MediumFeaturesChanged(aPresContext, &thisChanged);
|
||||
stylesChanged = stylesChanged || thisChanged;
|
||||
}
|
||||
|
||||
return stylesChanged;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* Contributor(s):
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -143,6 +144,13 @@ class nsStyleSet
|
|||
PRInt32 aModType,
|
||||
PRUint32 aStateMask);
|
||||
|
||||
/*
|
||||
* Do any processing that needs to happen as a result of a change in
|
||||
* the characteristics of the medium, and return whether style rules
|
||||
* may have changed as a result.
|
||||
*/
|
||||
PRBool MediumFeaturesChanged(nsPresContext* aPresContext);
|
||||
|
||||
// APIs for registering objects that can supply additional
|
||||
// rules during processing.
|
||||
void SetBindingManager(nsBindingManager* aBindingManager)
|
||||
|
|
Загрузка…
Ссылка в новой задаче