tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SimpleVelocityTracker.cpp (5129B)


      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 "SimpleVelocityTracker.h"
      8 
      9 #include "mozilla/ServoStyleConsts.h"  // for StyleComputedTimingFunction
     10 #include "mozilla/StaticPrefs_apz.h"
     11 #include "mozilla/StaticPtr.h"  // for StaticAutoPtr
     12 
     13 static mozilla::LazyLogModule sApzSvtLog("apz.simplevelocitytracker");
     14 #define SVT_LOG(...) MOZ_LOG(sApzSvtLog, LogLevel::Debug, (__VA_ARGS__))
     15 
     16 namespace mozilla {
     17 namespace layers {
     18 
     19 // When we compute the velocity we do so by taking two input events and
     20 // dividing the distance delta over the time delta. In some cases the time
     21 // delta can be really small, which can make the velocity computation very
     22 // volatile. To avoid this we impose a minimum time delta below which we do
     23 // not recompute the velocity.
     24 MOZ_RUNINIT const TimeDuration MIN_VELOCITY_SAMPLE_TIME =
     25    TimeDuration::FromMilliseconds(5);
     26 
     27 extern StaticAutoPtr<StyleComputedTimingFunction> gVelocityCurveFunction;
     28 
     29 SimpleVelocityTracker::SimpleVelocityTracker(Axis* aAxis)
     30    : mAxis(aAxis), mVelocitySamplePos(0) {}
     31 
     32 void SimpleVelocityTracker::StartTracking(ParentLayerCoord aPos,
     33                                          TimeStamp aTimestamp) {
     34  Clear();
     35  mVelocitySampleTime = aTimestamp;
     36  mVelocitySamplePos = aPos;
     37 }
     38 
     39 Maybe<float> SimpleVelocityTracker::AddPosition(ParentLayerCoord aPos,
     40                                                TimeStamp aTimestamp) {
     41  if (aTimestamp <= mVelocitySampleTime + MIN_VELOCITY_SAMPLE_TIME) {
     42    // See also the comment on MIN_VELOCITY_SAMPLE_TIME.
     43    // We don't update either mVelocitySampleTime or mVelocitySamplePos so that
     44    // eventually when we do get an event with the required time delta we use
     45    // the corresponding distance delta as well.
     46    SVT_LOG("%p|%s skipping velocity computation for small time delta %f ms\n",
     47            mAxis->OpaqueApzcPointer(), mAxis->Name(),
     48            (aTimestamp - mVelocitySampleTime).ToMilliseconds());
     49    return Nothing();
     50  }
     51 
     52  float newVelocity =
     53      (float)(mVelocitySamplePos - aPos) /
     54      (float)(aTimestamp - mVelocitySampleTime).ToMilliseconds();
     55 
     56  newVelocity = ApplyFlingCurveToVelocity(newVelocity);
     57 
     58  SVT_LOG("%p|%s updating velocity to %f with touch\n",
     59          mAxis->OpaqueApzcPointer(), mAxis->Name(), newVelocity);
     60  mVelocitySampleTime = aTimestamp;
     61  mVelocitySamplePos = aPos;
     62 
     63  AddVelocityToQueue(aTimestamp, newVelocity);
     64 
     65  return Some(newVelocity);
     66 }
     67 
     68 Maybe<float> SimpleVelocityTracker::ComputeVelocity(TimeStamp aTimestamp) {
     69  float velocity = 0;
     70  int count = 0;
     71  for (const auto& e : mVelocityQueue) {
     72    TimeDuration timeDelta = (aTimestamp - e.first);
     73    if (timeDelta < TimeDuration::FromMilliseconds(
     74                        StaticPrefs::apz_velocity_relevance_time_ms())) {
     75      count++;
     76      velocity += e.second;
     77    }
     78  }
     79  mVelocityQueue.Clear();
     80  if (count > 1) {
     81    velocity /= count;
     82  }
     83  return Some(velocity);
     84 }
     85 
     86 void SimpleVelocityTracker::Clear() { mVelocityQueue.Clear(); }
     87 
     88 void SimpleVelocityTracker::AddVelocityToQueue(TimeStamp aTimestamp,
     89                                               float aVelocity) {
     90  mVelocityQueue.AppendElement(std::make_pair(aTimestamp, aVelocity));
     91  if (mVelocityQueue.Length() >
     92      StaticPrefs::apz_max_velocity_queue_size_AtStartup()) {
     93    mVelocityQueue.RemoveElementAt(0);
     94  }
     95 }
     96 
     97 float SimpleVelocityTracker::ApplyFlingCurveToVelocity(float aVelocity) const {
     98  float newVelocity = aVelocity;
     99  if (StaticPrefs::apz_max_velocity_inches_per_ms() > 0.0f) {
    100    bool velocityIsNegative = (newVelocity < 0);
    101    newVelocity = fabs(newVelocity);
    102 
    103    float maxVelocity =
    104        mAxis->ToLocalVelocity(StaticPrefs::apz_max_velocity_inches_per_ms());
    105    newVelocity = std::min(newVelocity, maxVelocity);
    106 
    107    if (StaticPrefs::apz_fling_curve_threshold_inches_per_ms() > 0.0f &&
    108        StaticPrefs::apz_fling_curve_threshold_inches_per_ms() <
    109            StaticPrefs::apz_max_velocity_inches_per_ms()) {
    110      float curveThreshold = mAxis->ToLocalVelocity(
    111          StaticPrefs::apz_fling_curve_threshold_inches_per_ms());
    112      if (newVelocity > curveThreshold) {
    113        // here, 0 < curveThreshold < newVelocity <= maxVelocity, so we apply
    114        // the curve
    115        float scale = maxVelocity - curveThreshold;
    116        float funcInput = (newVelocity - curveThreshold) / scale;
    117        float funcOutput =
    118            gVelocityCurveFunction->At(funcInput, /* aBeforeFlag = */ false);
    119        float curvedVelocity = (funcOutput * scale) + curveThreshold;
    120        SVT_LOG("%p|%s curving up velocity from %f to %f\n",
    121                mAxis->OpaqueApzcPointer(), mAxis->Name(), newVelocity,
    122                curvedVelocity);
    123        newVelocity = curvedVelocity;
    124      }
    125    }
    126 
    127    if (velocityIsNegative) {
    128      newVelocity = -newVelocity;
    129    }
    130  }
    131 
    132  return newVelocity;
    133 }
    134 
    135 }  // namespace layers
    136 }  // namespace mozilla