mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Don't bother reresolving style when empty stylesheets get added (eg from empty
<style> elements). Also remove the methods for blowing away the ruletree during a style reresolve, since ruletrees are now garbage-collected. Bug 196557, r+sr=dbaron
This commit is contained in:
parent
e0c66a21b8
commit
0c5dc097d7
@ -66,6 +66,7 @@ public:
|
||||
NS_IMETHOD GetMediumCount(PRInt32& aCount) const = 0;
|
||||
NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const = 0;
|
||||
NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const = 0;
|
||||
NS_IMETHOD_(PRBool) HasRules() const = 0;
|
||||
|
||||
/**
|
||||
* Whether the sheet is applicable. A sheet that is not applicable
|
||||
|
@ -174,20 +174,6 @@ public:
|
||||
NS_IMETHOD Shutdown(nsIPresContext* aPresContext);
|
||||
NS_IMETHOD NotifyStyleContextDestroyed(nsIPresContext* aPresContext,
|
||||
nsStyleContext* aStyleContext);
|
||||
|
||||
// The following two methods can be used to tear down and reconstruct a rule tree. The idea
|
||||
// is to first call BeginRuleTreeReconstruct, which will set aside the old rule
|
||||
// tree. The entire frame tree should then have ReResolveStyleContext
|
||||
// called on it. With the old rule tree hidden from view, the newly resolved style contexts will
|
||||
// resolve to rule nodes in a fresh rule tree, and the re-resolve system will properly compute
|
||||
// the visual impact of the changes.
|
||||
//
|
||||
// After re-resolution, call EndRuleTreeReconstruct() to finally discard the old rule tree.
|
||||
// This trick can be used in lieu of a full frame reconstruction when drastic style changes
|
||||
// happen (e.g., stylesheets being added/removed in the DOM, theme switching in the Mozilla app,
|
||||
// etc.
|
||||
virtual nsresult BeginRuleTreeReconstruct();
|
||||
virtual nsresult EndRuleTreeReconstruct();
|
||||
|
||||
// For getting the cached default data in case we hit out-of-memory.
|
||||
// To be used only by nsRuleNode.
|
||||
@ -364,7 +350,6 @@ protected:
|
||||
|
||||
nsRuleNode* mRuleTree; // This is the root of our rule tree. It is a lexicographic tree of
|
||||
// matched rules that style contexts use to look up properties.
|
||||
nsRuleNode* mOldRuleTree; // Used during rule tree reconstruction.
|
||||
nsRuleWalker* mRuleWalker; // This is an instance of a rule walker that can be used
|
||||
// to navigate through our tree.
|
||||
|
||||
@ -387,7 +372,6 @@ StyleSetImpl::StyleSetImpl()
|
||||
: mFrameConstructor(nsnull),
|
||||
mQuirkStyleSheet(nsnull),
|
||||
mRuleTree(nsnull),
|
||||
mOldRuleTree(nsnull),
|
||||
mRuleWalker(nsnull),
|
||||
mInShutdown(PR_FALSE),
|
||||
mDestroyedCount(0)
|
||||
@ -1462,26 +1446,6 @@ StyleSetImpl::GetRuleTree(nsRuleNode** aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
StyleSetImpl::BeginRuleTreeReconstruct()
|
||||
{
|
||||
delete mRuleWalker;
|
||||
mRuleWalker = nsnull;
|
||||
mOldRuleTree = mRuleTree;
|
||||
mRuleTree = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
StyleSetImpl::EndRuleTreeReconstruct()
|
||||
{
|
||||
if (mOldRuleTree) {
|
||||
mOldRuleTree->Destroy();
|
||||
mOldRuleTree = nsnull;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCachedStyleData*
|
||||
StyleSetImpl::GetDefaultStyleData()
|
||||
{
|
||||
|
@ -816,6 +816,7 @@ public:
|
||||
NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const;
|
||||
NS_IMETHOD AppendMedium(nsIAtom* aMedium);
|
||||
NS_IMETHOD ClearMedia(void);
|
||||
NS_IMETHOD_(PRBool) HasRules() const;
|
||||
NS_IMETHOD DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex);
|
||||
NS_IMETHOD InsertRuleIntoGroup(const nsAString& aRule, nsICSSGroupRule* aGroup, PRUint32 aIndex, PRUint32* _retval);
|
||||
NS_IMETHOD ReplaceRuleInGroup(nsICSSGroupRule* aGroup, nsICSSRule* aOld, nsICSSRule* aNew);
|
||||
@ -1916,6 +1917,13 @@ CSSStyleSheetImpl::ClearMedia(void)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRBool)
|
||||
CSSStyleSheetImpl::HasRules() const
|
||||
{
|
||||
PRInt32 count;
|
||||
StyleRuleCount(count);
|
||||
return count != 0;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSStyleSheetImpl::GetApplicable(PRBool& aApplicable) const
|
||||
|
@ -354,6 +354,7 @@ public:
|
||||
NS_IMETHOD GetMediumCount(PRInt32& aCount) const;
|
||||
NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const;
|
||||
NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const;
|
||||
NS_IMETHOD_(PRBool) HasRules() const;
|
||||
|
||||
NS_IMETHOD GetApplicable(PRBool& aApplicable) const;
|
||||
|
||||
@ -590,6 +591,13 @@ HTMLCSSStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const
|
||||
return PR_TRUE; // works for all media
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRBool)
|
||||
HTMLCSSStyleSheetImpl::HasRules() const
|
||||
{
|
||||
return PR_TRUE; // We always have rules, since mFirstLineRule and
|
||||
// mFirstLetterRule are created on request.
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLCSSStyleSheetImpl::GetApplicable(PRBool& aApplicable) const
|
||||
{
|
||||
|
@ -518,6 +518,7 @@ public:
|
||||
NS_IMETHOD GetMediumCount(PRInt32& aCount) const;
|
||||
NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const;
|
||||
NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const;
|
||||
NS_IMETHOD_(PRBool) HasRules() const;
|
||||
|
||||
NS_IMETHOD GetApplicable(PRBool& aApplicable) const;
|
||||
|
||||
@ -947,6 +948,11 @@ HTMLStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const
|
||||
return PR_TRUE; // works for all media
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRBool)
|
||||
HTMLStyleSheetImpl::HasRules() const
|
||||
{
|
||||
return PR_TRUE; // We have rules at all reasonable times
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLStyleSheetImpl::GetApplicable(PRBool& aApplicable) const
|
||||
|
@ -169,7 +169,7 @@ public:
|
||||
* all style data for a given pres shell without necessarily reconstructing
|
||||
* all of the frames.
|
||||
*/
|
||||
NS_IMETHOD ReconstructStyleData(PRBool aRebuildRuleTree) = 0;
|
||||
NS_IMETHOD ReconstructStyleData() = 0;
|
||||
|
||||
/** Setup all style rules required to implement preferences
|
||||
* - used for background/text/link colors and link underlining
|
||||
|
@ -1720,7 +1720,7 @@ nsPresContext::ThemeChanged()
|
||||
if (!mShell)
|
||||
return NS_OK;
|
||||
|
||||
return mShell->ReconstructStyleData(PR_FALSE);
|
||||
return mShell->ReconstructStyleData();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1047,7 +1047,7 @@ public:
|
||||
NS_IMETHOD GetActiveAlternateStyleSheet(nsString& aSheetTitle);
|
||||
NS_IMETHOD SelectAlternateStyleSheet(const nsString& aSheetTitle);
|
||||
NS_IMETHOD ListAlternateStyleSheets(nsStringArray& aTitleList);
|
||||
NS_IMETHOD ReconstructStyleData(PRBool aRebuildRuleTree);
|
||||
NS_IMETHOD ReconstructStyleData();
|
||||
NS_IMETHOD SetPreferenceStyleRules(PRBool aForceReflow);
|
||||
NS_IMETHOD EnablePrefStyleRules(PRBool aEnable, PRUint8 aPrefType=0xFF);
|
||||
NS_IMETHOD ArePrefStyleRulesEnabled(PRBool& aEnabled);
|
||||
@ -2017,11 +2017,8 @@ PresShell::SelectAlternateStyleSheet(const nsString& aSheetTitle)
|
||||
}
|
||||
}
|
||||
}
|
||||
// We don't need to rebuild the
|
||||
// rule tree, since no rule nodes have been rendered invalid by the
|
||||
// addition of new rule content. They can simply lurk in the tree
|
||||
// until the stylesheet is enabled once more.
|
||||
return ReconstructStyleData(PR_FALSE);
|
||||
|
||||
return ReconstructStyleData();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -5418,106 +5415,8 @@ PresShell::ReconstructFrames(void)
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* It's better to add stuff to the |DidSetStyleContext| method of the
|
||||
* relevant frames than adding it here. These methods should (ideally,
|
||||
* anyway) go away.
|
||||
*/
|
||||
|
||||
// Return value says whether to walk children.
|
||||
typedef PRBool (* PR_CALLBACK frameWalkerFn)(nsIFrame *aFrame, void *aClosure);
|
||||
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
BuildFramechangeList(nsIFrame *aFrame, void *aClosure)
|
||||
{
|
||||
nsStyleChangeList *changeList = NS_STATIC_CAST(nsStyleChangeList*, aClosure);
|
||||
|
||||
// Ok, get our binding information.
|
||||
if (!aFrame->GetStyleDisplay()->mBinding.IsEmpty()) {
|
||||
// We had a binding.
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
content->GetDocument(getter_AddRefs(doc));
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIBindingManager> bm;
|
||||
doc->GetBindingManager(getter_AddRefs(bm));
|
||||
nsCOMPtr<nsIXBLBinding> binding;
|
||||
bm->GetBinding(content, getter_AddRefs(binding));
|
||||
PRBool marked = PR_FALSE;
|
||||
binding->MarkedForDeath(&marked);
|
||||
if (marked) {
|
||||
// Add in a change to process, thus ensuring this binding gets rebuilt.
|
||||
changeList->AppendChange(aFrame, content, NS_STYLE_HINT_FRAMECHANGE);
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
ReResolveMenusAndTrees(nsIFrame *aFrame, void *aClosure)
|
||||
{
|
||||
// Trees have a special style cache that needs to be flushed when
|
||||
// the theme changes.
|
||||
nsCOMPtr<nsITreeBoxObject> treeBox(do_QueryInterface(aFrame));
|
||||
if (treeBox)
|
||||
treeBox->ClearStyleAndImageCaches();
|
||||
|
||||
// We deliberately don't re-resolve style on a menu's popup
|
||||
// sub-content, since doing so slows menus to a crawl. That means we
|
||||
// have to special-case them on a skin switch, and ensure that the
|
||||
// popup frames just get destroyed completely.
|
||||
nsCOMPtr<nsIMenuFrame> menuFrame(do_QueryInterface(aFrame));
|
||||
if (menuFrame) {
|
||||
menuFrame->UngenerateMenu();
|
||||
menuFrame->OpenMenu(PR_FALSE);
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
WalkFramesThroughPlaceholders(nsIPresContext *aPresContext, nsIFrame *aFrame,
|
||||
frameWalkerFn aFunc, void *aClosure)
|
||||
{
|
||||
PRBool walkChildren = (*aFunc)(aFrame, aClosure);
|
||||
if (!walkChildren)
|
||||
return;
|
||||
|
||||
PRInt32 listIndex = 0;
|
||||
nsCOMPtr<nsIAtom> childList;
|
||||
|
||||
do {
|
||||
nsIFrame *child = nsnull;
|
||||
aFrame->FirstChild(aPresContext, childList, &child);
|
||||
while (child) {
|
||||
if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
|
||||
// only do frames that are in flow
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
child->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::placeholderFrame == frameType) { // placeholder
|
||||
// get out of flow frame and recur there
|
||||
nsIFrame* outOfFlowFrame =
|
||||
NS_STATIC_CAST(nsPlaceholderFrame*, child)->GetOutOfFlowFrame();
|
||||
NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
|
||||
WalkFramesThroughPlaceholders(aPresContext, outOfFlowFrame,
|
||||
aFunc, aClosure);
|
||||
}
|
||||
else
|
||||
WalkFramesThroughPlaceholders(aPresContext, child, aFunc, aClosure);
|
||||
}
|
||||
child = child->GetNextSibling();
|
||||
}
|
||||
|
||||
aFrame->GetAdditionalChildListName(listIndex++, getter_AddRefs(childList));
|
||||
} while (childList);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::ReconstructStyleData(PRBool aRebuildRuleTree)
|
||||
PresShell::ReconstructStyleData()
|
||||
{
|
||||
nsIFrame* rootFrame;
|
||||
GetRootFrame(&rootFrame);
|
||||
@ -5540,18 +5439,6 @@ PresShell::ReconstructStyleData(PRBool aRebuildRuleTree)
|
||||
// Now handle some of our more problematic widgets (and also deal with
|
||||
// skin XBL changing).
|
||||
nsStyleChangeList changeList;
|
||||
if (aRebuildRuleTree) {
|
||||
// Handle those widgets that have special style contexts cached
|
||||
// that will point to invalid rule nodes following a rule tree
|
||||
// reconstruction.
|
||||
WalkFramesThroughPlaceholders(mPresContext, rootFrame,
|
||||
&BuildFramechangeList, &changeList);
|
||||
cssFrameConstructor->ProcessRestyledFrames(changeList, mPresContext);
|
||||
changeList.Clear();
|
||||
|
||||
// Now do a complete re-resolve of our style tree.
|
||||
set->BeginRuleTreeReconstruct();
|
||||
}
|
||||
|
||||
nsChangeHint frameChange = NS_STYLE_HINT_NONE;
|
||||
frameManager->ComputeStyleChangeFor(rootFrame, kNameSpaceID_Unknown, nsnull,
|
||||
@ -5562,18 +5449,8 @@ PresShell::ReconstructStyleData(PRBool aRebuildRuleTree)
|
||||
set->ReconstructDocElementHierarchy(mPresContext);
|
||||
else {
|
||||
cssFrameConstructor->ProcessRestyledFrames(changeList, mPresContext);
|
||||
#ifdef MOZ_XUL
|
||||
if (aRebuildRuleTree) {
|
||||
GetRootFrame(&rootFrame);
|
||||
WalkFramesThroughPlaceholders(mPresContext, rootFrame,
|
||||
&ReResolveMenusAndTrees, nsnull);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (aRebuildRuleTree)
|
||||
set->EndRuleTreeReconstruct();
|
||||
|
||||
VERIFY_STYLE_TREE;
|
||||
|
||||
return NS_OK;
|
||||
@ -5587,14 +5464,12 @@ PresShell::StyleSheetAdded(nsIDocument *aDocument,
|
||||
NS_PRECONDITION(aStyleSheet, "Must have a style sheet!");
|
||||
PRBool applicable;
|
||||
aStyleSheet->GetApplicable(applicable);
|
||||
if (applicable) {
|
||||
// If style information is being added, we don't need to rebuild the
|
||||
// rule tree, since no rule nodes have been rendered invalid by the
|
||||
// addition of new rule content.
|
||||
return ReconstructStyleData(PR_FALSE);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
if (!applicable || !aStyleSheet->HasRules()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return ReconstructStyleData();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -5605,13 +5480,11 @@ PresShell::StyleSheetRemoved(nsIDocument *aDocument,
|
||||
NS_PRECONDITION(aStyleSheet, "Must have a style sheet!");
|
||||
PRBool applicable;
|
||||
aStyleSheet->GetApplicable(applicable);
|
||||
if (applicable) {
|
||||
// XXXdwh We'd like to be able to use ReconstructStyleData in all the
|
||||
// other style sheet calls, but it doesn't quite work because of HTML tables.
|
||||
return ReconstructStyleData(PR_TRUE);
|
||||
if (!applicable || !aStyleSheet->HasRules()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
return ReconstructStyleData();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -5626,11 +5499,11 @@ PresShell::StyleSheetApplicableStateChanged(nsIDocument *aDocument,
|
||||
return rv;
|
||||
}
|
||||
|
||||
// We don't need to rebuild the
|
||||
// rule tree, since no rule nodes have been rendered invalid by the
|
||||
// addition of new rule content. They can simply lurk in the tree
|
||||
// until the stylesheet is enabled once more.
|
||||
return ReconstructStyleData(PR_FALSE);
|
||||
if (!aStyleSheet->HasRules()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return ReconstructStyleData();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -5639,7 +5512,7 @@ PresShell::StyleRuleChanged(nsIDocument *aDocument,
|
||||
nsIStyleRule* aOldStyleRule,
|
||||
nsIStyleRule* aNewStyleRule)
|
||||
{
|
||||
return ReconstructStyleData(PR_FALSE);
|
||||
return ReconstructStyleData();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -5647,7 +5520,7 @@ PresShell::StyleRuleAdded(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aStyleRule)
|
||||
{
|
||||
return ReconstructStyleData(PR_FALSE);
|
||||
return ReconstructStyleData();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -5655,7 +5528,7 @@ PresShell::StyleRuleRemoved(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aStyleRule)
|
||||
{
|
||||
return ReconstructStyleData(PR_FALSE);
|
||||
return ReconstructStyleData();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -169,7 +169,7 @@ public:
|
||||
* all style data for a given pres shell without necessarily reconstructing
|
||||
* all of the frames.
|
||||
*/
|
||||
NS_IMETHOD ReconstructStyleData(PRBool aRebuildRuleTree) = 0;
|
||||
NS_IMETHOD ReconstructStyleData() = 0;
|
||||
|
||||
/** Setup all style rules required to implement preferences
|
||||
* - used for background/text/link colors and link underlining
|
||||
|
@ -111,20 +111,6 @@ public:
|
||||
|
||||
virtual nsresult GetRuleTree(nsRuleNode** aResult) = 0;
|
||||
|
||||
// The following two methods can be used to tear down and reconstruct a rule tree. The idea
|
||||
// is to first call BeginRuleTreeReconstruct, which will set aside the old rule
|
||||
// tree. The entire frame tree should then have ReResolveStyleContext
|
||||
// called on it. With the old rule tree hidden from view, the newly resolved style contexts will
|
||||
// resolve to rule nodes in a fresh rule tree, and the re-resolve system will properly compute
|
||||
// the visual impact of the changes.
|
||||
//
|
||||
// After re-resolution, call EndRuleTreeReconstruct() to finally discard the old rule tree.
|
||||
// This trick can be used in lieu of a full frame reconstruction when drastic style changes
|
||||
// happen (e.g., stylesheets being added/removed in the DOM, theme switching in the Mozilla app,
|
||||
// etc.
|
||||
virtual nsresult BeginRuleTreeReconstruct()=0;
|
||||
virtual nsresult EndRuleTreeReconstruct()=0;
|
||||
|
||||
// For getting the cached default data in case we hit out-of-memory.
|
||||
// To be used only by nsRuleNode.
|
||||
virtual nsCachedStyleData* GetDefaultStyleData() = 0;
|
||||
|
@ -1720,7 +1720,7 @@ nsPresContext::ThemeChanged()
|
||||
if (!mShell)
|
||||
return NS_OK;
|
||||
|
||||
return mShell->ReconstructStyleData(PR_FALSE);
|
||||
return mShell->ReconstructStyleData();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1047,7 +1047,7 @@ public:
|
||||
NS_IMETHOD GetActiveAlternateStyleSheet(nsString& aSheetTitle);
|
||||
NS_IMETHOD SelectAlternateStyleSheet(const nsString& aSheetTitle);
|
||||
NS_IMETHOD ListAlternateStyleSheets(nsStringArray& aTitleList);
|
||||
NS_IMETHOD ReconstructStyleData(PRBool aRebuildRuleTree);
|
||||
NS_IMETHOD ReconstructStyleData();
|
||||
NS_IMETHOD SetPreferenceStyleRules(PRBool aForceReflow);
|
||||
NS_IMETHOD EnablePrefStyleRules(PRBool aEnable, PRUint8 aPrefType=0xFF);
|
||||
NS_IMETHOD ArePrefStyleRulesEnabled(PRBool& aEnabled);
|
||||
@ -2017,11 +2017,8 @@ PresShell::SelectAlternateStyleSheet(const nsString& aSheetTitle)
|
||||
}
|
||||
}
|
||||
}
|
||||
// We don't need to rebuild the
|
||||
// rule tree, since no rule nodes have been rendered invalid by the
|
||||
// addition of new rule content. They can simply lurk in the tree
|
||||
// until the stylesheet is enabled once more.
|
||||
return ReconstructStyleData(PR_FALSE);
|
||||
|
||||
return ReconstructStyleData();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -5418,106 +5415,8 @@ PresShell::ReconstructFrames(void)
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* It's better to add stuff to the |DidSetStyleContext| method of the
|
||||
* relevant frames than adding it here. These methods should (ideally,
|
||||
* anyway) go away.
|
||||
*/
|
||||
|
||||
// Return value says whether to walk children.
|
||||
typedef PRBool (* PR_CALLBACK frameWalkerFn)(nsIFrame *aFrame, void *aClosure);
|
||||
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
BuildFramechangeList(nsIFrame *aFrame, void *aClosure)
|
||||
{
|
||||
nsStyleChangeList *changeList = NS_STATIC_CAST(nsStyleChangeList*, aClosure);
|
||||
|
||||
// Ok, get our binding information.
|
||||
if (!aFrame->GetStyleDisplay()->mBinding.IsEmpty()) {
|
||||
// We had a binding.
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
content->GetDocument(getter_AddRefs(doc));
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIBindingManager> bm;
|
||||
doc->GetBindingManager(getter_AddRefs(bm));
|
||||
nsCOMPtr<nsIXBLBinding> binding;
|
||||
bm->GetBinding(content, getter_AddRefs(binding));
|
||||
PRBool marked = PR_FALSE;
|
||||
binding->MarkedForDeath(&marked);
|
||||
if (marked) {
|
||||
// Add in a change to process, thus ensuring this binding gets rebuilt.
|
||||
changeList->AppendChange(aFrame, content, NS_STYLE_HINT_FRAMECHANGE);
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
ReResolveMenusAndTrees(nsIFrame *aFrame, void *aClosure)
|
||||
{
|
||||
// Trees have a special style cache that needs to be flushed when
|
||||
// the theme changes.
|
||||
nsCOMPtr<nsITreeBoxObject> treeBox(do_QueryInterface(aFrame));
|
||||
if (treeBox)
|
||||
treeBox->ClearStyleAndImageCaches();
|
||||
|
||||
// We deliberately don't re-resolve style on a menu's popup
|
||||
// sub-content, since doing so slows menus to a crawl. That means we
|
||||
// have to special-case them on a skin switch, and ensure that the
|
||||
// popup frames just get destroyed completely.
|
||||
nsCOMPtr<nsIMenuFrame> menuFrame(do_QueryInterface(aFrame));
|
||||
if (menuFrame) {
|
||||
menuFrame->UngenerateMenu();
|
||||
menuFrame->OpenMenu(PR_FALSE);
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
WalkFramesThroughPlaceholders(nsIPresContext *aPresContext, nsIFrame *aFrame,
|
||||
frameWalkerFn aFunc, void *aClosure)
|
||||
{
|
||||
PRBool walkChildren = (*aFunc)(aFrame, aClosure);
|
||||
if (!walkChildren)
|
||||
return;
|
||||
|
||||
PRInt32 listIndex = 0;
|
||||
nsCOMPtr<nsIAtom> childList;
|
||||
|
||||
do {
|
||||
nsIFrame *child = nsnull;
|
||||
aFrame->FirstChild(aPresContext, childList, &child);
|
||||
while (child) {
|
||||
if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
|
||||
// only do frames that are in flow
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
child->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::placeholderFrame == frameType) { // placeholder
|
||||
// get out of flow frame and recur there
|
||||
nsIFrame* outOfFlowFrame =
|
||||
NS_STATIC_CAST(nsPlaceholderFrame*, child)->GetOutOfFlowFrame();
|
||||
NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
|
||||
WalkFramesThroughPlaceholders(aPresContext, outOfFlowFrame,
|
||||
aFunc, aClosure);
|
||||
}
|
||||
else
|
||||
WalkFramesThroughPlaceholders(aPresContext, child, aFunc, aClosure);
|
||||
}
|
||||
child = child->GetNextSibling();
|
||||
}
|
||||
|
||||
aFrame->GetAdditionalChildListName(listIndex++, getter_AddRefs(childList));
|
||||
} while (childList);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::ReconstructStyleData(PRBool aRebuildRuleTree)
|
||||
PresShell::ReconstructStyleData()
|
||||
{
|
||||
nsIFrame* rootFrame;
|
||||
GetRootFrame(&rootFrame);
|
||||
@ -5540,18 +5439,6 @@ PresShell::ReconstructStyleData(PRBool aRebuildRuleTree)
|
||||
// Now handle some of our more problematic widgets (and also deal with
|
||||
// skin XBL changing).
|
||||
nsStyleChangeList changeList;
|
||||
if (aRebuildRuleTree) {
|
||||
// Handle those widgets that have special style contexts cached
|
||||
// that will point to invalid rule nodes following a rule tree
|
||||
// reconstruction.
|
||||
WalkFramesThroughPlaceholders(mPresContext, rootFrame,
|
||||
&BuildFramechangeList, &changeList);
|
||||
cssFrameConstructor->ProcessRestyledFrames(changeList, mPresContext);
|
||||
changeList.Clear();
|
||||
|
||||
// Now do a complete re-resolve of our style tree.
|
||||
set->BeginRuleTreeReconstruct();
|
||||
}
|
||||
|
||||
nsChangeHint frameChange = NS_STYLE_HINT_NONE;
|
||||
frameManager->ComputeStyleChangeFor(rootFrame, kNameSpaceID_Unknown, nsnull,
|
||||
@ -5562,18 +5449,8 @@ PresShell::ReconstructStyleData(PRBool aRebuildRuleTree)
|
||||
set->ReconstructDocElementHierarchy(mPresContext);
|
||||
else {
|
||||
cssFrameConstructor->ProcessRestyledFrames(changeList, mPresContext);
|
||||
#ifdef MOZ_XUL
|
||||
if (aRebuildRuleTree) {
|
||||
GetRootFrame(&rootFrame);
|
||||
WalkFramesThroughPlaceholders(mPresContext, rootFrame,
|
||||
&ReResolveMenusAndTrees, nsnull);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (aRebuildRuleTree)
|
||||
set->EndRuleTreeReconstruct();
|
||||
|
||||
VERIFY_STYLE_TREE;
|
||||
|
||||
return NS_OK;
|
||||
@ -5587,14 +5464,12 @@ PresShell::StyleSheetAdded(nsIDocument *aDocument,
|
||||
NS_PRECONDITION(aStyleSheet, "Must have a style sheet!");
|
||||
PRBool applicable;
|
||||
aStyleSheet->GetApplicable(applicable);
|
||||
if (applicable) {
|
||||
// If style information is being added, we don't need to rebuild the
|
||||
// rule tree, since no rule nodes have been rendered invalid by the
|
||||
// addition of new rule content.
|
||||
return ReconstructStyleData(PR_FALSE);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
if (!applicable || !aStyleSheet->HasRules()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return ReconstructStyleData();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -5605,13 +5480,11 @@ PresShell::StyleSheetRemoved(nsIDocument *aDocument,
|
||||
NS_PRECONDITION(aStyleSheet, "Must have a style sheet!");
|
||||
PRBool applicable;
|
||||
aStyleSheet->GetApplicable(applicable);
|
||||
if (applicable) {
|
||||
// XXXdwh We'd like to be able to use ReconstructStyleData in all the
|
||||
// other style sheet calls, but it doesn't quite work because of HTML tables.
|
||||
return ReconstructStyleData(PR_TRUE);
|
||||
if (!applicable || !aStyleSheet->HasRules()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
return ReconstructStyleData();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -5626,11 +5499,11 @@ PresShell::StyleSheetApplicableStateChanged(nsIDocument *aDocument,
|
||||
return rv;
|
||||
}
|
||||
|
||||
// We don't need to rebuild the
|
||||
// rule tree, since no rule nodes have been rendered invalid by the
|
||||
// addition of new rule content. They can simply lurk in the tree
|
||||
// until the stylesheet is enabled once more.
|
||||
return ReconstructStyleData(PR_FALSE);
|
||||
if (!aStyleSheet->HasRules()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return ReconstructStyleData();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -5639,7 +5512,7 @@ PresShell::StyleRuleChanged(nsIDocument *aDocument,
|
||||
nsIStyleRule* aOldStyleRule,
|
||||
nsIStyleRule* aNewStyleRule)
|
||||
{
|
||||
return ReconstructStyleData(PR_FALSE);
|
||||
return ReconstructStyleData();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -5647,7 +5520,7 @@ PresShell::StyleRuleAdded(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aStyleRule)
|
||||
{
|
||||
return ReconstructStyleData(PR_FALSE);
|
||||
return ReconstructStyleData();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -5655,7 +5528,7 @@ PresShell::StyleRuleRemoved(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aStyleRule)
|
||||
{
|
||||
return ReconstructStyleData(PR_FALSE);
|
||||
return ReconstructStyleData();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -816,6 +816,7 @@ public:
|
||||
NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const;
|
||||
NS_IMETHOD AppendMedium(nsIAtom* aMedium);
|
||||
NS_IMETHOD ClearMedia(void);
|
||||
NS_IMETHOD_(PRBool) HasRules() const;
|
||||
NS_IMETHOD DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex);
|
||||
NS_IMETHOD InsertRuleIntoGroup(const nsAString& aRule, nsICSSGroupRule* aGroup, PRUint32 aIndex, PRUint32* _retval);
|
||||
NS_IMETHOD ReplaceRuleInGroup(nsICSSGroupRule* aGroup, nsICSSRule* aOld, nsICSSRule* aNew);
|
||||
@ -1916,6 +1917,13 @@ CSSStyleSheetImpl::ClearMedia(void)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRBool)
|
||||
CSSStyleSheetImpl::HasRules() const
|
||||
{
|
||||
PRInt32 count;
|
||||
StyleRuleCount(count);
|
||||
return count != 0;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CSSStyleSheetImpl::GetApplicable(PRBool& aApplicable) const
|
||||
|
@ -354,6 +354,7 @@ public:
|
||||
NS_IMETHOD GetMediumCount(PRInt32& aCount) const;
|
||||
NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const;
|
||||
NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const;
|
||||
NS_IMETHOD_(PRBool) HasRules() const;
|
||||
|
||||
NS_IMETHOD GetApplicable(PRBool& aApplicable) const;
|
||||
|
||||
@ -590,6 +591,13 @@ HTMLCSSStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const
|
||||
return PR_TRUE; // works for all media
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRBool)
|
||||
HTMLCSSStyleSheetImpl::HasRules() const
|
||||
{
|
||||
return PR_TRUE; // We always have rules, since mFirstLineRule and
|
||||
// mFirstLetterRule are created on request.
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLCSSStyleSheetImpl::GetApplicable(PRBool& aApplicable) const
|
||||
{
|
||||
|
@ -518,6 +518,7 @@ public:
|
||||
NS_IMETHOD GetMediumCount(PRInt32& aCount) const;
|
||||
NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const;
|
||||
NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const;
|
||||
NS_IMETHOD_(PRBool) HasRules() const;
|
||||
|
||||
NS_IMETHOD GetApplicable(PRBool& aApplicable) const;
|
||||
|
||||
@ -947,6 +948,11 @@ HTMLStyleSheetImpl::UseForMedium(nsIAtom* aMedium) const
|
||||
return PR_TRUE; // works for all media
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRBool)
|
||||
HTMLStyleSheetImpl::HasRules() const
|
||||
{
|
||||
return PR_TRUE; // We have rules at all reasonable times
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLStyleSheetImpl::GetApplicable(PRBool& aApplicable) const
|
||||
|
@ -66,6 +66,7 @@ public:
|
||||
NS_IMETHOD GetMediumCount(PRInt32& aCount) const = 0;
|
||||
NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const = 0;
|
||||
NS_IMETHOD_(PRBool) UseForMedium(nsIAtom* aMedium) const = 0;
|
||||
NS_IMETHOD_(PRBool) HasRules() const = 0;
|
||||
|
||||
/**
|
||||
* Whether the sheet is applicable. A sheet that is not applicable
|
||||
|
@ -174,20 +174,6 @@ public:
|
||||
NS_IMETHOD Shutdown(nsIPresContext* aPresContext);
|
||||
NS_IMETHOD NotifyStyleContextDestroyed(nsIPresContext* aPresContext,
|
||||
nsStyleContext* aStyleContext);
|
||||
|
||||
// The following two methods can be used to tear down and reconstruct a rule tree. The idea
|
||||
// is to first call BeginRuleTreeReconstruct, which will set aside the old rule
|
||||
// tree. The entire frame tree should then have ReResolveStyleContext
|
||||
// called on it. With the old rule tree hidden from view, the newly resolved style contexts will
|
||||
// resolve to rule nodes in a fresh rule tree, and the re-resolve system will properly compute
|
||||
// the visual impact of the changes.
|
||||
//
|
||||
// After re-resolution, call EndRuleTreeReconstruct() to finally discard the old rule tree.
|
||||
// This trick can be used in lieu of a full frame reconstruction when drastic style changes
|
||||
// happen (e.g., stylesheets being added/removed in the DOM, theme switching in the Mozilla app,
|
||||
// etc.
|
||||
virtual nsresult BeginRuleTreeReconstruct();
|
||||
virtual nsresult EndRuleTreeReconstruct();
|
||||
|
||||
// For getting the cached default data in case we hit out-of-memory.
|
||||
// To be used only by nsRuleNode.
|
||||
@ -364,7 +350,6 @@ protected:
|
||||
|
||||
nsRuleNode* mRuleTree; // This is the root of our rule tree. It is a lexicographic tree of
|
||||
// matched rules that style contexts use to look up properties.
|
||||
nsRuleNode* mOldRuleTree; // Used during rule tree reconstruction.
|
||||
nsRuleWalker* mRuleWalker; // This is an instance of a rule walker that can be used
|
||||
// to navigate through our tree.
|
||||
|
||||
@ -387,7 +372,6 @@ StyleSetImpl::StyleSetImpl()
|
||||
: mFrameConstructor(nsnull),
|
||||
mQuirkStyleSheet(nsnull),
|
||||
mRuleTree(nsnull),
|
||||
mOldRuleTree(nsnull),
|
||||
mRuleWalker(nsnull),
|
||||
mInShutdown(PR_FALSE),
|
||||
mDestroyedCount(0)
|
||||
@ -1462,26 +1446,6 @@ StyleSetImpl::GetRuleTree(nsRuleNode** aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
StyleSetImpl::BeginRuleTreeReconstruct()
|
||||
{
|
||||
delete mRuleWalker;
|
||||
mRuleWalker = nsnull;
|
||||
mOldRuleTree = mRuleTree;
|
||||
mRuleTree = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
StyleSetImpl::EndRuleTreeReconstruct()
|
||||
{
|
||||
if (mOldRuleTree) {
|
||||
mOldRuleTree->Destroy();
|
||||
mOldRuleTree = nsnull;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCachedStyleData*
|
||||
StyleSetImpl::GetDefaultStyleData()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user