Source code

Revision control

Other Tools

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
#include "OverscrollHandoffState.h"
8
9
#include <algorithm> // for std::stable_sort
10
#include "mozilla/Assertions.h"
11
#include "AsyncPanZoomController.h"
12
13
namespace mozilla {
14
namespace layers {
15
16
OverscrollHandoffChain::~OverscrollHandoffChain() = default;
17
18
void OverscrollHandoffChain::Add(AsyncPanZoomController* aApzc) {
19
mChain.push_back(aApzc);
20
}
21
22
struct CompareByScrollPriority {
23
bool operator()(const RefPtr<AsyncPanZoomController>& a,
24
const RefPtr<AsyncPanZoomController>& b) const {
25
return a->HasScrollgrab() && !b->HasScrollgrab();
26
}
27
};
28
29
void OverscrollHandoffChain::SortByScrollPriority() {
30
// The sorting being stable ensures that the relative order between
31
// non-scrollgrabbing APZCs remains child -> parent.
32
// (The relative order between scrollgrabbing APZCs will also remain
33
// child -> parent, though that's just an artefact of the implementation
34
// and users of 'scrollgrab' should not rely on this.)
35
std::stable_sort(mChain.begin(), mChain.end(), CompareByScrollPriority());
36
}
37
38
const RefPtr<AsyncPanZoomController>& OverscrollHandoffChain::GetApzcAtIndex(
39
uint32_t aIndex) const {
40
MOZ_ASSERT(aIndex < Length());
41
return mChain[aIndex];
42
}
43
44
uint32_t OverscrollHandoffChain::IndexOf(
45
const AsyncPanZoomController* aApzc) const {
46
uint32_t i;
47
for (i = 0; i < Length(); ++i) {
48
if (mChain[i] == aApzc) {
49
break;
50
}
51
}
52
return i;
53
}
54
55
void OverscrollHandoffChain::ForEachApzc(APZCMethod aMethod) const {
56
for (uint32_t i = 0; i < Length(); ++i) {
57
(mChain[i]->*aMethod)();
58
}
59
}
60
61
bool OverscrollHandoffChain::AnyApzc(APZCPredicate aPredicate) const {
62
MOZ_ASSERT(Length() > 0);
63
for (uint32_t i = 0; i < Length(); ++i) {
64
if ((mChain[i]->*aPredicate)()) {
65
return true;
66
}
67
}
68
return false;
69
}
70
71
void OverscrollHandoffChain::FlushRepaints() const {
72
ForEachApzc(&AsyncPanZoomController::FlushRepaintForOverscrollHandoff);
73
}
74
75
void OverscrollHandoffChain::CancelAnimations(
76
CancelAnimationFlags aFlags) const {
77
MOZ_ASSERT(Length() > 0);
78
for (uint32_t i = 0; i < Length(); ++i) {
79
mChain[i]->CancelAnimation(aFlags);
80
}
81
}
82
83
void OverscrollHandoffChain::ClearOverscroll() const {
84
ForEachApzc(&AsyncPanZoomController::ClearOverscroll);
85
}
86
87
void OverscrollHandoffChain::SnapBackOverscrolledApzc(
88
const AsyncPanZoomController* aStart) const {
89
uint32_t i = IndexOf(aStart);
90
for (; i < Length(); ++i) {
91
AsyncPanZoomController* apzc = mChain[i];
92
if (!apzc->IsDestroyed()) {
93
apzc->SnapBackIfOverscrolled();
94
}
95
}
96
}
97
98
bool OverscrollHandoffChain::CanBePanned(
99
const AsyncPanZoomController* aApzc) const {
100
// Find |aApzc| in the handoff chain.
101
uint32_t i = IndexOf(aApzc);
102
103
// See whether any APZC in the handoff chain starting from |aApzc|
104
// has room to be panned.
105
for (uint32_t j = i; j < Length(); ++j) {
106
if (mChain[j]->IsPannable()) {
107
return true;
108
}
109
}
110
111
return false;
112
}
113
114
bool OverscrollHandoffChain::CanScrollInDirection(
115
const AsyncPanZoomController* aApzc, ScrollDirection aDirection) const {
116
// Find |aApzc| in the handoff chain.
117
uint32_t i = IndexOf(aApzc);
118
119
// See whether any APZC in the handoff chain starting from |aApzc|
120
// has room to scroll in the given direction.
121
for (uint32_t j = i; j < Length(); ++j) {
122
if (mChain[j]->CanScroll(aDirection)) {
123
return true;
124
}
125
}
126
127
return false;
128
}
129
130
bool OverscrollHandoffChain::HasOverscrolledApzc() const {
131
return AnyApzc(&AsyncPanZoomController::IsOverscrolled);
132
}
133
134
bool OverscrollHandoffChain::HasFastFlungApzc() const {
135
return AnyApzc(&AsyncPanZoomController::IsFlingingFast);
136
}
137
138
RefPtr<AsyncPanZoomController> OverscrollHandoffChain::FindFirstScrollable(
139
const InputData& aInput,
140
ScrollDirections* aOutAllowedScrollDirections) const {
141
// Start by allowing scrolling in both directions. As we do handoff
142
// overscroll-behavior may restrict one or both of the directions.
143
*aOutAllowedScrollDirections += ScrollDirection::eVertical;
144
*aOutAllowedScrollDirections += ScrollDirection::eHorizontal;
145
146
for (size_t i = 0; i < Length(); i++) {
147
if (mChain[i]->CanScroll(aInput)) {
148
return mChain[i];
149
}
150
151
*aOutAllowedScrollDirections &= mChain[i]->GetAllowedHandoffDirections();
152
if (aOutAllowedScrollDirections->isEmpty()) {
153
return nullptr;
154
}
155
}
156
return nullptr;
157
}
158
159
} // namespace layers
160
} // namespace mozilla