Modified: trunk/Source/WebCore/css/CSSStyleSelector.cpp (93121 => 93122)
--- trunk/Source/WebCore/css/CSSStyleSelector.cpp 2011-08-16 16:59:04 UTC (rev 93121)
+++ trunk/Source/WebCore/css/CSSStyleSelector.cpp 2011-08-16 17:15:06 UTC (rev 93122)
@@ -68,6 +68,7 @@
#include "HTMLNames.h"
#include "HTMLProgressElement.h"
#include "HTMLTextAreaElement.h"
+#include "InspectorInstrumentation.h"
#include "KeyframeList.h"
#include "LinkHash.h"
#include "LocaleToScriptMapping.h"
@@ -894,8 +895,6 @@
m_ruleList = 0;
m_fontDirty = false;
-
- m_forcePseudoClassMask = DoNotForcePseudoClassMask;
}
static inline const AtomicString* linkAttribute(Node* node)
@@ -2031,12 +2030,12 @@
}
}
-PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, unsigned rulesToInclude, unsigned forcePseudoClassMask)
+PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, unsigned rulesToInclude)
{
- return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude, forcePseudoClassMask);
+ return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude);
}
-PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, unsigned rulesToInclude, unsigned forcePseudoClassMask)
+PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, unsigned rulesToInclude)
{
if (!e || !e->document()->haveStylesheetsLoaded())
return 0;
@@ -2045,7 +2044,6 @@
initElement(e);
initForStyleResolve(e, 0, pseudoId);
- m_forcePseudoClassMask = forcePseudoClassMask;
if (rulesToInclude & UAAndUserCSSRules) {
int firstUARule = -1, lastUARule = -1;
@@ -2070,7 +2068,6 @@
}
m_checker.m_collectRulesOnly = false;
- m_forcePseudoClassMask = DoNotForcePseudoClassMask;
return m_ruleList.release();
}
@@ -2093,7 +2090,7 @@
}
// Slow path.
- SelectorMatch match = m_checker.checkSelector(ruleData.selector(), m_element, m_dynamicPseudo, false, false, m_forcePseudoClassMask, style(), m_parentNode ? m_parentNode->renderStyle() : 0);
+ SelectorMatch match = m_checker.checkSelector(ruleData.selector(), m_element, m_dynamicPseudo, false, false, style(), m_parentNode ? m_parentNode->renderStyle() : 0);
if (match != SelectorMatches)
return false;
if (m_checker.m_pseudoStyle != NOPSEUDO && m_checker.m_pseudoStyle != m_dynamicPseudo)
@@ -2222,7 +2219,7 @@
// * SelectorMatches - the selector matches the element e
// * SelectorFailsLocally - the selector fails for the element e
// * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e
-CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* e, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, unsigned forcePseudoClassMask, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
+CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* e, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
{
#if ENABLE(SVG)
// Spec: CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree
@@ -2232,7 +2229,7 @@
#endif
// first selector has to match
- if (!checkOneSelector(sel, e, dynamicPseudo, isSubSelector, encounteredLink, forcePseudoClassMask, elementStyle, elementParentStyle))
+ if (!checkOneSelector(sel, e, dynamicPseudo, isSubSelector, encounteredLink, elementStyle, elementParentStyle))
return SelectorFailsLocally;
// The rest of the selectors has to match
@@ -2266,7 +2263,7 @@
if (!n || !n->isElementNode())
return SelectorFailsCompletely;
e = static_cast<Element*>(n);
- SelectorMatch match = checkSelector(sel, e, dynamicPseudo, false, encounteredLink, forcePseudoClassMask);
+ SelectorMatch match = checkSelector(sel, e, dynamicPseudo, false, encounteredLink);
if (match != SelectorFailsLocally)
return match;
}
@@ -2277,7 +2274,7 @@
if (!n || !n->isElementNode())
return SelectorFailsCompletely;
e = static_cast<Element*>(n);
- return checkSelector(sel, e, dynamicPseudo, false, encounteredLink, forcePseudoClassMask);
+ return checkSelector(sel, e, dynamicPseudo, false, encounteredLink);
}
case CSSSelector::DirectAdjacent:
{
@@ -2293,7 +2290,7 @@
return SelectorFailsLocally;
e = static_cast<Element*>(n);
m_matchVisitedPseudoClass = false;
- return checkSelector(sel, e, dynamicPseudo, false, encounteredLink, forcePseudoClassMask);
+ return checkSelector(sel, e, dynamicPseudo, false, encounteredLink);
}
case CSSSelector::IndirectAdjacent:
if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
@@ -2309,7 +2306,7 @@
return SelectorFailsLocally;
e = static_cast<Element*>(n);
m_matchVisitedPseudoClass = false;
- SelectorMatch match = checkSelector(sel, e, dynamicPseudo, false, encounteredLink, forcePseudoClassMask);
+ SelectorMatch match = checkSelector(sel, e, dynamicPseudo, false, encounteredLink);
if (match != SelectorFailsLocally)
return match;
};
@@ -2321,14 +2318,14 @@
if ((elementStyle || m_collectRulesOnly) && dynamicPseudo != NOPSEUDO && dynamicPseudo != SELECTION &&
!((RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER) && sel->m_match == CSSSelector::PseudoClass))
return SelectorFailsCompletely;
- return checkSelector(sel, e, dynamicPseudo, true, encounteredLink, forcePseudoClassMask, elementStyle, elementParentStyle);
+ return checkSelector(sel, e, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle);
case CSSSelector::ShadowDescendant:
{
Node* shadowHostNode = e->shadowAncestorNode();
if (shadowHostNode == e || !shadowHostNode->isElementNode())
return SelectorFailsCompletely;
e = static_cast<Element*>(shadowHostNode);
- return checkSelector(sel, e, dynamicPseudo, false, encounteredLink, forcePseudoClassMask);
+ return checkSelector(sel, e, dynamicPseudo, false, encounteredLink);
}
}
@@ -2487,7 +2484,7 @@
return false;
}
-bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, unsigned forcePseudoClassMask, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
+bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
{
ASSERT(e);
if (!e)
@@ -2529,7 +2526,7 @@
// the parser enforces that this never occurs
ASSERT(subSel->pseudoType() != CSSSelector::PseudoNot);
- if (!checkOneSelector(subSel, e, dynamicPseudo, true, encounteredLink, forcePseudoClassMask, elementStyle, elementParentStyle))
+ if (!checkOneSelector(subSel, e, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle))
return true;
}
} else if (dynamicPseudo != NOPSEUDO && (RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER)) {
@@ -2541,28 +2538,8 @@
return !m_document->page()->focusController()->isActive();
}
- CSSSelector::PseudoType pseudoType = sel->pseudoType();
-
- // Check forced pseudo class mask first.
- if (forcePseudoClassMask != DoNotForcePseudoClassMask) {
- switch (pseudoType) {
- case CSSSelector::PseudoLink:
- return forcePseudoClassMask & ForceLink;
- case CSSSelector::PseudoVisited:
- return forcePseudoClassMask & ForceVisited;
- case CSSSelector::PseudoFocus:
- return forcePseudoClassMask & ForceFocus;
- case CSSSelector::PseudoHover:
- return forcePseudoClassMask & ForceHover;
- case CSSSelector::PseudoActive:
- return forcePseudoClassMask & ForceActive;
- default:
- break;
- }
- }
-
// Normal element pseudo class checking.
- switch (pseudoType) {
+ switch (sel->pseudoType()) {
// Pseudo classes:
case CSSSelector::PseudoNot:
break; // Already handled up above.
@@ -2858,7 +2835,7 @@
break;
case CSSSelector::PseudoAny:
for (CSSSelector* selector = sel->selectorList()->first(); selector; selector = CSSSelectorList::next(selector)) {
- if (checkSelector(selector, e, dynamicPseudo, true, encounteredLink, forcePseudoClassMask, elementStyle, elementParentStyle) == SelectorMatches)
+ if (checkSelector(selector, e, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle) == SelectorMatches)
return true;
}
break;
@@ -2879,7 +2856,7 @@
break;
case CSSSelector::PseudoVisited:
if (e && e->isLink())
- return m_matchVisitedPseudoClass;
+ return m_matchVisitedPseudoClass || InspectorInstrumentation::forcePseudoState(e, CSSSelector::PseudoVisited);
break;
case CSSSelector::PseudoDrag: {
if (elementStyle)
@@ -2891,7 +2868,7 @@
break;
}
case CSSSelector::PseudoFocus:
- if (e && e->focused() && e->document()->frame() && e->document()->frame()->selection()->isFocusedAndActive())
+ if (e && ((e->focused() && e->document()->frame() && e->document()->frame()->selection()->isFocusedAndActive()) || InspectorInstrumentation::forcePseudoState(e, CSSSelector::PseudoFocus)))
return true;
break;
case CSSSelector::PseudoHover: {
@@ -2902,7 +2879,7 @@
elementStyle->setAffectedByHoverRules(true);
else if (e->renderStyle())
e->renderStyle()->setAffectedByHoverRules(true);
- if (e->hovered())
+ if (e->hovered() || InspectorInstrumentation::forcePseudoState(e, CSSSelector::PseudoHover))
return true;
}
break;
@@ -2915,7 +2892,7 @@
elementStyle->setAffectedByActiveRules(true);
else if (e->renderStyle())
e->renderStyle()->setAffectedByActiveRules(true);
- if (e->active())
+ if (e->active() || InspectorInstrumentation::forcePseudoState(e, CSSSelector::PseudoActive))
return true;
}
break;
Modified: trunk/Source/WebCore/css/CSSStyleSelector.h (93121 => 93122)
--- trunk/Source/WebCore/css/CSSStyleSelector.h 2011-08-16 16:59:04 UTC (rev 93121)
+++ trunk/Source/WebCore/css/CSSStyleSelector.h 2011-08-16 17:15:06 UTC (rev 93122)
@@ -134,16 +134,6 @@
PassRefPtr<RenderStyle> styleForKeyframe(const RenderStyle*, const WebKitCSSKeyframeRule*, KeyframeValue&);
public:
- enum ForcePseudoClassFlags {
- ForceNone = 0,
- DoNotForcePseudoClassMask = 1 << 0,
- ForceHover = 1 << 1,
- ForceFocus = 1 << 2,
- ForceActive = 1 << 3,
- ForceLink = 1 << 4,
- ForceVisited = 1 << 5
- };
-
// These methods will give back the set of rules that matched for a given element (or a pseudo-element).
enum CSSRuleFilter {
UAAndUserCSSRules = 1 << 1,
@@ -153,8 +143,8 @@
AllButEmptyCSSRules = UAAndUserCSSRules | AuthorCSSRules | CrossOriginCSSRules,
AllCSSRules = AllButEmptyCSSRules | EmptyCSSRules,
};
- PassRefPtr<CSSRuleList> styleRulesForElement(Element*, unsigned rulesToInclude = AllButEmptyCSSRules, unsigned forcePseudoClassMask = DoNotForcePseudoClassMask);
- PassRefPtr<CSSRuleList> pseudoStyleRulesForElement(Element*, PseudoId, unsigned rulesToInclude = AllButEmptyCSSRules, unsigned forcePseudoClassMask = DoNotForcePseudoClassMask);
+ PassRefPtr<CSSRuleList> styleRulesForElement(Element*, unsigned rulesToInclude = AllButEmptyCSSRules);
+ PassRefPtr<CSSRuleList> pseudoStyleRulesForElement(Element*, PseudoId, unsigned rulesToInclude = AllButEmptyCSSRules);
// Given a CSS keyword in the range (xx-small to -webkit-xxx-large), this function will return
// the correct font size scaled relative to the user's default (medium).
@@ -285,8 +275,8 @@
SelectorChecker(Document*, bool strictParsing);
bool checkSelector(CSSSelector*, Element*) const;
- SelectorMatch checkSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, unsigned forcePseudoClassMask = DoNotForcePseudoClassMask, RenderStyle* = 0, RenderStyle* elementParentStyle = 0) const;
- bool checkOneSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, unsigned forcePseudoClassMask, RenderStyle*, RenderStyle* elementParentStyle) const;
+ SelectorMatch checkSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* = 0, RenderStyle* elementParentStyle = 0) const;
+ bool checkOneSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle*, RenderStyle* elementParentStyle) const;
bool checkScrollbarPseudoClass(CSSSelector*, PseudoId& dynamicPseudo) const;
static bool fastCheckSelector(const CSSSelector*, const Element*);
@@ -383,7 +373,6 @@
CSSValue* m_lineHeightValue;
bool m_fontDirty;
bool m_matchAuthorAndUserStyles;
- unsigned m_forcePseudoClassMask; // enum ForcePseudoClassFlags
RefPtr<CSSFontSelector> m_fontSelector;
Vector<CSSMutableStyleDeclaration*> m_additionalAttributeStyleDecls;
Modified: trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp (93121 => 93122)
--- trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp 2011-08-16 16:59:04 UTC (rev 93121)
+++ trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp 2011-08-16 17:15:06 UTC (rev 93122)
@@ -130,6 +130,14 @@
namespace WebCore {
+enum ForcePseudoClassFlags {
+ PseudoNone = 0,
+ PseudoHover = 1 << 0,
+ PseudoFocus = 1 << 1,
+ PseudoActive = 1 << 2,
+ PseudoVisited = 1 << 3
+};
+
static unsigned computePseudoClassMask(InspectorArray* pseudoClassArray)
{
DEFINE_STATIC_LOCAL(String, active, ("active"));
@@ -137,9 +145,9 @@
DEFINE_STATIC_LOCAL(String, focus, ("focus"));
DEFINE_STATIC_LOCAL(String, visited, ("visited"));
if (!pseudoClassArray || !pseudoClassArray->length())
- return CSSStyleSelector::DoNotForcePseudoClassMask;
+ return PseudoNone;
- unsigned result = CSSStyleSelector::ForceNone;
+ unsigned result = PseudoNone;
for (size_t i = 0; i < pseudoClassArray->length(); ++i) {
RefPtr<InspectorValue> pseudoClassValue = pseudoClassArray->get(i);
String pseudoClass;
@@ -147,13 +155,13 @@
if (!success)
continue;
if (pseudoClass == active)
- result |= CSSStyleSelector::ForceActive;
+ result |= PseudoActive;
else if (pseudoClass == hover)
- result |= CSSStyleSelector::ForceHover;
+ result |= PseudoHover;
else if (pseudoClass == focus)
- result |= CSSStyleSelector::ForceFocus;
+ result |= PseudoFocus;
else if (pseudoClass == visited)
- result |= CSSStyleSelector::ForceVisited;
+ result |= PseudoVisited;
}
return result;
@@ -186,6 +194,7 @@
InspectorCSSAgent::InspectorCSSAgent(InstrumentingAgents* instrumentingAgents, InspectorDOMAgent* domAgent)
: m_instrumentingAgents(instrumentingAgents)
, m_domAgent(domAgent)
+ , m_lastPseudoState(0)
, m_lastStyleSheetId(1)
, m_lastRuleId(1)
, m_lastStyleId(1)
@@ -203,6 +212,11 @@
reset();
}
+void InspectorCSSAgent::clearFrontend()
+{
+ clearPseudoState(true);
+}
+
void InspectorCSSAgent::reset()
{
m_idToInspectorStyleSheet.clear();
@@ -211,6 +225,25 @@
m_documentToInspectorStyleSheet.clear();
}
+bool InspectorCSSAgent::forcePseudoState(Element* element, CSSSelector::PseudoType pseudoType)
+{
+ if (m_lastElementWithPseudoState != element)
+ return false;
+
+ switch (pseudoType) {
+ case CSSSelector::PseudoActive:
+ return m_lastPseudoState & PseudoActive;
+ case CSSSelector::PseudoFocus:
+ return m_lastPseudoState & PseudoFocus;
+ case CSSSelector::PseudoHover:
+ return m_lastPseudoState & PseudoHover;
+ case CSSSelector::PseudoVisited:
+ return m_lastPseudoState & PseudoVisited;
+ default:
+ return false;
+ }
+}
+
void InspectorCSSAgent::getStylesForNode(ErrorString* errorString, int nodeId, const RefPtr<InspectorArray>* forcedPseudoClasses, RefPtr<InspectorObject>* result)
{
Element* element = elementForId(errorString, nodeId);
@@ -227,16 +260,22 @@
RefPtr<InspectorStyle> computedInspectorStyle = InspectorStyle::create(InspectorCSSId(), computedStyleInfo, 0);
resultObject->setObject("computedStyle", computedInspectorStyle->buildObjectForStyle());
- unsigned forcePseudoClassMask = computePseudoClassMask(forcedPseudoClasses ? forcedPseudoClasses->get() : 0);
+ unsigned forcePseudoState = computePseudoClassMask(forcedPseudoClasses ? forcedPseudoClasses->get() : 0);
+ bool needStyleRecalc = element != m_lastElementWithPseudoState || forcePseudoState != m_lastPseudoState;
+ m_lastPseudoState = forcePseudoState;
+ m_lastElementWithPseudoState = element;
+ if (needStyleRecalc)
+ element->ownerDocument()->styleSelectorChanged(RecalcStyleImmediately);
+
CSSStyleSelector* selector = element->ownerDocument()->styleSelector();
- RefPtr<CSSRuleList> matchedRules = selector->styleRulesForElement(element, CSSStyleSelector::AllCSSRules, forcePseudoClassMask);
+ RefPtr<CSSRuleList> matchedRules = selector->styleRulesForElement(element, CSSStyleSelector::AllCSSRules);
resultObject->setArray("matchedCSSRules", buildArrayForRuleList(matchedRules.get()));
resultObject->setArray("styleAttributes", buildArrayForAttributeStyles(element));
RefPtr<InspectorArray> pseudoElements = InspectorArray::create();
for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < AFTER_LAST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
- RefPtr<CSSRuleList> matchedRules = selector->pseudoStyleRulesForElement(element, pseudoId, CSSStyleSelector::AllCSSRules, forcePseudoClassMask);
+ RefPtr<CSSRuleList> matchedRules = selector->pseudoStyleRulesForElement(element, pseudoId, CSSStyleSelector::AllCSSRules);
if (matchedRules && matchedRules->length()) {
RefPtr<InspectorObject> pseudoStyles = InspectorObject::create();
pseudoStyles->setNumber("pseudoId", static_cast<int>(pseudoId));
@@ -583,6 +622,7 @@
{
if (document)
m_documentToInspectorStyleSheet.remove(document);
+ clearPseudoState(false);
}
void InspectorCSSAgent::didRemoveDOMNode(Node* node)
@@ -590,6 +630,11 @@
if (!node)
return;
+ if (m_lastElementWithPseudoState.get() == node) {
+ clearPseudoState(false);
+ return;
+ }
+
NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(node);
if (it == m_nodeToInspectorStyleSheet.end())
return;
@@ -610,6 +655,18 @@
it->second->didModifyElementAttribute();
}
+void InspectorCSSAgent::clearPseudoState(bool recalcStyles)
+{
+ Element* element = m_lastElementWithPseudoState.get();
+ m_lastElementWithPseudoState = 0;
+ m_lastPseudoState = 0;
+ if (recalcStyles && element) {
+ Document* document = element->ownerDocument();
+ if (document)
+ document->styleSelectorChanged(RecalcStyleImmediately);
+ }
+}
+
} // namespace WebCore
#endif // ENABLE(INSPECTOR)