File: StickyScrollContainer.h

package info (click to toggle)
firefox 141.0.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,550,616 kB
  • sloc: cpp: 7,426,508; javascript: 6,367,238; ansic: 3,707,354; python: 1,368,984; xml: 623,983; asm: 426,916; java: 184,324; sh: 64,488; makefile: 19,203; objc: 13,059; perl: 12,955; yacc: 4,583; cs: 3,846; pascal: 3,352; lex: 1,720; ruby: 1,071; exp: 762; php: 436; lisp: 258; awk: 247; sql: 66; sed: 54; csh: 10
file content (118 lines) | stat: -rw-r--r-- 3,816 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/**
 * compute sticky positioning, both during reflow and when the scrolling
 * container scrolls
 */

#ifndef StickyScrollContainer_h
#define StickyScrollContainer_h

#include "mozilla/DepthOrderedFrameList.h"
#include "nsIScrollPositionListener.h"
#include "nsPoint.h"
#include "nsRectAbsolute.h"
#include "nsTArray.h"

struct nsRect;
class nsIFrame;

namespace mozilla {

class ScrollContainerFrame;

class StickyScrollContainer final : public nsIScrollPositionListener {
 public:
  /**
   * Find (and create if necessary) the StickyScrollContainer associated with
   * the scroll container of the given frame, if a scroll container exists.
   */
  static StickyScrollContainer* GetStickyScrollContainerForFrame(
      nsIFrame* aFrame);

  /**
   * Find the StickyScrollContainer associated with the given scroll frame,
   * if it exists.
   */
  static StickyScrollContainer* GetStickyScrollContainerForScrollFrame(
      nsIFrame* aScrollFrame);

  void AddFrame(nsIFrame* aFrame) { mFrames.Add(aFrame); }
  void RemoveFrame(nsIFrame* aFrame) { mFrames.Remove(aFrame); }

  ScrollContainerFrame* ScrollContainer() const {
    return mScrollContainerFrame;
  }

  // Compute the offsets for a sticky position element
  static void ComputeStickyOffsets(nsIFrame* aFrame);

  /**
   * Compute the position of a sticky positioned frame, based on information
   * stored in its properties along with our scroll frame and scroll position.
   */
  nsPoint ComputePosition(nsIFrame* aFrame) const;

  /**
   * Compute where a frame should not scroll with the page, represented by the
   * difference of two rectangles.
   */
  void GetScrollRanges(nsIFrame* aFrame, nsRectAbsolute* aOuter,
                       nsRectAbsolute* aInner) const;

  /**
   * Compute and set the position of a frame and its following continuations.
   */
  void PositionContinuations(nsIFrame* aFrame);

  /**
   * Compute and set the position of all sticky frames, given the current
   * scroll position of the scroll frame. If not in reflow, aSubtreeRoot should
   * be null; otherwise, overflow-area updates will be limited to not affect
   * aSubtreeRoot or its ancestors.
   */
  void UpdatePositions(nsPoint aScrollPosition, nsIFrame* aSubtreeRoot);

  // nsIScrollPositionListener
  void ScrollPositionWillChange(nscoord aX, nscoord aY) override;
  void ScrollPositionDidChange(nscoord aX, nscoord aY) override;

  ~StickyScrollContainer();

  const DepthOrderedFrameList& GetFrames() const { return mFrames; }

  /**
   * Returns true if the frame is "stuck" in the y direction, ie it's acting
   * like fixed position. aFrame should be in GetFrames().
   */
  bool IsStuckInYDirection(nsIFrame* aFrame) const;

  /**
   * Calls FrameNeedsReflow on all sticky position children.
   */
  void MarkFramesForReflow();

 private:
  explicit StickyScrollContainer(ScrollContainerFrame* aScrollContainerFrame);

  /**
   * Compute two rectangles that determine sticky positioning: |aStick|, based
   * on the scroll container, and |aContain|, based on the containing block.
   * Sticky positioning keeps the frame position (its upper-left corner) always
   * within |aContain| and secondarily within |aStick|.
   */
  void ComputeStickyLimits(nsIFrame* aFrame, nsRect* aStick,
                           nsRect* aContain) const;

  ScrollContainerFrame* const mScrollContainerFrame;
  DepthOrderedFrameList mFrames;
  nsPoint mScrollPosition;
};

}  // namespace mozilla

#endif /* StickyScrollContainer_h */