StickyScrollContainer.h (3570B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /** 8 * compute sticky positioning, both during reflow and when the scrolling 9 * container scrolls 10 */ 11 12 #ifndef StickyScrollContainer_h 13 #define StickyScrollContainer_h 14 15 #include "mozilla/DepthOrderedFrameList.h" 16 #include "nsPoint.h" 17 #include "nsRectAbsolute.h" 18 #include "nsTArray.h" 19 20 struct nsRect; 21 class nsIFrame; 22 23 namespace mozilla { 24 25 class ScrollContainerFrame; 26 27 class StickyScrollContainer final { 28 public: 29 /** 30 * Find (and create if necessary) the StickyScrollContainer associated with 31 * the scroll container of the given frame, if a scroll container exists. 32 */ 33 static StickyScrollContainer* GetOrCreateForFrame(nsIFrame*); 34 35 void AddFrame(nsIFrame* aFrame) { mFrames.Add(aFrame); } 36 void RemoveFrame(nsIFrame* aFrame) { mFrames.Remove(aFrame); } 37 38 ScrollContainerFrame* ScrollContainer() const { 39 return mScrollContainerFrame; 40 } 41 42 // Compute the offsets for a sticky position element 43 static void ComputeStickyOffsets(nsIFrame* aFrame); 44 45 /** 46 * Compute the position of a sticky positioned frame, based on information 47 * stored in its properties along with our scroll frame and scroll position. 48 */ 49 nsPoint ComputePosition(nsIFrame* aFrame) const; 50 51 /** 52 * Compute where a frame should not scroll with the page, represented by the 53 * difference of two rectangles. 54 */ 55 void GetScrollRanges(nsIFrame* aFrame, nsRectAbsolute* aOuter, 56 nsRectAbsolute* aInner) const; 57 58 /** 59 * Compute and set the position of a frame and its following continuations. 60 */ 61 void PositionContinuations(nsIFrame* aFrame); 62 63 /** 64 * Compute and set the position of all sticky frames, given the current 65 * scroll position of the scroll frame. If not in reflow, aSubtreeRoot should 66 * be null; otherwise, overflow-area updates will be limited to not affect 67 * aSubtreeRoot or its ancestors. 68 */ 69 void UpdatePositions(nsPoint aScrollPosition, nsIFrame* aSubtreeRoot); 70 71 void ScrollPositionDidChange(const nsPoint&); 72 73 ~StickyScrollContainer(); 74 75 const DepthOrderedFrameList& GetFrames() const { return mFrames; } 76 77 /** 78 * Returns true if the frame is "stuck" in the y direction, ie it's acting 79 * like fixed position. aFrame should be in GetFrames(). 80 */ 81 bool IsStuckInYDirection(nsIFrame* aFrame) const; 82 83 /** 84 * Calls FrameNeedsReflow on all sticky position children. 85 */ 86 void MarkFramesForReflow(); 87 88 void SetShouldFlatten(bool aShouldFlatten) { 89 mShouldFlatten = aShouldFlatten; 90 } 91 bool ShouldFlattenAway() const { return mShouldFlatten; } 92 93 explicit StickyScrollContainer(ScrollContainerFrame* aScrollContainerFrame); 94 95 private: 96 /** 97 * Compute two rectangles that determine sticky positioning: |aStick|, based 98 * on the scroll container, and |aContain|, based on the containing block. 99 * Sticky positioning keeps the frame position (its upper-left corner) always 100 * within |aContain| and secondarily within |aStick|. 101 */ 102 void ComputeStickyLimits(nsIFrame* aFrame, nsRect* aStick, 103 nsRect* aContain) const; 104 105 ScrollContainerFrame* const mScrollContainerFrame; 106 DepthOrderedFrameList mFrames; 107 nsPoint mScrollPosition; 108 bool mShouldFlatten = false; 109 }; 110 111 } // namespace mozilla 112 113 #endif /* StickyScrollContainer_h */