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 "AutoscrollAnimation.h"
8
9
#include <cmath> // for sqrtf()
10
11
#include "AsyncPanZoomController.h"
12
#include "APZCTreeManager.h"
13
#include "FrameMetrics.h"
14
#include "mozilla/Telemetry.h" // for Telemetry
15
16
namespace mozilla {
17
namespace layers {
18
19
// Helper function for AutoscrollAnimation::DoSample().
20
// Basically copied as-is from toolkit/content/browser-content.js.
21
static float Accelerate(ScreenCoord curr, ScreenCoord start) {
22
static const int speed = 12;
23
float val = (curr - start) / speed;
24
if (val > 1) {
25
return val * sqrtf(val) - 1;
26
}
27
if (val < -1) {
28
return val * sqrtf(-val) + 1;
29
}
30
return 0;
31
}
32
33
AutoscrollAnimation::AutoscrollAnimation(AsyncPanZoomController& aApzc,
34
const ScreenPoint& aAnchorLocation)
35
: mApzc(aApzc), mAnchorLocation(aAnchorLocation) {}
36
37
bool AutoscrollAnimation::DoSample(FrameMetrics& aFrameMetrics,
38
const TimeDuration& aDelta) {
39
APZCTreeManager* treeManager = mApzc.GetApzcTreeManager();
40
if (!treeManager) {
41
return false;
42
}
43
44
ScreenPoint mouseLocation = treeManager->GetCurrentMousePosition();
45
46
// The implementation of this function closely mirrors that of its main-
47
// thread equivalent, the autoscrollLoop() function in
48
// toolkit/content/browser-content.js.
49
50
// Avoid long jumps when the browser hangs for more than |maxTimeDelta| ms.
51
static const TimeDuration maxTimeDelta = TimeDuration::FromMilliseconds(100);
52
TimeDuration timeDelta = TimeDuration::Min(aDelta, maxTimeDelta);
53
54
float timeCompensation = timeDelta.ToMilliseconds() / 20;
55
56
// Notes:
57
// - The main-thread implementation rounds the scroll delta to an integer,
58
// and keeps track of the fractional part as an "error". It does this
59
// because it uses Window.scrollBy() or Element.scrollBy() to perform
60
// the scrolling, and those functions truncate the fractional part of
61
// the offset. APZ does no such truncation, so there's no need to keep
62
// track of the fractional part separately.
63
// - The Accelerate() function takes Screen coordinates as inputs, but
64
// its output is interpreted as CSS coordinates. This is intentional,
65
// insofar as autoscrollLoop() does the same thing.
66
CSSPoint scrollDelta{
67
Accelerate(mouseLocation.x, mAnchorLocation.x) * timeCompensation,
68
Accelerate(mouseLocation.y, mAnchorLocation.y) * timeCompensation};
69
70
mApzc.ScrollByAndClamp(scrollDelta);
71
72
// An autoscroll animation never ends of its own accord.
73
// It can be stopped in response to various input events, in which case
74
// AsyncPanZoomController::StopAutoscroll() will stop it via
75
// CancelAnimation().
76
return true;
77
}
78
79
void AutoscrollAnimation::Cancel(CancelAnimationFlags aFlags) {
80
// The cancellation was initiated by browser.js, so there's no need to
81
// notify it.
82
if (aFlags & TriggeredExternally) {
83
return;
84
}
85
86
if (RefPtr<GeckoContentController> controller =
87
mApzc.GetGeckoContentController()) {
88
controller->CancelAutoscroll(mApzc.GetGuid());
89
}
90
}
91
92
} // namespace layers
93
} // namespace mozilla