diff --git a/content/xbl/src/nsBindingManager.cpp b/content/xbl/src/nsBindingManager.cpp index c383f61f7d8..e4d1bf2e569 100644 --- a/content/xbl/src/nsBindingManager.cpp +++ b/content/xbl/src/nsBindingManager.cpp @@ -77,6 +77,7 @@ #include "nsDOMCID.h" #include "nsIDOMScriptObjectFactory.h" #include "nsIScriptGlobalObject.h" +#include "nsTHashtable.h" #include "nsIScriptContext.h" #include "nsBindingManager.h" @@ -1234,8 +1235,7 @@ nsBindingManager::GetBindingImplementation(nsIContent* aContent, REFNSIID aIID, } nsresult -nsBindingManager::WalkRules(nsStyleSet* aStyleSet, - nsIStyleRuleProcessor::EnumFunc aFunc, +nsBindingManager::WalkRules(nsIStyleRuleProcessor::EnumFunc aFunc, RuleProcessorData* aData, PRBool* aCutOffInheritance) { @@ -1280,6 +1280,63 @@ nsBindingManager::WalkRules(nsStyleSet* aStyleSet, return NS_OK; } +typedef nsTHashtable RuleProcessorSet; + +PR_STATIC_CALLBACK(PLDHashOperator) +EnumRuleProcessors(nsISupports *aKey, nsXBLBinding *aBinding, void* aClosure) +{ + RuleProcessorSet *set = static_cast(aClosure); + for (nsXBLBinding *binding = aBinding; binding; + binding = binding->GetBaseBinding()) { + nsIStyleRuleProcessor *ruleProc = + binding->PrototypeBinding()->GetRuleProcessor(); + if (ruleProc) { + if (!set->IsInitialized() && !set->Init(16)) + return PL_DHASH_STOP; + set->PutEntry(ruleProc); + } + } + return PL_DHASH_NEXT; +} + +struct MediumFeaturesChangedData { + nsPresContext *mPresContext; + PRBool *mRulesChanged; +}; + +PR_STATIC_CALLBACK(PLDHashOperator) +EnumMediumFeaturesChanged(nsVoidPtrHashKey *aKey, void* aClosure) +{ + nsIStyleRuleProcessor *ruleProcessor = + static_cast(const_cast(aKey->GetKey())); + MediumFeaturesChangedData *data = + static_cast(aClosure); + + PRBool thisChanged = PR_FALSE; + ruleProcessor->MediumFeaturesChanged(data->mPresContext, &thisChanged); + *data->mRulesChanged = *data->mRulesChanged || thisChanged; + + return PL_DHASH_NEXT; +} + +nsresult +nsBindingManager::MediumFeaturesChanged(nsPresContext* aPresContext, + PRBool* aRulesChanged) +{ + *aRulesChanged = PR_FALSE; + if (!mBindingTable.IsInitialized()) + return NS_OK; + + RuleProcessorSet set; + mBindingTable.EnumerateRead(EnumRuleProcessors, &set); + if (!set.IsInitialized()) + return NS_OK; + + MediumFeaturesChangedData data = { aPresContext, aRulesChanged }; + set.EnumerateEntries(EnumMediumFeaturesChanged, &data); + return NS_OK; +} + PRBool nsBindingManager::ShouldBuildChildFrames(nsIContent* aContent) { diff --git a/content/xbl/src/nsBindingManager.h b/content/xbl/src/nsBindingManager.h index 8651f0e42f3..6009b7e8961 100755 --- a/content/xbl/src/nsBindingManager.h +++ b/content/xbl/src/nsBindingManager.h @@ -184,10 +184,16 @@ public: PRBool ShouldBuildChildFrames(nsIContent* aContent); // Style rule methods - nsresult WalkRules(nsStyleSet* aStyleSet, - nsIStyleRuleProcessor::EnumFunc aFunc, + nsresult WalkRules(nsIStyleRuleProcessor::EnumFunc aFunc, RuleProcessorData* aData, PRBool* aCutOffInheritance); + /** + * 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). + */ + nsresult MediumFeaturesChanged(nsPresContext* aPresContext, + PRBool* aRulesChanged); NS_HIDDEN_(void) Traverse(nsIContent *aContent, nsCycleCollectionTraversalCallback &cb); diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index adb2ef6de2b..84708fc89b7 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -533,8 +533,7 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc, PRBool cutOffInheritance = PR_FALSE; if (mBindingManager) { // We can supply additional document-level sheets that should be walked. - mBindingManager->WalkRules(this, aCollectorFunc, aData, - &cutOffInheritance); + mBindingManager->WalkRules(aCollectorFunc, aData, &cutOffInheritance); } if (!skipUserStyles && !cutOffInheritance && mRuleProcessors[eDocSheet]) // NOTE: different @@ -594,7 +593,7 @@ nsStyleSet::WalkRuleProcessors(nsIStyleRuleProcessor::EnumFunc aFunc, PRBool cutOffInheritance = PR_FALSE; if (mBindingManager) { // We can supply additional document-level sheets that should be walked. - mBindingManager->WalkRules(this, aFunc, aData, &cutOffInheritance); + mBindingManager->WalkRules(aFunc, aData, &cutOffInheritance); } if (!skipUserStyles && !cutOffInheritance && mRuleProcessors[eDocSheet]) // NOTE: different @@ -968,7 +967,6 @@ 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]; @@ -980,5 +978,11 @@ nsStyleSet::MediumFeaturesChanged(nsPresContext* aPresContext) stylesChanged = stylesChanged || thisChanged; } + if (mBindingManager) { + PRBool thisChanged = PR_FALSE; + mBindingManager->MediumFeaturesChanged(aPresContext, &thisChanged); + stylesChanged = stylesChanged || thisChanged; + } + return stylesChanged; } diff --git a/layout/style/test/Makefile.in b/layout/style/test/Makefile.in index e073fb864e6..2f905e0256f 100644 --- a/layout/style/test/Makefile.in +++ b/layout/style/test/Makefile.in @@ -104,6 +104,7 @@ _TEST_FILES = test_acid3_test46.html \ test_initial_computation.html \ test_initial_storage.html \ test_media_queries.html \ + test_media_queries_dynamic_xbl.html \ test_of_type_selectors.xhtml \ test_parse_rule.html \ test_property_database.html \ @@ -131,6 +132,9 @@ _TEST_FILES = test_acid3_test46.html \ xbl_bindings.xml \ empty.html \ media_queries_iframe.html \ + media_queries_dynamic_xbl_binding.xml \ + media_queries_dynamic_xbl_iframe.html \ + media_queries_dynamic_xbl_style.css \ $(NULL) diff --git a/layout/style/test/media_queries_dynamic_xbl_binding.xml b/layout/style/test/media_queries_dynamic_xbl_binding.xml new file mode 100644 index 00000000000..4b851553909 --- /dev/null +++ b/layout/style/test/media_queries_dynamic_xbl_binding.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/layout/style/test/media_queries_dynamic_xbl_iframe.html b/layout/style/test/media_queries_dynamic_xbl_iframe.html new file mode 100644 index 00000000000..50e8008fa2b --- /dev/null +++ b/layout/style/test/media_queries_dynamic_xbl_iframe.html @@ -0,0 +1,5 @@ + + +

Hello

diff --git a/layout/style/test/media_queries_dynamic_xbl_style.css b/layout/style/test/media_queries_dynamic_xbl_style.css new file mode 100644 index 00000000000..5c99c07ee6f --- /dev/null +++ b/layout/style/test/media_queries_dynamic_xbl_style.css @@ -0,0 +1,6 @@ +@media (orientation: portrait) { + div { color: purple; } +} +@media (orientation: landscape) { + div { color: blue; } +} diff --git a/layout/style/test/test_media_queries_dynamic_xbl.html b/layout/style/test/test_media_queries_dynamic_xbl.html new file mode 100644 index 00000000000..7ab8a6d6670 --- /dev/null +++ b/layout/style/test/test_media_queries_dynamic_xbl.html @@ -0,0 +1,41 @@ + + + + + Test for Bug 156716 + + + + + +Mozilla Bug 156716 + +
+
+
+ + +