| 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 #ifndef ScrollAnchor_h | 5 #ifndef ScrollAnchor_h |
| 6 #define ScrollAnchor_h | 6 #define ScrollAnchor_h |
| 7 | 7 |
| 8 #include "core/CoreExport.h" | 8 #include "core/CoreExport.h" |
| 9 #include "platform/geometry/LayoutPoint.h" | 9 #include "platform/geometry/LayoutPoint.h" |
| 10 #include "platform/heap/Handle.h" | 10 #include "platform/heap/Handle.h" |
| 11 | 11 |
| 12 namespace blink { | 12 namespace blink { |
| 13 | 13 |
| 14 class LayoutObject; | 14 class LayoutObject; |
| 15 class ScrollableArea; | 15 class ScrollableArea; |
| 16 | 16 |
| 17 // Scrolls to compensate for layout movements (bit.ly/scroll-anchoring). | 17 // Scrolls to compensate for layout movements (bit.ly/scroll-anchoring). |
| 18 class CORE_EXPORT ScrollAnchor final { | 18 class CORE_EXPORT ScrollAnchor final { |
| 19 DISALLOW_NEW(); | 19 DISALLOW_NEW(); |
| 20 | 20 |
| 21 public: | 21 public: |
| 22 ScrollAnchor(ScrollableArea*); | 22 ScrollAnchor(ScrollableArea*); |
| 23 ~ScrollAnchor(); | 23 ~ScrollAnchor(); |
| 24 | 24 |
| 25 // The LayoutObject we are currently anchored to. Lazily computed during | 25 // The LayoutObject we are currently anchored to. Lazily computed during |
| 26 // save() and cached until the next call to clear(). | 26 // save() and cached until the next call to clear(). |
| 27 LayoutObject* anchorObject() const { return m_anchorObject; } | 27 LayoutObject* anchorObject() const { return m_current.m_anchorObject; } |
| 28 | 28 |
| 29 // Invalidates the anchor. | 29 // Indicates that the next save() should compute a new anchor. (In certain |
| 30 // cases the previous anchor will be reused; see comments in restore.) |
| 30 void clear(); | 31 void clear(); |
| 31 | 32 |
| 32 // Records the anchor's location in relation to the scroller. Should be | 33 // Records the anchor's location in relation to the scroller. Should be |
| 33 // called when the scroller is about to be laid out. | 34 // called when the scroller is about to be laid out. |
| 34 void save(); | 35 void save(); |
| 35 | 36 |
| 36 // Scrolls to compensate for any change in the anchor's relative location | 37 // Scrolls to compensate for any change in the anchor's relative location |
| 37 // since the most recent call to save(). Should be called immediately after | 38 // since the most recent call to save(). Should be called immediately after |
| 38 // the scroller has been laid out. | 39 // the scroller has been laid out. |
| 39 void restore(); | 40 void restore(); |
| 40 | 41 |
| 41 enum class Corner { | 42 enum class Corner { |
| 42 TopLeft = 0, | 43 TopLeft = 0, |
| 43 TopRight, | 44 TopRight, |
| 44 }; | 45 }; |
| 45 // Which corner of the anchor object we are currently anchored to. | 46 // Which corner of the anchor object we are currently anchored to. |
| 46 // Only meaningful if anchorObject() is non-null. | 47 // Only meaningful if anchorObject() is non-null. |
| 47 Corner corner() const { return m_corner; } | 48 Corner corner() const { return m_current.m_corner; } |
| 49 |
| 50 // Checks if we hold any references to the specified object. |
| 51 bool refersTo(const LayoutObject*) const; |
| 52 |
| 53 // Notifies us that an object will be removed from the layout tree. |
| 54 void notifyRemoved(LayoutObject*); |
| 48 | 55 |
| 49 DEFINE_INLINE_TRACE() { visitor->trace(m_scroller); } | 56 DEFINE_INLINE_TRACE() { visitor->trace(m_scroller); } |
| 50 | 57 |
| 51 private: | 58 private: |
| 52 void findAnchor(); | 59 void findAnchor(); |
| 53 | 60 |
| 54 enum WalkStatus { | 61 enum WalkStatus { |
| 55 Skip = 0, | 62 Skip = 0, |
| 56 Constrain, | 63 Constrain, |
| 57 Continue, | 64 Continue, |
| 58 Return | 65 Return |
| 59 }; | 66 }; |
| 60 struct ExamineResult { | 67 struct ExamineResult { |
| 61 ExamineResult(WalkStatus s) | 68 ExamineResult(WalkStatus s) |
| 62 : status(s) | 69 : status(s) |
| 63 , viable(false) | 70 , viable(false) |
| 64 , corner(Corner::TopLeft) {} | 71 , corner(Corner::TopLeft) {} |
| 65 | 72 |
| 66 ExamineResult(WalkStatus s, Corner c) | 73 ExamineResult(WalkStatus s, Corner c) |
| 67 : status(s) | 74 : status(s) |
| 68 , viable(true) | 75 , viable(true) |
| 69 , corner(c) {} | 76 , corner(c) {} |
| 70 | 77 |
| 71 WalkStatus status; | 78 WalkStatus status; |
| 72 bool viable; | 79 bool viable; |
| 73 Corner corner; | 80 Corner corner; |
| 74 }; | 81 }; |
| 75 ExamineResult examine(const LayoutObject*) const; | 82 ExamineResult examine(const LayoutObject*) const; |
| 76 | 83 |
| 84 struct AnchorPoint { |
| 85 AnchorPoint() |
| 86 : m_anchorObject(nullptr) |
| 87 , m_corner(Corner::TopLeft) {} |
| 88 |
| 89 AnchorPoint(LayoutObject* anchorObject, Corner corner) |
| 90 : m_anchorObject(anchorObject) |
| 91 , m_corner(corner) {} |
| 92 |
| 93 explicit operator bool() const { return m_anchorObject; } |
| 94 |
| 95 void clear(); |
| 96 |
| 97 // The LayoutObject we should anchor to. |
| 98 LayoutObject* m_anchorObject; |
| 99 |
| 100 // Which corner of m_anchorObject's bounding box to anchor to. |
| 101 Corner m_corner; |
| 102 |
| 103 // Location of m_layoutObject relative to scroller at time of save(). |
| 104 LayoutPoint m_savedRelativeOffset; |
| 105 }; |
| 106 IntSize computeAdjustment(const AnchorPoint&) const; |
| 107 void adjust(IntSize); |
| 108 |
| 77 // The scroller that owns and is adjusted by this ScrollAnchor. | 109 // The scroller that owns and is adjusted by this ScrollAnchor. |
| 78 Member<ScrollableArea> m_scroller; | 110 Member<ScrollableArea> m_scroller; |
| 79 | 111 |
| 80 // The LayoutObject we should anchor to. Lazily computed. | 112 // The current anchor point. Lazily computed. |
| 81 LayoutObject* m_anchorObject; | 113 AnchorPoint m_current; |
| 82 | 114 |
| 83 // Which corner of m_anchorObject's bounding box to anchor to. | 115 // The anchor point that was used for the most recent non-zero adjustment. |
| 84 Corner m_corner; | 116 AnchorPoint m_lastAdjusted; |
| 85 | 117 |
| 86 // Location of m_layoutObject relative to scroller at time of save(). | 118 // The size of the most recent non-zero adjustment. |
| 87 LayoutPoint m_savedRelativeOffset; | 119 IntSize m_lastAdjustment; |
| 120 |
| 121 // True iff the last adjustment was the exact opposite of the one before it. |
| 122 // A bounce suggests a circular interaction with a scroll event handler. |
| 123 bool m_hasBounced; |
| 88 }; | 124 }; |
| 89 | 125 |
| 90 } // namespace blink | 126 } // namespace blink |
| 91 | 127 |
| 92 #endif // ScrollAnchor_h | 128 #endif // ScrollAnchor_h |
| OLD | NEW |