summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/src/OverscrollHandoffState.h
blob: 173d6bddde9ddb6e06bf4238b9cfe9df41b0ce48 (plain)
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et 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/. */

#ifndef mozilla_layers_OverscrollHandoffChain_h
#define mozilla_layers_OverscrollHandoffChain_h

#include <vector>
#include "mozilla/RefPtr.h"   // for RefPtr
#include "nsISupportsImpl.h"  // for NS_INLINE_DECL_THREADSAFE_REFCOUNTING
#include "APZUtils.h"         // for CancelAnimationFlags
#include "Layers.h"           // for Layer::ScrollDirection
#include "Units.h"            // for ScreenPoint

namespace mozilla {

class InputData;

namespace layers {

class AsyncPanZoomController;

/**
 * This class represents the chain of APZCs along which overscroll is handed off.
 * It is created by APZCTreeManager by starting from an initial APZC which is
 * the target for input events, and following the scroll parent ID links (often
 * but not always corresponding to parent pointers in the APZC tree), then
 * adjusting for scrollgrab.
 */
class OverscrollHandoffChain
{
protected:
  // Reference-counted classes cannot have public destructors.
  ~OverscrollHandoffChain();
public:
  // Threadsafe so that the controller and compositor threads can both maintain
  // nsRefPtrs to the same handoff chain.
  // Mutable so that we can pass around the class by
  // RefPtr<const OverscrollHandoffChain> and thus enforce that, once built,
  // the chain is not modified.
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OverscrollHandoffChain)

  /*
   * Methods for building the handoff chain.
   * These should be used only by AsyncPanZoomController::BuildOverscrollHandoffChain().
   */
  void Add(AsyncPanZoomController* aApzc);
  void SortByScrollPriority();

  /*
   * Methods for accessing the handoff chain.
   */
  uint32_t Length() const { return mChain.size(); }
  const RefPtr<AsyncPanZoomController>& GetApzcAtIndex(uint32_t aIndex) const;
  // Returns Length() if |aApzc| is not on this chain.
  uint32_t IndexOf(const AsyncPanZoomController* aApzc) const;

  /*
   * Convenience methods for performing operations on APZCs in the chain.
   */

  // Flush repaints all the way up the chain.
  void FlushRepaints() const;

  // Cancel animations all the way up the chain.
  void CancelAnimations(CancelAnimationFlags aFlags = Default) const;

  // Clear overscroll all the way up the chain.
  void ClearOverscroll() const;

  // Snap back the APZC that is overscrolled on the subset of the chain from
  // |aStart| onwards, if any.
  void SnapBackOverscrolledApzc(const AsyncPanZoomController* aStart) const;

  // Determine whether the given APZC, or any APZC further in the chain,
  // has room to be panned.
  bool CanBePanned(const AsyncPanZoomController* aApzc) const;

  // Determine whether the given APZC, or any APZC further in the chain,
  // can scroll in the given direction.
  bool CanScrollInDirection(const AsyncPanZoomController* aApzc,
                            Layer::ScrollDirection aDirection) const;

  // Determine whether any APZC along this handoff chain is overscrolled.
  bool HasOverscrolledApzc() const;

  // Determine whether any APZC along this handoff chain has been flung fast.
  bool HasFastFlungApzc() const;

  RefPtr<AsyncPanZoomController> FindFirstScrollable(const InputData& aInput) const;

private:
  std::vector<RefPtr<AsyncPanZoomController>> mChain;

  typedef void (AsyncPanZoomController::*APZCMethod)();
  typedef bool (AsyncPanZoomController::*APZCPredicate)() const;
  void ForEachApzc(APZCMethod aMethod) const;
  bool AnyApzc(APZCPredicate aPredicate) const;
};

/**
 * This class groups the state maintained during overscroll handoff.
 */
struct OverscrollHandoffState {
  OverscrollHandoffState(const OverscrollHandoffChain& aChain,
                         const ScreenPoint& aPanDistance,
                         ScrollSource aScrollSource)
    : mChain(aChain),
      mChainIndex(0),
      mPanDistance(aPanDistance),
      mScrollSource(aScrollSource)
  {}

  // The chain of APZCs along which we hand off scroll.
  // This is const to indicate that the chain does not change over the
  // course of handoff.
  const OverscrollHandoffChain& mChain;

  // The index of the APZC in the chain that we are currently giving scroll to.
  // This is non-const to indicate that this changes over the course of handoff.
  uint32_t mChainIndex;

  // The total distance since touch-start of the pan that triggered the
  // handoff. This is const to indicate that it does not change over the
  // course of handoff.
  // The x/y components of this are non-negative.
  const ScreenPoint mPanDistance;

  ScrollSource mScrollSource;
};

/*
 * This class groups the state maintained during fling handoff.
 */
struct FlingHandoffState {
  // The velocity of the fling being handed off.
  ParentLayerPoint mVelocity;

  // The chain of APZCs along which we hand off the fling.
  // Unlike in OverscrollHandoffState, this is stored by RefPtr because
  // otherwise it may not stay alive for the entire handoff.
  RefPtr<const OverscrollHandoffChain> mChain;

  // Whether handoff has happened by this point, or we're still process
  // the original fling.
  bool mIsHandoff;

  // The single APZC that was scrolled by the pan that started this fling.
  // The fling is only allowed to scroll this APZC, too.
  // Used only if immediate scroll handoff is disallowed.
  RefPtr<const AsyncPanZoomController> mScrolledApzc;
};

} // namespace layers
} // namespace mozilla

#endif /* mozilla_layers_OverscrollHandoffChain_h */