mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-08 12:22:34 +00:00
Backed out changeset bca0b6ed92e4
This commit is contained in:
parent
35bd533654
commit
f968dfb0d2
@ -1676,6 +1676,7 @@ PresShell::Init(nsIDocument* aDocument,
|
||||
nsCOMPtr<nsIObserverService> 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);
|
||||
@ -1743,6 +1744,7 @@ PresShell::Destroy()
|
||||
nsCOMPtr<nsIObserverService> 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");
|
||||
@ -7585,6 +7587,14 @@ PresShell::Observe(nsISupports* aSubject,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!nsCRT::strcmp(aTopic, NS_LINK_VISITED_EVENT_TOPIC)) {
|
||||
nsCOMPtr<nsIURI> 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;
|
||||
|
@ -48,8 +48,7 @@
|
||||
* 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
|
||||
* 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
|
||||
* bit that the class corresponds to. If CSS_STATE_PSEUDO_CLASS is
|
||||
* not defined, it'll be automatically defined to CSS_PSEUDO_CLASS.
|
||||
*/
|
||||
|
||||
@ -74,11 +73,9 @@ CSS_PSEUDO_CLASS(notPseudo, ":not")
|
||||
CSS_PSEUDO_CLASS(mozBoundElement, ":-moz-bound-element")
|
||||
CSS_PSEUDO_CLASS(root, ":root")
|
||||
|
||||
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_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(active, ":active", NS_EVENT_STATE_ACTIVE)
|
||||
CSS_STATE_PSEUDO_CLASS(checked, ":checked", NS_EVENT_STATE_CHECKED)
|
||||
|
@ -910,7 +910,8 @@ RuleProcessorData::RuleProcessorData(nsPresContext* aPresContext,
|
||||
mPreviousSiblingData(nsnull),
|
||||
mParentData(nsnull),
|
||||
mLanguage(nsnull),
|
||||
mGotContentState(PR_FALSE)
|
||||
mGotContentState(PR_FALSE),
|
||||
mGotLinkInfo(PR_FALSE)
|
||||
{
|
||||
MOZ_COUNT_CTOR(RuleProcessorData);
|
||||
|
||||
@ -958,6 +959,9 @@ 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.
|
||||
}
|
||||
@ -1034,13 +1038,6 @@ 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;
|
||||
}
|
||||
@ -1048,8 +1045,37 @@ RuleProcessorData::ContentState()
|
||||
PRBool
|
||||
RuleProcessorData::IsLink()
|
||||
{
|
||||
PRUint32 state = ContentState();
|
||||
return (state & (NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)) != 0;
|
||||
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;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
@ -1611,6 +1637,31 @@ 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)
|
||||
@ -1684,13 +1735,13 @@ notPseudoMatches(RuleProcessorData& data, PRBool setNodeFlags,
|
||||
typedef PRBool
|
||||
(NS_FASTCALL * PseudoClassMatcher)(RuleProcessorData&, PRBool setNodeFlags,
|
||||
nsPseudoClassList* pseudoClass);
|
||||
// Only one of mFunc or mBits will be set; the other will be null or 0
|
||||
// Only one of mFunc or mBit 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 mBits;
|
||||
PRInt32 mBit;
|
||||
};
|
||||
|
||||
static const PseudoClassInfo sPseudoClassInfo[] = {
|
||||
@ -1814,15 +1865,33 @@ 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 statesToCheck = info.mBits;
|
||||
NS_ABORT_IF_FALSE(statesToCheck != 0, "How did that happen?");
|
||||
if ((statesToCheck & (NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE)) &&
|
||||
PRInt32 stateToCheck = info.mBit;
|
||||
NS_ABORT_IF_FALSE(stateToCheck != 0, "How did that happen?");
|
||||
if ((stateToCheck & (NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE)) &&
|
||||
data.mCompatMode == eCompatibility_NavQuirks &&
|
||||
// global selector (but don't check .class):
|
||||
!aSelector->HasTagSelector() && !aSelector->mIDList &&
|
||||
@ -1839,11 +1908,11 @@ static PRBool SelectorMatches(RuleProcessorData &data,
|
||||
// selectors ":hover" and ":active".
|
||||
return PR_FALSE;
|
||||
} else {
|
||||
if (aStateMask & statesToCheck) {
|
||||
if (aStateMask & stateToCheck) {
|
||||
if (aDependence)
|
||||
*aDependence = PR_TRUE;
|
||||
} else {
|
||||
if (!(data.ContentState() & statesToCheck)) {
|
||||
if (!(data.ContentState() & stateToCheck)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
@ -2255,6 +2324,28 @@ 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 ||
|
||||
@ -2371,7 +2462,11 @@ PRBool IsStateSelector(nsCSSSelector& aSelector)
|
||||
if (pseudoClass->mType >= nsCSSPseudoClasses::ePseudoClass_Count) {
|
||||
continue;
|
||||
}
|
||||
if (sPseudoClassInfo[pseudoClass->mType].mBits) {
|
||||
// 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) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -238,18 +238,23 @@ 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) {
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
// 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);
|
||||
}
|
||||
} // end link/visited/active rules
|
||||
} // end A tag
|
||||
|
@ -109,6 +109,10 @@ 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),
|
||||
@ -153,7 +157,11 @@ 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 {
|
||||
|
Loading…
Reference in New Issue
Block a user