diff options
Diffstat (limited to '')
-rw-r--r-- | gfx/layers/apz/src/AutoscrollAnimation.cpp | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/gfx/layers/apz/src/AutoscrollAnimation.cpp b/gfx/layers/apz/src/AutoscrollAnimation.cpp new file mode 100644 index 0000000000..8d4b8fca10 --- /dev/null +++ b/gfx/layers/apz/src/AutoscrollAnimation.cpp @@ -0,0 +1,93 @@ +/* -*- 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/. */ + +#include "AutoscrollAnimation.h" + +#include <cmath> // for sqrtf() + +#include "AsyncPanZoomController.h" +#include "APZCTreeManager.h" +#include "FrameMetrics.h" +#include "mozilla/Telemetry.h" // for Telemetry + +namespace mozilla { +namespace layers { + +// Helper function for AutoscrollAnimation::DoSample(). +// Basically copied as-is from toolkit/actors/AutoScrollChild.jsm. +static float Accelerate(ScreenCoord curr, ScreenCoord start) { + static const int speed = 12; + float val = (curr - start) / speed; + if (val > 1) { + return val * sqrtf(val) - 1; + } + if (val < -1) { + return val * sqrtf(-val) + 1; + } + return 0; +} + +AutoscrollAnimation::AutoscrollAnimation(AsyncPanZoomController& aApzc, + const ScreenPoint& aAnchorLocation) + : mApzc(aApzc), mAnchorLocation(aAnchorLocation) {} + +bool AutoscrollAnimation::DoSample(FrameMetrics& aFrameMetrics, + const TimeDuration& aDelta) { + APZCTreeManager* treeManager = mApzc.GetApzcTreeManager(); + if (!treeManager) { + return false; + } + + ScreenPoint mouseLocation = treeManager->GetCurrentMousePosition(); + + // The implementation of this function closely mirrors that of its main- + // thread equivalent, the autoscrollLoop() function in + // toolkit/actors/AutoScrollChild.jsm. + + // Avoid long jumps when the browser hangs for more than |maxTimeDelta| ms. + static const TimeDuration maxTimeDelta = TimeDuration::FromMilliseconds(100); + TimeDuration timeDelta = TimeDuration::Min(aDelta, maxTimeDelta); + + float timeCompensation = timeDelta.ToMilliseconds() / 20; + + // Notes: + // - The main-thread implementation rounds the scroll delta to an integer, + // and keeps track of the fractional part as an "error". It does this + // because it uses Window.scrollBy() or Element.scrollBy() to perform + // the scrolling, and those functions truncate the fractional part of + // the offset. APZ does no such truncation, so there's no need to keep + // track of the fractional part separately. + // - The Accelerate() function takes Screen coordinates as inputs, but + // its output is interpreted as CSS coordinates. This is intentional, + // insofar as autoscrollLoop() does the same thing. + CSSPoint scrollDelta{ + Accelerate(mouseLocation.x, mAnchorLocation.x) * timeCompensation, + Accelerate(mouseLocation.y, mAnchorLocation.y) * timeCompensation}; + + mApzc.ScrollByAndClamp(scrollDelta); + + // An autoscroll animation never ends of its own accord. + // It can be stopped in response to various input events, in which case + // AsyncPanZoomController::StopAutoscroll() will stop it via + // CancelAnimation(). + return true; +} + +void AutoscrollAnimation::Cancel(CancelAnimationFlags aFlags) { + // The cancellation was initiated by browser.js, so there's no need to + // notify it. + if (aFlags & TriggeredExternally) { + return; + } + + if (RefPtr<GeckoContentController> controller = + mApzc.GetGeckoContentController()) { + controller->CancelAutoscroll(mApzc.GetGuid()); + } +} + +} // namespace layers +} // namespace mozilla |