| 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/line/InlineTextBox.h" | 9 #include "core/layout/line/InlineTextBox.h" |
| 10 #include "core/paint/PaintLayerScrollableArea.h" | 10 #include "core/paint/PaintLayerScrollableArea.h" |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 if (scroller->isFrameView()) | 97 if (scroller->isFrameView()) |
| 98 relativeBounds.moveBy(-flooredIntPoint(scroller->scrollPositionDouble())
); | 98 relativeBounds.moveBy(-flooredIntPoint(scroller->scrollPositionDouble())
); |
| 99 return relativeBounds; | 99 return relativeBounds; |
| 100 } | 100 } |
| 101 | 101 |
| 102 static LayoutPoint computeRelativeOffset(const LayoutObject* layoutObject, const
ScrollableArea* scroller, Corner corner) | 102 static LayoutPoint computeRelativeOffset(const LayoutObject* layoutObject, const
ScrollableArea* scroller, Corner corner) |
| 103 { | 103 { |
| 104 return cornerPointOfRect(relativeBounds(layoutObject, scroller), corner); | 104 return cornerPointOfRect(relativeBounds(layoutObject, scroller), corner); |
| 105 } | 105 } |
| 106 | 106 |
| 107 static bool candidateMovesWithScroller(const LayoutObject* candidate, const Scro
llableArea* scroller) | 107 static bool candidateMayMoveWithScroller(const LayoutObject* candidate, const Sc
rollableArea* scroller) |
| 108 { | 108 { |
| 109 if (candidate->style() && candidate->style()->hasViewportConstrainedPosition
()) | 109 if (const ComputedStyle* style = candidate->style()) { |
| 110 return false; | 110 if (style->hasViewportConstrainedPosition()) |
| 111 return false; |
| 112 |
| 113 if (style->hasOutOfFlowPosition()) { |
| 114 // Absolute positioned elements with non-zero scrollTop/Left/Bottom/ |
| 115 // Right can stick to the viewport. |
| 116 if (!style->top().isZero() || !style->left().isZero() |
| 117 || !style->bottom().isZero() || !style->right().isZero()) |
| 118 return false; |
| 119 } |
| 120 } |
| 111 | 121 |
| 112 bool skippedByContainerLookup = false; | 122 bool skippedByContainerLookup = false; |
| 113 candidate->container(scrollerLayoutBox(scroller), &skippedByContainerLookup)
; | 123 candidate->container(scrollerLayoutBox(scroller), &skippedByContainerLookup)
; |
| 114 return !skippedByContainerLookup; | 124 return !skippedByContainerLookup; |
| 115 } | 125 } |
| 116 | 126 |
| 117 ScrollAnchor::ExamineResult ScrollAnchor::examine(const LayoutObject* candidate)
const | 127 ScrollAnchor::ExamineResult ScrollAnchor::examine(const LayoutObject* candidate)
const |
| 118 { | 128 { |
| 119 if (candidate->isLayoutInline()) | 129 if (candidate->isLayoutInline()) |
| 120 return ExamineResult(Continue); | 130 return ExamineResult(Continue); |
| 121 | 131 |
| 122 // Anonymous blocks are not in the DOM tree and it may be hard for | 132 // Anonymous blocks are not in the DOM tree and it may be hard for |
| 123 // developers to reason about the anchor node. | 133 // developers to reason about the anchor node. |
| 124 if (candidate->isAnonymous()) | 134 if (candidate->isAnonymous()) |
| 125 return ExamineResult(Continue); | 135 return ExamineResult(Continue); |
| 126 | 136 |
| 127 if (!candidate->isText() && !candidate->isBox()) | 137 if (!candidate->isText() && !candidate->isBox()) |
| 128 return ExamineResult(Skip); | 138 return ExamineResult(Skip); |
| 129 | 139 |
| 130 if (!candidateMovesWithScroller(candidate, m_scroller)) | 140 if (!candidateMayMoveWithScroller(candidate, m_scroller)) |
| 131 return ExamineResult(Skip); | 141 return ExamineResult(Skip); |
| 132 | 142 |
| 133 LayoutRect candidateRect = relativeBounds(candidate, m_scroller); | 143 LayoutRect candidateRect = relativeBounds(candidate, m_scroller); |
| 134 LayoutRect visibleRect = scrollerLayoutBoxItem(m_scroller).overflowClipRect(
LayoutPoint()); | 144 LayoutRect visibleRect = scrollerLayoutBoxItem(m_scroller).overflowClipRect(
LayoutPoint()); |
| 135 | 145 |
| 136 bool occupiesSpace = candidateRect.width() > 0 && candidateRect.height() > 0
; | 146 bool occupiesSpace = candidateRect.width() > 0 && candidateRect.height() > 0
; |
| 137 if (occupiesSpace && visibleRect.intersects(candidateRect)) { | 147 if (occupiesSpace && visibleRect.intersects(candidateRect)) { |
| 138 return ExamineResult( | 148 return ExamineResult( |
| 139 visibleRect.contains(candidateRect) ? Return : Constrain, | 149 visibleRect.contains(candidateRect) ? Return : Constrain, |
| 140 cornerFromCandidateRect(candidate)); | 150 cornerFromCandidateRect(candidate)); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 return; | 196 return; |
| 187 | 197 |
| 188 m_current.m_anchorObject->setIsScrollAnchorObject(); | 198 m_current.m_anchorObject->setIsScrollAnchorObject(); |
| 189 m_current.m_savedRelativeOffset = computeRelativeOffset( | 199 m_current.m_savedRelativeOffset = computeRelativeOffset( |
| 190 m_current.m_anchorObject, m_scroller, m_current.m_corner); | 200 m_current.m_anchorObject, m_scroller, m_current.m_corner); |
| 191 | 201 |
| 192 if (m_lastAdjusted) { | 202 if (m_lastAdjusted) { |
| 193 // We need to update m_lastAdjusted.m_savedRelativeOffset, since it is | 203 // We need to update m_lastAdjusted.m_savedRelativeOffset, since it is |
| 194 // relative to the visible rect and the user may have scrolled since the | 204 // relative to the visible rect and the user may have scrolled since the |
| 195 // last adjustment. | 205 // last adjustment. |
| 196 if (!candidateMovesWithScroller(m_lastAdjusted.m_anchorObject, m_scrolle
r)) { | 206 if (!candidateMayMoveWithScroller(m_lastAdjusted.m_anchorObject, m_scrol
ler)) { |
| 197 m_lastAdjusted.clear(); | 207 m_lastAdjusted.clear(); |
| 198 } else if (m_lastAdjusted.m_anchorObject == m_current.m_anchorObject | 208 } else if (m_lastAdjusted.m_anchorObject == m_current.m_anchorObject |
| 199 && m_lastAdjusted.m_corner == m_current.m_corner) { | 209 && m_lastAdjusted.m_corner == m_current.m_corner) { |
| 200 m_lastAdjusted.m_savedRelativeOffset = m_current.m_savedRelativeOffs
et; | 210 m_lastAdjusted.m_savedRelativeOffset = m_current.m_savedRelativeOffs
et; |
| 201 } else { | 211 } else { |
| 202 m_lastAdjusted.m_savedRelativeOffset = computeRelativeOffset( | 212 m_lastAdjusted.m_savedRelativeOffset = computeRelativeOffset( |
| 203 m_lastAdjusted.m_anchorObject, m_scroller, m_lastAdjusted.m_corn
er); | 213 m_lastAdjusted.m_anchorObject, m_scroller, m_lastAdjusted.m_corn
er); |
| 204 } | 214 } |
| 205 } | 215 } |
| 206 } | 216 } |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 | 294 |
| 285 void ScrollAnchor::notifyRemoved(LayoutObject* layoutObject) | 295 void ScrollAnchor::notifyRemoved(LayoutObject* layoutObject) |
| 286 { | 296 { |
| 287 if (m_current.m_anchorObject == layoutObject) | 297 if (m_current.m_anchorObject == layoutObject) |
| 288 m_current.clear(); | 298 m_current.clear(); |
| 289 if (m_lastAdjusted.m_anchorObject == layoutObject) | 299 if (m_lastAdjusted.m_anchorObject == layoutObject) |
| 290 m_lastAdjusted.clear(); | 300 m_lastAdjusted.clear(); |
| 291 } | 301 } |
| 292 | 302 |
| 293 } // namespace blink | 303 } // namespace blink |
| OLD | NEW |