Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=2 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 "nsPoint.h"
16 : #include "nsTArray.h"
17 : #include "nsIScrollPositionListener.h"
18 :
19 : struct nsRect;
20 : class nsIFrame;
21 : class nsIScrollableFrame;
22 :
23 : namespace mozilla {
24 :
25 : class StickyScrollContainer final : public nsIScrollPositionListener
26 : {
27 : public:
28 : /**
29 : * Find (and create if necessary) the StickyScrollContainer associated with
30 : * the scroll container of the given frame, if a scroll container exists.
31 : */
32 : static StickyScrollContainer* GetStickyScrollContainerForFrame(nsIFrame* aFrame);
33 :
34 : /**
35 : * Find the StickyScrollContainer associated with the given scroll frame,
36 : * if it exists.
37 : */
38 : static StickyScrollContainer* GetStickyScrollContainerForScrollFrame(nsIFrame* aScrollFrame);
39 :
40 : /**
41 : * aFrame may have moved into or out of a scroll frame's frame subtree.
42 : */
43 : static void NotifyReparentedFrameAcrossScrollFrameBoundary(nsIFrame* aFrame,
44 : nsIFrame* aOldParent);
45 :
46 0 : void AddFrame(nsIFrame* aFrame) {
47 0 : mFrames.AppendElement(aFrame);
48 0 : }
49 0 : void RemoveFrame(nsIFrame* aFrame) {
50 0 : mFrames.RemoveElement(aFrame);
51 0 : }
52 :
53 0 : nsIScrollableFrame* ScrollFrame() const {
54 0 : return mScrollFrame;
55 : }
56 :
57 : // Compute the offsets for a sticky position element
58 : static void ComputeStickyOffsets(nsIFrame* aFrame);
59 :
60 : /**
61 : * Compute the position of a sticky positioned frame, based on information
62 : * stored in its properties along with our scroll frame and scroll position.
63 : */
64 : nsPoint ComputePosition(nsIFrame* aFrame) const;
65 :
66 : /**
67 : * Compute where a frame should not scroll with the page, represented by the
68 : * difference of two rectangles.
69 : */
70 : void GetScrollRanges(nsIFrame* aFrame, nsRect* aOuter, nsRect* aInner) const;
71 :
72 : /**
73 : * Compute and set the position of a frame and its following continuations.
74 : */
75 : void PositionContinuations(nsIFrame* aFrame);
76 :
77 : /**
78 : * Compute and set the position of all sticky frames, given the current
79 : * scroll position of the scroll frame. If not in reflow, aSubtreeRoot should
80 : * be null; otherwise, overflow-area updates will be limited to not affect
81 : * aSubtreeRoot or its ancestors.
82 : */
83 : void UpdatePositions(nsPoint aScrollPosition, nsIFrame* aSubtreeRoot);
84 :
85 : // nsIScrollPositionListener
86 : virtual void ScrollPositionWillChange(nscoord aX, nscoord aY) override;
87 : virtual void ScrollPositionDidChange(nscoord aX, nscoord aY) override;
88 :
89 : ~StickyScrollContainer();
90 :
91 : private:
92 : explicit StickyScrollContainer(nsIScrollableFrame* aScrollFrame);
93 :
94 : /**
95 : * Compute two rectangles that determine sticky positioning: |aStick|, based
96 : * on the scroll container, and |aContain|, based on the containing block.
97 : * Sticky positioning keeps the frame position (its upper-left corner) always
98 : * within |aContain| and secondarily within |aStick|.
99 : */
100 : void ComputeStickyLimits(nsIFrame* aFrame, nsRect* aStick,
101 : nsRect* aContain) const;
102 :
103 : nsIScrollableFrame* const mScrollFrame;
104 : nsTArray<nsIFrame*> mFrames;
105 : nsPoint mScrollPosition;
106 : };
107 :
108 : } // namespace mozilla
109 :
110 : #endif /* StickyScrollContainer_h */
|