| 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 LayoutBox* box = scroller->layoutBox(); | 50 LayoutBox* box = scroller->layoutBox(); |
| 51 DCHECK(box); | 51 DCHECK(box); |
| 52 return box; | 52 return box; |
| 53 } | 53 } |
| 54 | 54 |
| 55 static LayoutBoxItem scrollerLayoutBoxItem(const ScrollableArea* scroller) | 55 static LayoutBoxItem scrollerLayoutBoxItem(const ScrollableArea* scroller) |
| 56 { | 56 { |
| 57 return LayoutBoxItem(scrollerLayoutBox(scroller)); | 57 return LayoutBoxItem(scrollerLayoutBox(scroller)); |
| 58 } | 58 } |
| 59 | 59 |
| 60 static Corner cornerFromCandidateRect(const LayoutObject* layoutObject) | 60 static Corner cornerToAnchor(const ScrollableArea* scroller) |
| 61 { | 61 { |
| 62 ASSERT(layoutObject); | 62 const ComputedStyle* style = scrollerLayoutBox(scroller)->style(); |
| 63 if (layoutObject->style()->isFlippedBlocksWritingMode() | 63 if (style->isFlippedBlocksWritingMode() || !style->isLeftToRightDirection()) |
| 64 || !layoutObject->style()->isLeftToRightDirection()) | |
| 65 return Corner::TopRight; | 64 return Corner::TopRight; |
| 66 return Corner::TopLeft; | 65 return Corner::TopLeft; |
| 67 } | 66 } |
| 68 | 67 |
| 69 static LayoutPoint cornerPointOfRect(LayoutRect rect, Corner whichCorner) | 68 static LayoutPoint cornerPointOfRect(LayoutRect rect, Corner whichCorner) |
| 70 { | 69 { |
| 71 switch (whichCorner) { | 70 switch (whichCorner) { |
| 72 case Corner::TopLeft: return rect.minXMinYCorner(); | 71 case Corner::TopLeft: return rect.minXMinYCorner(); |
| 73 case Corner::TopRight: return rect.maxXMinYCorner(); | 72 case Corner::TopRight: return rect.maxXMinYCorner(); |
| 74 } | 73 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 if (candidate->style()->overflowAnchor() == AnchorNone) | 152 if (candidate->style()->overflowAnchor() == AnchorNone) |
| 154 return ExamineResult(Skip); | 153 return ExamineResult(Skip); |
| 155 | 154 |
| 156 LayoutRect candidateRect = relativeBounds(candidate, m_scroller); | 155 LayoutRect candidateRect = relativeBounds(candidate, m_scroller); |
| 157 LayoutRect visibleRect = scrollerLayoutBoxItem(m_scroller).overflowClipRect(
LayoutPoint()); | 156 LayoutRect visibleRect = scrollerLayoutBoxItem(m_scroller).overflowClipRect(
LayoutPoint()); |
| 158 | 157 |
| 159 bool occupiesSpace = candidateRect.width() > 0 && candidateRect.height() > 0
; | 158 bool occupiesSpace = candidateRect.width() > 0 && candidateRect.height() > 0
; |
| 160 if (occupiesSpace && visibleRect.intersects(candidateRect)) { | 159 if (occupiesSpace && visibleRect.intersects(candidateRect)) { |
| 161 return ExamineResult( | 160 return ExamineResult( |
| 162 visibleRect.contains(candidateRect) ? Return : Constrain, | 161 visibleRect.contains(candidateRect) ? Return : Constrain, |
| 163 cornerFromCandidateRect(candidate)); | 162 cornerToAnchor(m_scroller)); |
| 164 } else { | 163 } else { |
| 165 return ExamineResult(Skip); | 164 return ExamineResult(Skip); |
| 166 } | 165 } |
| 167 } | 166 } |
| 168 | 167 |
| 169 void ScrollAnchor::findAnchor() | 168 void ScrollAnchor::findAnchor() |
| 170 { | 169 { |
| 171 TRACE_EVENT0("blink", "ScrollAnchor::findAnchor"); | 170 TRACE_EVENT0("blink", "ScrollAnchor::findAnchor"); |
| 172 SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Layout.ScrollAnchor.TimeToFindAnchor"); | 171 SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Layout.ScrollAnchor.TimeToFindAnchor"); |
| 173 | 172 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 current = current->parent(); | 210 current = current->parent(); |
| 212 } | 211 } |
| 213 } | 212 } |
| 214 | 213 |
| 215 void ScrollAnchor::save() | 214 void ScrollAnchor::save() |
| 216 { | 215 { |
| 217 if (m_saved) | 216 if (m_saved) |
| 218 return; | 217 return; |
| 219 m_saved = true; | 218 m_saved = true; |
| 220 DCHECK(m_scroller); | 219 DCHECK(m_scroller); |
| 221 if (m_scroller->scrollPosition() == IntPoint::zero()) { | 220 |
| 221 ScrollbarOrientation blockLayoutAxis = |
| 222 scrollerLayoutBox(m_scroller)->isHorizontalWritingMode() ? VerticalScrol
lbar : HorizontalScrollbar; |
| 223 if (m_scroller->scrollPosition(blockLayoutAxis) == 0) { |
| 222 clear(); | 224 clear(); |
| 223 return; | 225 return; |
| 224 } | 226 } |
| 225 | 227 |
| 226 if (!m_anchorObject) { | 228 if (!m_anchorObject) { |
| 227 findAnchor(); | 229 findAnchor(); |
| 228 if (!m_anchorObject) | 230 if (!m_anchorObject) |
| 229 return; | 231 return; |
| 230 | 232 |
| 231 m_anchorObject->setIsScrollAnchorObject(); | 233 m_anchorObject->setIsScrollAnchorObject(); |
| 232 m_savedRelativeOffset = computeRelativeOffset( | 234 m_savedRelativeOffset = computeRelativeOffset( |
| 233 m_anchorObject, m_scroller, m_corner); | 235 m_anchorObject, m_scroller, m_corner); |
| 234 } | 236 } |
| 235 | 237 |
| 236 // Note that we must compute this during save() since the scroller's | 238 // Note that we must compute this during save() since the scroller's |
| 237 // descendants have finished layout (and had the bit cleared) by the | 239 // descendants have finished layout (and had the bit cleared) by the |
| 238 // time restore() is called. | 240 // time restore() is called. |
| 239 m_scrollAnchorDisablingStyleChanged = computeScrollAnchorDisablingStyleChang
ed(); | 241 m_scrollAnchorDisablingStyleChanged = computeScrollAnchorDisablingStyleChang
ed(); |
| 240 } | 242 } |
| 241 | 243 |
| 242 IntSize ScrollAnchor::computeAdjustment() const | 244 IntSize ScrollAnchor::computeAdjustment() const |
| 243 { | 245 { |
| 244 // The anchor node can report fractional positions, but it is DIP-snapped wh
en | 246 // The anchor node can report fractional positions, but it is DIP-snapped wh
en |
| 245 // painting (crbug.com/610805), so we must round the offsets to determine th
e | 247 // painting (crbug.com/610805), so we must round the offsets to determine th
e |
| 246 // visual delta. If we scroll by the delta in LayoutUnits, the snapping of t
he | 248 // visual delta. If we scroll by the delta in LayoutUnits, the snapping of t
he |
| 247 // anchor node may round differently from the snapping of the scroll positio
n. | 249 // anchor node may round differently from the snapping of the scroll positio
n. |
| 248 // (For example, anchor moving from 2.4px -> 2.6px is really 2px -> 3px, so
we | 250 // (For example, anchor moving from 2.4px -> 2.6px is really 2px -> 3px, so
we |
| 249 // should scroll by 1px instead of 0.2px.) This is true regardless of whethe
r | 251 // should scroll by 1px instead of 0.2px.) This is true regardless of whethe
r |
| 250 // the ScrollableArea actually uses fractional scroll positions. | 252 // the ScrollableArea actually uses fractional scroll positions. |
| 251 return roundedIntSize(computeRelativeOffset(m_anchorObject, m_scroller, m_co
rner)) - | 253 IntSize delta = roundedIntSize(computeRelativeOffset(m_anchorObject, m_scrol
ler, m_corner)) - |
| 252 roundedIntSize(m_savedRelativeOffset); | 254 roundedIntSize(m_savedRelativeOffset); |
| 255 |
| 256 // Only adjust on the block layout axis. |
| 257 if (scrollerLayoutBox(m_scroller)->isHorizontalWritingMode()) |
| 258 delta.setWidth(0); |
| 259 else |
| 260 delta.setHeight(0); |
| 261 return delta; |
| 253 } | 262 } |
| 254 | 263 |
| 255 void ScrollAnchor::restore() | 264 void ScrollAnchor::restore() |
| 256 { | 265 { |
| 257 if (!m_saved) | 266 if (!m_saved) |
| 258 return; | 267 return; |
| 259 m_saved = false; | 268 m_saved = false; |
| 260 DCHECK(m_scroller); | 269 DCHECK(m_scroller); |
| 261 if (!m_anchorObject) | 270 if (!m_anchorObject) |
| 262 return; | 271 return; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 return m_anchorObject == layoutObject; | 309 return m_anchorObject == layoutObject; |
| 301 } | 310 } |
| 302 | 311 |
| 303 void ScrollAnchor::notifyRemoved(LayoutObject* layoutObject) | 312 void ScrollAnchor::notifyRemoved(LayoutObject* layoutObject) |
| 304 { | 313 { |
| 305 if (m_anchorObject == layoutObject) | 314 if (m_anchorObject == layoutObject) |
| 306 clear(); | 315 clear(); |
| 307 } | 316 } |
| 308 | 317 |
| 309 } // namespace blink | 318 } // namespace blink |
| OLD | NEW |