| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/layout/ScrollAnchor.h" | 5 #include "core/layout/ScrollAnchor.h" |
| 6 | 6 |
| 7 #include "core/frame/FrameView.h" | 7 #include "core/frame/FrameView.h" |
| 8 #include "core/frame/UseCounter.h" | 8 #include "core/frame/UseCounter.h" |
| 9 #include "core/layout/LayoutBlockFlow.h" | 9 #include "core/layout/LayoutBlockFlow.h" |
| 10 #include "core/layout/api/LayoutBoxItem.h" | 10 #include "core/layout/api/LayoutBoxItem.h" |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 return false; | 118 return false; |
| 119 } | 119 } |
| 120 | 120 |
| 121 LayoutObject::AncestorSkipInfo skipInfo(scrollerLayoutBox(scroller)); | 121 LayoutObject::AncestorSkipInfo skipInfo(scrollerLayoutBox(scroller)); |
| 122 candidate->container(&skipInfo); | 122 candidate->container(&skipInfo); |
| 123 return !skipInfo.ancestorSkipped(); | 123 return !skipInfo.ancestorSkipped(); |
| 124 } | 124 } |
| 125 | 125 |
| 126 ScrollAnchor::ExamineResult ScrollAnchor::examine( | 126 ScrollAnchor::ExamineResult ScrollAnchor::examine( |
| 127 const LayoutObject* candidate) const { | 127 const LayoutObject* candidate) const { |
| 128 if (candidate == scrollerLayoutBox(m_scroller)) |
| 129 return ExamineResult(Continue); |
| 130 |
| 128 if (candidate->isLayoutInline()) | 131 if (candidate->isLayoutInline()) |
| 129 return ExamineResult(Continue); | 132 return ExamineResult(Continue); |
| 130 | 133 |
| 131 // Anonymous blocks are not in the DOM tree and it may be hard for | 134 // Anonymous blocks are not in the DOM tree and it may be hard for |
| 132 // developers to reason about the anchor node. | 135 // developers to reason about the anchor node. |
| 133 if (candidate->isAnonymous()) | 136 if (candidate->isAnonymous()) |
| 134 return ExamineResult(Continue); | 137 return ExamineResult(Continue); |
| 135 | 138 |
| 136 if (!candidate->isText() && !candidate->isBox()) | 139 if (!candidate->isText() && !candidate->isBox()) |
| 137 return ExamineResult(Skip); | 140 return ExamineResult(Skip); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 152 visibleRect.contains(candidateRect) ? Return : Constrain, | 155 visibleRect.contains(candidateRect) ? Return : Constrain, |
| 153 cornerToAnchor(m_scroller)); | 156 cornerToAnchor(m_scroller)); |
| 154 } else { | 157 } else { |
| 155 return ExamineResult(Skip); | 158 return ExamineResult(Skip); |
| 156 } | 159 } |
| 157 } | 160 } |
| 158 | 161 |
| 159 void ScrollAnchor::findAnchor() { | 162 void ScrollAnchor::findAnchor() { |
| 160 TRACE_EVENT0("blink", "ScrollAnchor::findAnchor"); | 163 TRACE_EVENT0("blink", "ScrollAnchor::findAnchor"); |
| 161 SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Layout.ScrollAnchor.TimeToFindAnchor"); | 164 SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Layout.ScrollAnchor.TimeToFindAnchor"); |
| 165 findAnchorRecursive(scrollerLayoutBox(m_scroller)); |
| 166 } |
| 162 | 167 |
| 163 LayoutObject* stayWithin = scrollerLayoutBox(m_scroller); | 168 bool ScrollAnchor::findAnchorRecursive(LayoutObject* candidate) { |
| 164 LayoutObject* candidate = stayWithin->nextInPreOrder(stayWithin); | 169 ExamineResult result = examine(candidate); |
| 165 while (candidate) { | 170 if (result.viable) { |
| 166 ExamineResult result = examine(candidate); | 171 m_anchorObject = candidate; |
| 167 if (result.viable) { | 172 m_corner = result.corner; |
| 168 m_anchorObject = candidate; | 173 } |
| 169 m_corner = result.corner; | 174 |
| 170 } | 175 if (result.status == Return) |
| 171 switch (result.status) { | 176 return true; |
| 172 case Skip: | 177 |
| 173 candidate = candidate->nextInPreOrderAfterChildren(stayWithin); | 178 if (result.status == Skip) |
| 174 break; | 179 return false; |
| 175 case Constrain: | 180 |
| 176 stayWithin = candidate; | 181 for (LayoutObject* child = candidate->slowFirstChild(); child; |
| 177 // fall through | 182 child = child->nextSibling()) { |
| 178 case Continue: | 183 if (findAnchorRecursive(child)) |
| 179 candidate = candidate->nextInPreOrder(stayWithin); | 184 return true; |
| 180 break; | 185 } |
| 181 case Return: | 186 |
| 182 return; | 187 // Make a separate pass to catch positioned descendants with a static DOM |
| 188 // parent that we skipped over (crbug.com/692701). |
| 189 if (candidate->isLayoutBlock()) { |
| 190 if (TrackedLayoutBoxListHashSet* positionedDescendants = |
| 191 toLayoutBlock(candidate)->positionedObjects()) { |
| 192 for (LayoutBox* descendant : *positionedDescendants) { |
| 193 if (descendant->parent() != candidate) { |
| 194 if (findAnchorRecursive(descendant)) |
| 195 return true; |
| 196 } |
| 197 } |
| 183 } | 198 } |
| 184 } | 199 } |
| 200 |
| 201 if (result.status == Constrain) |
| 202 return true; |
| 203 |
| 204 DCHECK(result.status == Continue); |
| 205 return false; |
| 185 } | 206 } |
| 186 | 207 |
| 187 bool ScrollAnchor::computeScrollAnchorDisablingStyleChanged() { | 208 bool ScrollAnchor::computeScrollAnchorDisablingStyleChanged() { |
| 188 LayoutObject* current = anchorObject(); | 209 LayoutObject* current = anchorObject(); |
| 189 if (!current) | 210 if (!current) |
| 190 return false; | 211 return false; |
| 191 | 212 |
| 192 LayoutObject* scrollerBox = scrollerLayoutBox(m_scroller); | 213 LayoutObject* scrollerBox = scrollerLayoutBox(m_scroller); |
| 193 while (true) { | 214 while (true) { |
| 194 DCHECK(current); | 215 DCHECK(current); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 bool ScrollAnchor::refersTo(const LayoutObject* layoutObject) const { | 350 bool ScrollAnchor::refersTo(const LayoutObject* layoutObject) const { |
| 330 return m_anchorObject == layoutObject; | 351 return m_anchorObject == layoutObject; |
| 331 } | 352 } |
| 332 | 353 |
| 333 void ScrollAnchor::notifyRemoved(LayoutObject* layoutObject) { | 354 void ScrollAnchor::notifyRemoved(LayoutObject* layoutObject) { |
| 334 if (m_anchorObject == layoutObject) | 355 if (m_anchorObject == layoutObject) |
| 335 clearSelf(); | 356 clearSelf(); |
| 336 } | 357 } |
| 337 | 358 |
| 338 } // namespace blink | 359 } // namespace blink |
| OLD | NEW |