diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 5b385c14c460..240559d1faeb 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -1673,7 +1673,6 @@ PresShell::Init(nsIDocument* aDocument, nsCOMPtr os = do_GetService("@mozilla.org/observer-service;1", &result); if (os) { - os->AddObserver(this, NS_LINK_VISITED_EVENT_TOPIC, PR_FALSE); os->AddObserver(this, "agent-sheet-added", PR_FALSE); os->AddObserver(this, "user-sheet-added", PR_FALSE); os->AddObserver(this, "agent-sheet-removed", PR_FALSE); @@ -1741,7 +1740,6 @@ PresShell::Destroy() nsCOMPtr os = do_GetService("@mozilla.org/observer-service;1"); if (os) { - os->RemoveObserver(this, NS_LINK_VISITED_EVENT_TOPIC); os->RemoveObserver(this, "agent-sheet-added"); os->RemoveObserver(this, "user-sheet-added"); os->RemoveObserver(this, "agent-sheet-removed"); @@ -7572,14 +7570,6 @@ PresShell::Observe(nsISupports* aSubject, } #endif - if (!nsCRT::strcmp(aTopic, NS_LINK_VISITED_EVENT_TOPIC)) { - nsCOMPtr uri = do_QueryInterface(aSubject); - if (uri && mDocument) { - mDocument->NotifyURIVisitednessChanged(uri); - } - return NS_OK; - } - if (!nsCRT::strcmp(aTopic, "agent-sheet-added") && mStyleSet) { AddAgentSheet(aSubject); return NS_OK; diff --git a/layout/style/nsCSSPseudoClassList.h b/layout/style/nsCSSPseudoClassList.h index 3c2da8e678a1..854d4520794d 100644 --- a/layout/style/nsCSSPseudoClassList.h +++ b/layout/style/nsCSSPseudoClassList.h @@ -48,7 +48,8 @@ * order. The first argument to CSS_PSEUDO_CLASS is the C++ * identifier of the atom. The second argument is the string value of * the atom. CSS_STATE_PSEUDO_CLASS also takes the name of the state - * bit that the class corresponds to. If CSS_STATE_PSEUDO_CLASS is + * bits that the class corresponds to. Only one of the bits needs to + * match for the pseudo-class to match. If CSS_STATE_PSEUDO_CLASS is * not defined, it'll be automatically defined to CSS_PSEUDO_CLASS. */ @@ -73,9 +74,11 @@ CSS_PSEUDO_CLASS(notPseudo, ":not") CSS_PSEUDO_CLASS(mozBoundElement, ":-moz-bound-element") CSS_PSEUDO_CLASS(root, ":root") -CSS_PSEUDO_CLASS(link, ":link") -CSS_PSEUDO_CLASS(mozAnyLink, ":-moz-any-link") // what matches :link or :visited -CSS_PSEUDO_CLASS(visited, ":visited") +CSS_STATE_PSEUDO_CLASS(link, ":link", NS_EVENT_STATE_UNVISITED) +// what matches :link or :visited +CSS_STATE_PSEUDO_CLASS(mozAnyLink, ":-moz-any-link", + NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED) +CSS_STATE_PSEUDO_CLASS(visited, ":visited", NS_EVENT_STATE_VISITED) CSS_STATE_PSEUDO_CLASS(active, ":active", NS_EVENT_STATE_ACTIVE) CSS_STATE_PSEUDO_CLASS(checked, ":checked", NS_EVENT_STATE_CHECKED) diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index 588b0578fca9..9b021bd75669 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -910,8 +910,7 @@ RuleProcessorData::RuleProcessorData(nsPresContext* aPresContext, mPreviousSiblingData(nsnull), mParentData(nsnull), mLanguage(nsnull), - mGotContentState(PR_FALSE), - mGotLinkInfo(PR_FALSE) + mGotContentState(PR_FALSE) { MOZ_COUNT_CTOR(RuleProcessorData); @@ -959,9 +958,6 @@ RuleProcessorData::RuleProcessorData(nsPresContext* aPresContext, mIsHTMLContent = (mNameSpaceID == kNameSpaceID_XHTML); mIsHTML = mIsHTMLContent && aContent->IsInHTMLDocument(); - // No need to initialize mIsLink or mLinkState; the IsLink() accessor will - // handle that. - // No need to initialize mContentState; the ContentState() accessor will handle // that. } @@ -1038,6 +1034,13 @@ RuleProcessorData::ContentState() } else { mContentState = mContent->IntrinsicState(); } + + // If we are not supposed to mark visited links as such, be sure to flip the + // bits appropriately. + if (!gSupportVisitedPseudo && (mContentState & NS_EVENT_STATE_VISITED)) { + mContentState = (mContentState & ~PRUint32(NS_EVENT_STATE_VISITED)) | + NS_EVENT_STATE_UNVISITED; + } } return mContentState; } @@ -1045,37 +1048,8 @@ RuleProcessorData::ContentState() PRBool RuleProcessorData::IsLink() { - if (!mGotLinkInfo) { - mGotLinkInfo = PR_TRUE; - mLinkState = eLinkState_Unknown; - mIsLink = PR_FALSE; - // if HTML content and it has some attributes, check for an HTML link - // NOTE: optimization: cannot be a link if no attributes (since it needs - // an href) - nsILinkHandler* linkHandler = - mPresContext ? mPresContext->GetLinkHandler() : nsnull; - if (mIsHTMLContent && mHasAttributes) { - // check if it is an HTML Link - if (nsStyleUtil::IsHTMLLink(mContent, linkHandler, &mLinkState)) { - mIsLink = PR_TRUE; - } - } - - // if not an HTML link, check for a simple xlink (cannot be both HTML - // link and xlink) NOTE: optimization: cannot be an XLink if no - // attributes (since it needs an href) - if(!mIsLink && - mHasAttributes && - !(mIsHTMLContent || mContent->IsXUL()) && - nsStyleUtil::IsLink(mContent, linkHandler, &mLinkState)) { - mIsLink = PR_TRUE; - } - - if (mLinkState == eLinkState_Visited && !gSupportVisitedPseudo) { - mLinkState = eLinkState_Unvisited; - } - } - return mIsLink; + PRUint32 state = ContentState(); + return (state & (NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)) != 0; } PRInt32 @@ -1637,31 +1611,6 @@ langMatches(RuleProcessorData& data, PRBool setNodeFlags, return PR_FALSE; } -static PRBool NS_FASTCALL -mozAnyLinkMatches(RuleProcessorData& data, PRBool setNodeFlags, - nsPseudoClassList* pseudoClass) -{ - NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::mozAnyLink, - "Unexpected atom"); - return data.IsLink(); -} - -static PRBool NS_FASTCALL -linkMatches(RuleProcessorData& data, PRBool setNodeFlags, - nsPseudoClassList* pseudoClass) -{ - NS_NOTREACHED("Shouldn't be called"); - return PR_FALSE; -} - -static PRBool NS_FASTCALL -visitedMatches(RuleProcessorData& data, PRBool setNodeFlags, - nsPseudoClassList* pseudoClass) -{ - NS_NOTREACHED("Shouldn't be called"); - return PR_FALSE; -} - static PRBool NS_FASTCALL mozIsHTMLMatches(RuleProcessorData& data, PRBool setNodeFlags, nsPseudoClassList* pseudoClass) @@ -1735,13 +1684,13 @@ notPseudoMatches(RuleProcessorData& data, PRBool setNodeFlags, typedef PRBool (NS_FASTCALL * PseudoClassMatcher)(RuleProcessorData&, PRBool setNodeFlags, nsPseudoClassList* pseudoClass); -// Only one of mFunc or mBit will be set; the other will be null or 0 +// Only one of mFunc or mBits will be set; the other will be null or 0 // respectively. We could use a union, but then we'd still need to // differentiate somehow, eiher with another member in the struct or // with a boolean coming from _sowewhere_. struct PseudoClassInfo { PseudoClassMatcher mFunc; - PRInt32 mBit; + PRInt32 mBits; }; static const PseudoClassInfo sPseudoClassInfo[] = { @@ -1865,33 +1814,15 @@ static PRBool SelectorMatches(RuleProcessorData &data, // test for pseudo class match for (nsPseudoClassList* pseudoClass = aSelector->mPseudoClassList; pseudoClass; pseudoClass = pseudoClass->mNext) { - // XXXbz special-case for :link and :visited, which are neither - // fish nor fowl - if (pseudoClass->mAtom == nsCSSPseudoClasses::link || - pseudoClass->mAtom == nsCSSPseudoClasses::visited) { - if (!data.IsLink()) { - return PR_FALSE; - } - - if (aStateMask & NS_EVENT_STATE_VISITED) { - if (aDependence) - *aDependence = PR_TRUE; - } else if ((eLinkState_Visited == data.LinkState()) == - (nsCSSPseudoClasses::link == pseudoClass->mAtom)) { - // Visited but :link or unvisited but :visited - return PR_FALSE; - } - continue; - } const PseudoClassInfo& info = sPseudoClassInfo[pseudoClass->mType]; if (info.mFunc) { if (!(*info.mFunc)(data, setNodeFlags, pseudoClass)) { return PR_FALSE; } } else { - PRInt32 stateToCheck = info.mBit; - NS_ABORT_IF_FALSE(stateToCheck != 0, "How did that happen?"); - if ((stateToCheck & (NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE)) && + PRInt32 statesToCheck = info.mBits; + NS_ABORT_IF_FALSE(statesToCheck != 0, "How did that happen?"); + if ((statesToCheck & (NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE)) && data.mCompatMode == eCompatibility_NavQuirks && // global selector (but don't check .class): !aSelector->HasTagSelector() && !aSelector->mIDList && @@ -1908,11 +1839,11 @@ static PRBool SelectorMatches(RuleProcessorData &data, // selectors ":hover" and ":active". return PR_FALSE; } else { - if (aStateMask & stateToCheck) { + if (aStateMask & statesToCheck) { if (aDependence) *aDependence = PR_TRUE; } else { - if (!(data.ContentState() & stateToCheck)) { + if (!(data.ContentState() & statesToCheck)) { return PR_FALSE; } } @@ -2324,28 +2255,6 @@ nsCSSRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData // Don't do our special handling of certain attributes if the attr // hasn't changed yet. if (aData->mAttrHasChanged) { - // Since we always have :-moz-any-link (and almost always have :link - // and :visited rules from prefs), rather than hacking AddRule below - // to add |href| to the hash, we'll just handle it here. - if (aData->mAttribute == nsGkAtoms::href && - aData->mIsHTMLContent && - (aData->mContentTag == nsGkAtoms::a || - aData->mContentTag == nsGkAtoms::area || - aData->mContentTag == nsGkAtoms::link)) { - data.change = nsReStyleHint(data.change | eReStyle_Self); - } - // XXX What about XLinks? -#ifdef MOZ_SVG - // XXX should really check the attribute namespace is XLink - if (aData->mAttribute == nsGkAtoms::href && - aData->mNameSpaceID == kNameSpaceID_SVG && - aData->mContentTag == nsGkAtoms::a) { - data.change = nsReStyleHint(data.change | eReStyle_Self); - } -#endif - // XXXbz now that :link and :visited are also states, do we need a - // similar optimization in HasStateDependentStyle? - // check for the localedir, lwtheme and lwthemetextcolor attribute on root XUL elements if ((aData->mAttribute == nsGkAtoms::localedir || aData->mAttribute == nsGkAtoms::lwtheme || @@ -2462,11 +2371,7 @@ PRBool IsStateSelector(nsCSSSelector& aSelector) if (pseudoClass->mType >= nsCSSPseudoClasses::ePseudoClass_Count) { continue; } - // XXXbz special-case for now for :link/:visited, since they're - // sorta-states-but-not-really right now. - if (sPseudoClassInfo[pseudoClass->mType].mBit || - pseudoClass->mAtom == nsCSSPseudoClasses::link || - pseudoClass->mAtom == nsCSSPseudoClasses::visited) { + if (sPseudoClassInfo[pseudoClass->mType].mBits) { return PR_TRUE; } } diff --git a/layout/style/nsHTMLStyleSheet.cpp b/layout/style/nsHTMLStyleSheet.cpp index f9063c16ea99..77490689a12e 100644 --- a/layout/style/nsHTMLStyleSheet.cpp +++ b/layout/style/nsHTMLStyleSheet.cpp @@ -238,23 +238,18 @@ nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData) // if we have anchor colors, check if this is an anchor with an href if (tag == nsGkAtoms::a) { if (mLinkRule || mVisitedRule || mActiveRule) { - if (aData->IsLink()) { - switch (aData->LinkState()) { - case eLinkState_Unvisited: - if (mLinkRule) - ruleWalker->Forward(mLinkRule); - break; - case eLinkState_Visited: - if (mVisitedRule) - ruleWalker->Forward(mVisitedRule); - break; - default: - break; - } + PRUint32 state = aData->ContentState(); + if (mLinkRule && (state & NS_EVENT_STATE_UNVISITED)) { + ruleWalker->Forward(mLinkRule); + } + else if (mVisitedRule && (state & NS_EVENT_STATE_VISITED)) { + ruleWalker->Forward(mVisitedRule); + } - // No need to add to the active rule if it's not a link - if (mActiveRule && (aData->ContentState() & NS_EVENT_STATE_ACTIVE)) - ruleWalker->Forward(mActiveRule); + // No need to add to the active rule if it's not a link + if (mActiveRule && aData->IsLink() && + (state & NS_EVENT_STATE_ACTIVE)) { + ruleWalker->Forward(mActiveRule); } } // end link/visited/active rules } // end A tag diff --git a/layout/style/nsRuleProcessorData.h b/layout/style/nsRuleProcessorData.h index 26e21b8c529b..25caa745f8c8 100644 --- a/layout/style/nsRuleProcessorData.h +++ b/layout/style/nsRuleProcessorData.h @@ -109,10 +109,6 @@ public: const nsString* GetLang(); PRUint32 ContentState(); PRBool IsLink(); - nsLinkState LinkState() { - NS_ASSERTION(mGotLinkInfo && mIsLink, "Why am I being called?"); - return mLinkState; - } // Returns a 1-based index of the child in its parent. If the child // is not in its parent's child list (i.e., it is anonymous content), @@ -157,11 +153,7 @@ private: // mContentState, mLinkState, mIsLink are initialized lazily. PRInt32 mContentState; // eventStateMgr->GetContentState() or // mContent->IntrinsicState() if we have no ESM - nsLinkState mLinkState; // if a link, this is the state, otherwise unknown - PRPackedBool mIsLink; // nsStyleUtil::IsHTMLLink or nsStyleUtil::IsLink PRPackedBool mGotContentState; - PRPackedBool mGotLinkInfo; // Whether we've gotten the right values - // for mLinkState and mIsLink. }; struct ElementRuleProcessorData : public RuleProcessorData {