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 1079 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1090 | 1090 |
1091 // This is used by FrameSelection to denote when the active-state of the page ha
s changed | 1091 // This is used by FrameSelection to denote when the active-state of the page ha
s changed |
1092 // independent of the focused element changing. | 1092 // independent of the focused element changing. |
1093 void ContainerNode::focusStateChanged() | 1093 void ContainerNode::focusStateChanged() |
1094 { | 1094 { |
1095 // If we're just changing the window's active state and the focused node has
no | 1095 // If we're just changing the window's active state and the focused node has
no |
1096 // layoutObject we can just ignore the state change. | 1096 // layoutObject we can just ignore the state change. |
1097 if (!layoutObject()) | 1097 if (!layoutObject()) |
1098 return; | 1098 return; |
1099 | 1099 |
1100 if (computedStyle()->affectedByFocus() && computedStyle()->hasPseudoStyle(FI
RST_LETTER)) | 1100 if (computedStyle()->affectedByFocus()) { |
1101 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::cre
ateWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Focus)); | 1101 StyleChangeType changeType = computedStyle()->hasPseudoStyle(FIRST_LETTE
R) ? SubtreeStyleChange : LocalStyleChange; |
1102 else if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByFoc
us()) | 1102 setNeedsStyleRecalc(changeType, StyleChangeReasonForTracing::createWithE
xtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Focus)); |
| 1103 } |
| 1104 if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByFocus()) |
1103 toElement(this)->pseudoStateChanged(CSSSelector::PseudoFocus); | 1105 toElement(this)->pseudoStateChanged(CSSSelector::PseudoFocus); |
1104 else if (computedStyle()->affectedByFocus()) | |
1105 setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::creat
eWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Focus)); | |
1106 | 1106 |
1107 LayoutTheme::theme().controlStateChanged(*layoutObject(), FocusControlState)
; | 1107 LayoutTheme::theme().controlStateChanged(*layoutObject(), FocusControlState)
; |
1108 } | 1108 } |
1109 | 1109 |
1110 void ContainerNode::setFocus(bool received) | 1110 void ContainerNode::setFocus(bool received) |
1111 { | 1111 { |
1112 // Recurse up author shadow trees to mark shadow hosts if it matches :focus. | 1112 // Recurse up author shadow trees to mark shadow hosts if it matches :focus. |
1113 // TODO(kochi): Handle UA shadows which marks multiple nodes as focused such
as | 1113 // TODO(kochi): Handle UA shadows which marks multiple nodes as focused such
as |
1114 // <input type="date"> the same way as author shadow. | 1114 // <input type="date"> the same way as author shadow. |
1115 if (ShadowRoot* root = containingShadowRoot()) { | 1115 if (ShadowRoot* root = containingShadowRoot()) { |
(...skipping 27 matching lines...) Expand all Loading... |
1143 | 1143 |
1144 void ContainerNode::setActive(bool down) | 1144 void ContainerNode::setActive(bool down) |
1145 { | 1145 { |
1146 if (down == active()) | 1146 if (down == active()) |
1147 return; | 1147 return; |
1148 | 1148 |
1149 Node::setActive(down); | 1149 Node::setActive(down); |
1150 | 1150 |
1151 // FIXME: Why does this not need to handle the display: none transition like
:hover does? | 1151 // FIXME: Why does this not need to handle the display: none transition like
:hover does? |
1152 if (layoutObject()) { | 1152 if (layoutObject()) { |
1153 if (computedStyle()->affectedByActive() && computedStyle()->hasPseudoSty
le(FIRST_LETTER)) | 1153 if (computedStyle()->affectedByActive()) { |
1154 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing:
:createWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Activ
e)); | 1154 StyleChangeType changeType = computedStyle()->hasPseudoStyle(FIRST_L
ETTER) ? SubtreeStyleChange : LocalStyleChange; |
1155 else if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedB
yActive()) | 1155 setNeedsStyleRecalc(changeType, StyleChangeReasonForTracing::createW
ithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Active)); |
| 1156 } |
| 1157 if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByActi
ve()) |
1156 toElement(this)->pseudoStateChanged(CSSSelector::PseudoActive); | 1158 toElement(this)->pseudoStateChanged(CSSSelector::PseudoActive); |
1157 else if (computedStyle()->affectedByActive()) | |
1158 setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::c
reateWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Active)
); | |
1159 | 1159 |
1160 LayoutTheme::theme().controlStateChanged(*layoutObject(), PressedControl
State); | 1160 LayoutTheme::theme().controlStateChanged(*layoutObject(), PressedControl
State); |
1161 } | 1161 } |
1162 } | 1162 } |
1163 | 1163 |
1164 void ContainerNode::setHovered(bool over) | 1164 void ContainerNode::setHovered(bool over) |
1165 { | 1165 { |
1166 if (over == hovered()) | 1166 if (over == hovered()) |
1167 return; | 1167 return; |
1168 | 1168 |
1169 Node::setHovered(over); | 1169 Node::setHovered(over); |
1170 | 1170 |
1171 // If :hover sets display: none we lose our hover but still need to recalc o
ur style. | 1171 // If :hover sets display: none we lose our hover but still need to recalc o
ur style. |
1172 if (!layoutObject()) { | 1172 if (!layoutObject()) { |
1173 if (over) | 1173 if (over) |
1174 return; | 1174 return; |
1175 if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByHove
r()) | 1175 if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByHove
r()) |
1176 toElement(this)->pseudoStateChanged(CSSSelector::PseudoHover); | 1176 toElement(this)->pseudoStateChanged(CSSSelector::PseudoHover); |
1177 else | 1177 else |
1178 setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::c
reateWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Hover))
; | 1178 setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::c
reateWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Hover))
; |
1179 return; | 1179 return; |
1180 } | 1180 } |
1181 | 1181 |
1182 if (computedStyle()->affectedByHover() && computedStyle()->hasPseudoStyle(FI
RST_LETTER)) | 1182 if (computedStyle()->affectedByHover()) { |
1183 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::cre
ateWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Hover)); | 1183 StyleChangeType changeType = computedStyle()->hasPseudoStyle(FIRST_LETTE
R) ? SubtreeStyleChange : LocalStyleChange; |
1184 else if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByHov
er()) | 1184 setNeedsStyleRecalc(changeType, StyleChangeReasonForTracing::createWithE
xtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Hover)); |
| 1185 } |
| 1186 if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByHover()) |
1185 toElement(this)->pseudoStateChanged(CSSSelector::PseudoHover); | 1187 toElement(this)->pseudoStateChanged(CSSSelector::PseudoHover); |
1186 else if (computedStyle()->affectedByHover()) | |
1187 setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::creat
eWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Hover)); | |
1188 | 1188 |
1189 LayoutTheme::theme().controlStateChanged(*layoutObject(), HoverControlState)
; | 1189 LayoutTheme::theme().controlStateChanged(*layoutObject(), HoverControlState)
; |
1190 } | 1190 } |
1191 | 1191 |
1192 PassRefPtrWillBeRawPtr<HTMLCollection> ContainerNode::children() | 1192 PassRefPtrWillBeRawPtr<HTMLCollection> ContainerNode::children() |
1193 { | 1193 { |
1194 return ensureCachedCollection<HTMLCollection>(NodeChildren); | 1194 return ensureCachedCollection<HTMLCollection>(NodeChildren); |
1195 } | 1195 } |
1196 | 1196 |
1197 unsigned ContainerNode::countChildren() const | 1197 unsigned ContainerNode::countChildren() const |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1310 ASSERT(isElementNode() || isShadowRoot()); | 1310 ASSERT(isElementNode() || isShadowRoot()); |
1311 ensureRareData().setRestyleFlag(mask); | 1311 ensureRareData().setRestyleFlag(mask); |
1312 } | 1312 } |
1313 | 1313 |
1314 void ContainerNode::recalcChildStyle(StyleRecalcChange change) | 1314 void ContainerNode::recalcChildStyle(StyleRecalcChange change) |
1315 { | 1315 { |
1316 ASSERT(document().inStyleRecalc()); | 1316 ASSERT(document().inStyleRecalc()); |
1317 ASSERT(change >= UpdatePseudoElements || childNeedsStyleRecalc()); | 1317 ASSERT(change >= UpdatePseudoElements || childNeedsStyleRecalc()); |
1318 ASSERT(!needsStyleRecalc()); | 1318 ASSERT(!needsStyleRecalc()); |
1319 | 1319 |
1320 if (change < Force && hasRareData() && childNeedsStyleRecalc()) | |
1321 checkForChildrenAdjacentRuleChanges(); | |
1322 | |
1323 // This loop is deliberately backwards because we use insertBefore in the la
yout tree, and want to avoid | 1320 // This loop is deliberately backwards because we use insertBefore in the la
yout tree, and want to avoid |
1324 // a potentially n^2 loop to find the insertion point while resolving style.
Having us start from the last | 1321 // a potentially n^2 loop to find the insertion point while resolving style.
Having us start from the last |
1325 // child and work our way back means in the common case, we'll find the inse
rtion point in O(1) time. | 1322 // child and work our way back means in the common case, we'll find the inse
rtion point in O(1) time. |
1326 // See crbug.com/288225 | 1323 // See crbug.com/288225 |
1327 StyleResolver& styleResolver = document().ensureStyleResolver(); | 1324 StyleResolver& styleResolver = document().ensureStyleResolver(); |
1328 Text* lastTextNode = nullptr; | 1325 Text* lastTextNode = nullptr; |
1329 for (Node* child = lastChild(); child; child = child->previousSibling()) { | 1326 for (Node* child = lastChild(); child; child = child->previousSibling()) { |
1330 if (child->isTextNode()) { | 1327 if (child->isTextNode()) { |
1331 toText(child)->recalcTextStyle(change, lastTextNode); | 1328 toText(child)->recalcTextStyle(change, lastTextNode); |
1332 lastTextNode = toText(child); | 1329 lastTextNode = toText(child); |
1333 } else if (child->isElementNode()) { | 1330 } else if (child->isElementNode()) { |
1334 Element* element = toElement(child); | 1331 Element* element = toElement(child); |
1335 if (element->shouldCallRecalcStyle(change)) | 1332 if (element->shouldCallRecalcStyle(change)) |
1336 element->recalcStyle(change, lastTextNode); | 1333 element->recalcStyle(change, lastTextNode); |
1337 else if (element->supportsStyleSharing()) | 1334 else if (element->supportsStyleSharing()) |
1338 styleResolver.addToStyleSharingList(*element); | 1335 styleResolver.addToStyleSharingList(*element); |
1339 if (element->layoutObject()) | 1336 if (element->layoutObject()) |
1340 lastTextNode = nullptr; | 1337 lastTextNode = nullptr; |
1341 } | 1338 } |
1342 } | 1339 } |
1343 } | 1340 } |
1344 | 1341 |
1345 void ContainerNode::checkForChildrenAdjacentRuleChanges() | |
1346 { | |
1347 bool hasDirectAdjacentRules = childrenAffectedByDirectAdjacentRules(); | |
1348 bool hasIndirectAdjacentRules = childrenAffectedByIndirectAdjacentRules(); | |
1349 | |
1350 if (!hasDirectAdjacentRules && !hasIndirectAdjacentRules) | |
1351 return; | |
1352 | |
1353 unsigned forceCheckOfNextElementCount = 0; | |
1354 bool forceCheckOfAnyElementSibling = false; | |
1355 Document& document = this->document(); | |
1356 | |
1357 for (Element* child = ElementTraversal::firstChild(*this); child; child = El
ementTraversal::nextSibling(*child)) { | |
1358 bool childRulesChanged = child->needsStyleRecalc() && child->styleChange
Type() >= SubtreeStyleChange; | |
1359 | |
1360 if (forceCheckOfNextElementCount || forceCheckOfAnyElementSibling) | |
1361 child->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForT
racing::create(StyleChangeReason::SiblingSelector)); | |
1362 | |
1363 if (childRulesChanged && hasDirectAdjacentRules) | |
1364 forceCheckOfNextElementCount = document.styleEngine().maxDirectAdjac
entSelectors(); | |
1365 else if (forceCheckOfNextElementCount) | |
1366 --forceCheckOfNextElementCount; | |
1367 | |
1368 forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childR
ulesChanged && hasIndirectAdjacentRules); | |
1369 } | |
1370 } | |
1371 | |
1372 void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Nod
e* nodeBeforeChange, Node* nodeAfterChange) | 1342 void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Nod
e* nodeBeforeChange, Node* nodeAfterChange) |
1373 { | 1343 { |
1374 if (!inActiveDocument() || document().hasPendingForcedStyleRecalc() || style
ChangeType() >= SubtreeStyleChange) | 1344 if (!inActiveDocument() || document().hasPendingForcedStyleRecalc() || style
ChangeType() >= SubtreeStyleChange) |
1375 return; | 1345 return; |
1376 | 1346 |
1377 // Forward positional selectors include nth-child, nth-of-type, first-of-typ
e and only-of-type. | 1347 // Forward positional selectors include nth-child, nth-of-type, first-of-typ
e and only-of-type. |
1378 // The indirect adjacent selector is the ~ selector. | 1348 // The indirect adjacent selector is the ~ selector. |
1379 // Backward positional selectors include nth-last-child, nth-last-of-type, l
ast-of-type and only-of-type. | 1349 // Backward positional selectors include nth-last-child, nth-last-of-type, l
ast-of-type and only-of-type. |
1380 // We have to invalidate everything following the insertion point in the for
ward and indirect adjacent case, | 1350 // We have to invalidate everything following the insertion point in the for
ward and indirect adjacent case, |
1381 // and everything before the insertion point in the backward case. | 1351 // and everything before the insertion point in the backward case. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1427 | 1397 |
1428 // 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 | 1398 // 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 |
1429 // to match now. | 1399 // to match now. |
1430 if ((changeType == SiblingElementRemoved || changeType == FinishedParsin
gChildren) && lastChildElement == elementBeforeChange && lastChildElement && las
tChildElement->affectedByLastChildRules()) | 1400 if ((changeType == SiblingElementRemoved || changeType == FinishedParsin
gChildren) && lastChildElement == elementBeforeChange && lastChildElement && las
tChildElement->affectedByLastChildRules()) |
1431 lastChildElement->setNeedsStyleRecalc(SubtreeStyleChange, StyleChang
eReasonForTracing::create(StyleChangeReason::SiblingSelector)); | 1401 lastChildElement->setNeedsStyleRecalc(SubtreeStyleChange, StyleChang
eReasonForTracing::create(StyleChangeReason::SiblingSelector)); |
1432 } | 1402 } |
1433 | 1403 |
1434 // The + selector. We need to invalidate the first element following the cha
nge. It is the only possible element | 1404 // The + selector. We need to invalidate the first element following the cha
nge. It is the only possible element |
1435 // that could be affected by this DOM change. | 1405 // that could be affected by this DOM change. |
1436 if (childrenAffectedByDirectAdjacentRules() && nodeAfterChange) { | 1406 if (childrenAffectedByDirectAdjacentRules() && nodeAfterChange) { |
1437 if (Element* elementAfterChange = nodeAfterChange->isElementNode() ? toE
lement(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange)) | 1407 Element* elementAfterChange = nodeAfterChange->isElementNode() ? toEleme
nt(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange); |
| 1408 for (unsigned i = document().styleEngine().maxDirectAdjacentSelectors();
i && elementAfterChange; --i, elementAfterChange = ElementTraversal::nextSiblin
g(*elementAfterChange)) |
1438 elementAfterChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleCha
ngeReasonForTracing::create(StyleChangeReason::SiblingSelector)); | 1409 elementAfterChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleCha
ngeReasonForTracing::create(StyleChangeReason::SiblingSelector)); |
1439 } | 1410 } |
1440 } | 1411 } |
1441 | 1412 |
1442 void ContainerNode::invalidateNodeListCachesInAncestors(const QualifiedName* att
rName, Element* attributeOwnerElement) | 1413 void ContainerNode::invalidateNodeListCachesInAncestors(const QualifiedName* att
rName, Element* attributeOwnerElement) |
1443 { | 1414 { |
1444 if (hasRareData() && (!attrName || isAttributeNode())) { | 1415 if (hasRareData() && (!attrName || isAttributeNode())) { |
1445 if (NodeListsNodeData* lists = rareData()->nodeLists()) { | 1416 if (NodeListsNodeData* lists = rareData()->nodeLists()) { |
1446 if (ChildNodeList* childNodeList = lists->childNodeList(*this)) | 1417 if (ChildNodeList* childNodeList = lists->childNodeList(*this)) |
1447 childNodeList->invalidateCache(); | 1418 childNodeList->invalidateCache(); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1543 return true; | 1514 return true; |
1544 | 1515 |
1545 if (node->isElementNode() && toElement(node)->shadow()) | 1516 if (node->isElementNode() && toElement(node)->shadow()) |
1546 return true; | 1517 return true; |
1547 | 1518 |
1548 return false; | 1519 return false; |
1549 } | 1520 } |
1550 #endif | 1521 #endif |
1551 | 1522 |
1552 } // namespace blink | 1523 } // namespace blink |
OLD | NEW |