| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights
reserved. | 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights
reserved. |
| 6 * | 6 * |
| 7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
| 8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
| 9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
| 10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
| (...skipping 1062 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1073 | 1073 |
| 1074 // This is used by FrameSelection to denote when the active-state of the page ha
s changed | 1074 // This is used by FrameSelection to denote when the active-state of the page ha
s changed |
| 1075 // independent of the focused element changing. | 1075 // independent of the focused element changing. |
| 1076 void ContainerNode::focusStateChanged() | 1076 void ContainerNode::focusStateChanged() |
| 1077 { | 1077 { |
| 1078 // If we're just changing the window's active state and the focused node has
no | 1078 // If we're just changing the window's active state and the focused node has
no |
| 1079 // layoutObject we can just ignore the state change. | 1079 // layoutObject we can just ignore the state change. |
| 1080 if (!layoutObject()) | 1080 if (!layoutObject()) |
| 1081 return; | 1081 return; |
| 1082 | 1082 |
| 1083 if (computedStyle()->affectedByFocus() && computedStyle()->hasPseudoStyle(FI
RST_LETTER)) | 1083 if (computedStyle()->affectedByFocus()) { |
| 1084 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::cre
ateWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Focus)); | 1084 StyleChangeType changeType = computedStyle()->hasPseudoStyle(FIRST_LETTE
R) ? SubtreeStyleChange : LocalStyleChange; |
| 1085 else if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByFoc
us()) | 1085 setNeedsStyleRecalc(changeType, StyleChangeReasonForTracing::createWithE
xtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Focus)); |
| 1086 } |
| 1087 if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByFocus()) |
| 1086 toElement(this)->pseudoStateChanged(CSSSelector::PseudoFocus); | 1088 toElement(this)->pseudoStateChanged(CSSSelector::PseudoFocus); |
| 1087 else if (computedStyle()->affectedByFocus()) | |
| 1088 setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::creat
eWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Focus)); | |
| 1089 | 1089 |
| 1090 LayoutTheme::theme().controlStateChanged(*layoutObject(), FocusControlState)
; | 1090 LayoutTheme::theme().controlStateChanged(*layoutObject(), FocusControlState)
; |
| 1091 } | 1091 } |
| 1092 | 1092 |
| 1093 void ContainerNode::setFocus(bool received) | 1093 void ContainerNode::setFocus(bool received) |
| 1094 { | 1094 { |
| 1095 // Recurse up author shadow trees to mark shadow hosts if it matches :focus. | 1095 // Recurse up author shadow trees to mark shadow hosts if it matches :focus. |
| 1096 // TODO(kochi): Handle UA shadows which marks multiple nodes as focused such
as | 1096 // TODO(kochi): Handle UA shadows which marks multiple nodes as focused such
as |
| 1097 // <input type="date"> the same way as author shadow. | 1097 // <input type="date"> the same way as author shadow. |
| 1098 if (ShadowRoot* root = containingShadowRoot()) { | 1098 if (ShadowRoot* root = containingShadowRoot()) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1126 | 1126 |
| 1127 void ContainerNode::setActive(bool down) | 1127 void ContainerNode::setActive(bool down) |
| 1128 { | 1128 { |
| 1129 if (down == active()) | 1129 if (down == active()) |
| 1130 return; | 1130 return; |
| 1131 | 1131 |
| 1132 Node::setActive(down); | 1132 Node::setActive(down); |
| 1133 | 1133 |
| 1134 // FIXME: Why does this not need to handle the display: none transition like
:hover does? | 1134 // FIXME: Why does this not need to handle the display: none transition like
:hover does? |
| 1135 if (layoutObject()) { | 1135 if (layoutObject()) { |
| 1136 if (computedStyle()->affectedByActive() && computedStyle()->hasPseudoSty
le(FIRST_LETTER)) | 1136 if (computedStyle()->affectedByActive()) { |
| 1137 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing:
:createWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Activ
e)); | 1137 StyleChangeType changeType = computedStyle()->hasPseudoStyle(FIRST_L
ETTER) ? SubtreeStyleChange : LocalStyleChange; |
| 1138 else if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedB
yActive()) | 1138 setNeedsStyleRecalc(changeType, StyleChangeReasonForTracing::createW
ithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Active)); |
| 1139 } |
| 1140 if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByActi
ve()) |
| 1139 toElement(this)->pseudoStateChanged(CSSSelector::PseudoActive); | 1141 toElement(this)->pseudoStateChanged(CSSSelector::PseudoActive); |
| 1140 else if (computedStyle()->affectedByActive()) | |
| 1141 setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::c
reateWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Active)
); | |
| 1142 | 1142 |
| 1143 LayoutTheme::theme().controlStateChanged(*layoutObject(), PressedControl
State); | 1143 LayoutTheme::theme().controlStateChanged(*layoutObject(), PressedControl
State); |
| 1144 } | 1144 } |
| 1145 } | 1145 } |
| 1146 | 1146 |
| 1147 void ContainerNode::setHovered(bool over) | 1147 void ContainerNode::setHovered(bool over) |
| 1148 { | 1148 { |
| 1149 if (over == hovered()) | 1149 if (over == hovered()) |
| 1150 return; | 1150 return; |
| 1151 | 1151 |
| 1152 Node::setHovered(over); | 1152 Node::setHovered(over); |
| 1153 | 1153 |
| 1154 // If :hover sets display: none we lose our hover but still need to recalc o
ur style. | 1154 // If :hover sets display: none we lose our hover but still need to recalc o
ur style. |
| 1155 if (!layoutObject()) { | 1155 if (!layoutObject()) { |
| 1156 if (over) | 1156 if (over) |
| 1157 return; | 1157 return; |
| 1158 if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByHove
r()) | 1158 if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByHove
r()) |
| 1159 toElement(this)->pseudoStateChanged(CSSSelector::PseudoHover); | 1159 toElement(this)->pseudoStateChanged(CSSSelector::PseudoHover); |
| 1160 else | 1160 else |
| 1161 setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::c
reateWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Hover))
; | 1161 setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::c
reateWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Hover))
; |
| 1162 return; | 1162 return; |
| 1163 } | 1163 } |
| 1164 | 1164 |
| 1165 if (computedStyle()->affectedByHover() && computedStyle()->hasPseudoStyle(FI
RST_LETTER)) | 1165 if (computedStyle()->affectedByHover()) { |
| 1166 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::cre
ateWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Hover)); | 1166 StyleChangeType changeType = computedStyle()->hasPseudoStyle(FIRST_LETTE
R) ? SubtreeStyleChange : LocalStyleChange; |
| 1167 else if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByHov
er()) | 1167 setNeedsStyleRecalc(changeType, StyleChangeReasonForTracing::createWithE
xtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Hover)); |
| 1168 } |
| 1169 if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByHover()) |
| 1168 toElement(this)->pseudoStateChanged(CSSSelector::PseudoHover); | 1170 toElement(this)->pseudoStateChanged(CSSSelector::PseudoHover); |
| 1169 else if (computedStyle()->affectedByHover()) | |
| 1170 setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::creat
eWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Hover)); | |
| 1171 | 1171 |
| 1172 LayoutTheme::theme().controlStateChanged(*layoutObject(), HoverControlState)
; | 1172 LayoutTheme::theme().controlStateChanged(*layoutObject(), HoverControlState)
; |
| 1173 } | 1173 } |
| 1174 | 1174 |
| 1175 PassRefPtrWillBeRawPtr<HTMLCollection> ContainerNode::children() | 1175 PassRefPtrWillBeRawPtr<HTMLCollection> ContainerNode::children() |
| 1176 { | 1176 { |
| 1177 return ensureCachedCollection<HTMLCollection>(NodeChildren); | 1177 return ensureCachedCollection<HTMLCollection>(NodeChildren); |
| 1178 } | 1178 } |
| 1179 | 1179 |
| 1180 unsigned ContainerNode::countChildren() const | 1180 unsigned ContainerNode::countChildren() const |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1293 ASSERT(isElementNode() || isShadowRoot()); | 1293 ASSERT(isElementNode() || isShadowRoot()); |
| 1294 ensureRareData().setRestyleFlag(mask); | 1294 ensureRareData().setRestyleFlag(mask); |
| 1295 } | 1295 } |
| 1296 | 1296 |
| 1297 void ContainerNode::recalcChildStyle(StyleRecalcChange change) | 1297 void ContainerNode::recalcChildStyle(StyleRecalcChange change) |
| 1298 { | 1298 { |
| 1299 ASSERT(document().inStyleRecalc()); | 1299 ASSERT(document().inStyleRecalc()); |
| 1300 ASSERT(change >= UpdatePseudoElements || childNeedsStyleRecalc()); | 1300 ASSERT(change >= UpdatePseudoElements || childNeedsStyleRecalc()); |
| 1301 ASSERT(!needsStyleRecalc()); | 1301 ASSERT(!needsStyleRecalc()); |
| 1302 | 1302 |
| 1303 if (change < Force && hasRareData() && childNeedsStyleRecalc()) | |
| 1304 checkForChildrenAdjacentRuleChanges(); | |
| 1305 | |
| 1306 // This loop is deliberately backwards because we use insertBefore in the la
yout tree, and want to avoid | 1303 // This loop is deliberately backwards because we use insertBefore in the la
yout tree, and want to avoid |
| 1307 // a potentially n^2 loop to find the insertion point while resolving style.
Having us start from the last | 1304 // a potentially n^2 loop to find the insertion point while resolving style.
Having us start from the last |
| 1308 // child and work our way back means in the common case, we'll find the inse
rtion point in O(1) time. | 1305 // child and work our way back means in the common case, we'll find the inse
rtion point in O(1) time. |
| 1309 // See crbug.com/288225 | 1306 // See crbug.com/288225 |
| 1310 StyleResolver& styleResolver = document().ensureStyleResolver(); | 1307 StyleResolver& styleResolver = document().ensureStyleResolver(); |
| 1311 Text* lastTextNode = nullptr; | 1308 Text* lastTextNode = nullptr; |
| 1312 for (Node* child = lastChild(); child; child = child->previousSibling()) { | 1309 for (Node* child = lastChild(); child; child = child->previousSibling()) { |
| 1313 if (child->isTextNode()) { | 1310 if (child->isTextNode()) { |
| 1314 toText(child)->recalcTextStyle(change, lastTextNode); | 1311 toText(child)->recalcTextStyle(change, lastTextNode); |
| 1315 lastTextNode = toText(child); | 1312 lastTextNode = toText(child); |
| 1316 } else if (child->isElementNode()) { | 1313 } else if (child->isElementNode()) { |
| 1317 Element* element = toElement(child); | 1314 Element* element = toElement(child); |
| 1318 if (element->shouldCallRecalcStyle(change)) | 1315 if (element->shouldCallRecalcStyle(change)) |
| 1319 element->recalcStyle(change, lastTextNode); | 1316 element->recalcStyle(change, lastTextNode); |
| 1320 else if (element->supportsStyleSharing()) | 1317 else if (element->supportsStyleSharing()) |
| 1321 styleResolver.addToStyleSharingList(*element); | 1318 styleResolver.addToStyleSharingList(*element); |
| 1322 if (element->layoutObject()) | 1319 if (element->layoutObject()) |
| 1323 lastTextNode = nullptr; | 1320 lastTextNode = nullptr; |
| 1324 } | 1321 } |
| 1325 } | 1322 } |
| 1326 } | 1323 } |
| 1327 | 1324 |
| 1328 void ContainerNode::checkForChildrenAdjacentRuleChanges() | |
| 1329 { | |
| 1330 bool hasDirectAdjacentRules = childrenAffectedByDirectAdjacentRules(); | |
| 1331 bool hasIndirectAdjacentRules = childrenAffectedByIndirectAdjacentRules(); | |
| 1332 | |
| 1333 if (!hasDirectAdjacentRules && !hasIndirectAdjacentRules) | |
| 1334 return; | |
| 1335 | |
| 1336 unsigned forceCheckOfNextElementCount = 0; | |
| 1337 bool forceCheckOfAnyElementSibling = false; | |
| 1338 Document& document = this->document(); | |
| 1339 | |
| 1340 for (Element* child = ElementTraversal::firstChild(*this); child; child = El
ementTraversal::nextSibling(*child)) { | |
| 1341 bool childRulesChanged = child->needsStyleRecalc() && child->styleChange
Type() >= SubtreeStyleChange; | |
| 1342 | |
| 1343 if (forceCheckOfNextElementCount || forceCheckOfAnyElementSibling) | |
| 1344 child->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForT
racing::create(StyleChangeReason::SiblingSelector)); | |
| 1345 | |
| 1346 if (childRulesChanged && hasDirectAdjacentRules) | |
| 1347 forceCheckOfNextElementCount = document.styleEngine().maxDirectAdjac
entSelectors(); | |
| 1348 else if (forceCheckOfNextElementCount) | |
| 1349 --forceCheckOfNextElementCount; | |
| 1350 | |
| 1351 forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childR
ulesChanged && hasIndirectAdjacentRules); | |
| 1352 } | |
| 1353 } | |
| 1354 | |
| 1355 void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Nod
e* nodeBeforeChange, Node* nodeAfterChange) | 1325 void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Nod
e* nodeBeforeChange, Node* nodeAfterChange) |
| 1356 { | 1326 { |
| 1357 if (!inActiveDocument() || document().hasPendingForcedStyleRecalc() || style
ChangeType() >= SubtreeStyleChange) | 1327 if (!inActiveDocument() || document().hasPendingForcedStyleRecalc() || style
ChangeType() >= SubtreeStyleChange) |
| 1358 return; | 1328 return; |
| 1359 | 1329 |
| 1360 // Forward positional selectors include nth-child, nth-of-type, first-of-typ
e and only-of-type. | 1330 // Forward positional selectors include nth-child, nth-of-type, first-of-typ
e and only-of-type. |
| 1361 // The indirect adjacent selector is the ~ selector. | 1331 // The indirect adjacent selector is the ~ selector. |
| 1362 // Backward positional selectors include nth-last-child, nth-last-of-type, l
ast-of-type and only-of-type. | 1332 // Backward positional selectors include nth-last-child, nth-last-of-type, l
ast-of-type and only-of-type. |
| 1363 // We have to invalidate everything following the insertion point in the for
ward and indirect adjacent case, | 1333 // We have to invalidate everything following the insertion point in the for
ward and indirect adjacent case, |
| 1364 // and everything before the insertion point in the backward case. | 1334 // and everything before the insertion point in the backward case. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1410 | 1380 |
| 1411 // This is the last child element removal case. The parser callback case
is similar to node removal as well in that we need to change the last child | 1381 // This is the last child element removal case. The parser callback case
is similar to node removal as well in that we need to change the last child |
| 1412 // to match now. | 1382 // to match now. |
| 1413 if ((changeType == SiblingElementRemoved || changeType == FinishedParsin
gChildren) && lastChildElement == elementBeforeChange && lastChildElement && las
tChildElement->affectedByLastChildRules()) | 1383 if ((changeType == SiblingElementRemoved || changeType == FinishedParsin
gChildren) && lastChildElement == elementBeforeChange && lastChildElement && las
tChildElement->affectedByLastChildRules()) |
| 1414 lastChildElement->setNeedsStyleRecalc(SubtreeStyleChange, StyleChang
eReasonForTracing::create(StyleChangeReason::SiblingSelector)); | 1384 lastChildElement->setNeedsStyleRecalc(SubtreeStyleChange, StyleChang
eReasonForTracing::create(StyleChangeReason::SiblingSelector)); |
| 1415 } | 1385 } |
| 1416 | 1386 |
| 1417 // The + selector. We need to invalidate the first element following the cha
nge. It is the only possible element | 1387 // The + selector. We need to invalidate the first element following the cha
nge. It is the only possible element |
| 1418 // that could be affected by this DOM change. | 1388 // that could be affected by this DOM change. |
| 1419 if (childrenAffectedByDirectAdjacentRules() && nodeAfterChange) { | 1389 if (childrenAffectedByDirectAdjacentRules() && nodeAfterChange) { |
| 1420 if (Element* elementAfterChange = nodeAfterChange->isElementNode() ? toE
lement(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange)) | 1390 Element* elementAfterChange = nodeAfterChange->isElementNode() ? toEleme
nt(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange); |
| 1391 for (unsigned i = document().styleEngine().maxDirectAdjacentSelectors();
i && elementAfterChange; --i, elementAfterChange = ElementTraversal::nextSiblin
g(*elementAfterChange)) |
| 1421 elementAfterChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleCha
ngeReasonForTracing::create(StyleChangeReason::SiblingSelector)); | 1392 elementAfterChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleCha
ngeReasonForTracing::create(StyleChangeReason::SiblingSelector)); |
| 1422 } | 1393 } |
| 1423 } | 1394 } |
| 1424 | 1395 |
| 1425 void ContainerNode::invalidateNodeListCachesInAncestors(const QualifiedName* att
rName, Element* attributeOwnerElement) | 1396 void ContainerNode::invalidateNodeListCachesInAncestors(const QualifiedName* att
rName, Element* attributeOwnerElement) |
| 1426 { | 1397 { |
| 1427 if (hasRareData() && (!attrName || isAttributeNode())) { | 1398 if (hasRareData() && (!attrName || isAttributeNode())) { |
| 1428 if (NodeListsNodeData* lists = rareData()->nodeLists()) { | 1399 if (NodeListsNodeData* lists = rareData()->nodeLists()) { |
| 1429 if (ChildNodeList* childNodeList = lists->childNodeList(*this)) | 1400 if (ChildNodeList* childNodeList = lists->childNodeList(*this)) |
| 1430 childNodeList->invalidateCache(); | 1401 childNodeList->invalidateCache(); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1523 return true; | 1494 return true; |
| 1524 | 1495 |
| 1525 if (node->isElementNode() && toElement(node)->shadow()) | 1496 if (node->isElementNode() && toElement(node)->shadow()) |
| 1526 return true; | 1497 return true; |
| 1527 | 1498 |
| 1528 return false; | 1499 return false; |
| 1529 } | 1500 } |
| 1530 #endif | 1501 #endif |
| 1531 | 1502 |
| 1532 } // namespace blink | 1503 } // namespace blink |
| OLD | NEW |