Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  SmoothScrollAnimation.cpp

  Sprache: C
 

/* 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 "SmoothScrollAnimation.h"
#include "AsyncPanZoomController.h"
#include "ScrollAnimationBezierPhysics.h"
#include "ScrollAnimationMSDPhysics.h"
#include "ScrollPositionUpdate.h"
#include "Units.h"
#include "mozilla/RelativeTo.h"
#include "mozilla/StaticPrefs_general.h"
#include "nsLayoutUtils.h"

static mozilla::LazyLogModule sApzScrollAnimLog("apz.scrollanimation");
#define SSA_LOG(...) MOZ_LOG(sApzScrollAnimLog, LogLevel::Debug, (__VA_ARGS__))

namespace mozilla {
namespace layers {

/*static*/
already_AddRefed<SmoothScrollAnimation> SmoothScrollAnimation::Create(
    AsyncPanZoomController& aApzc, ScrollAnimationKind aKind,
    ViewportType aViewportToScroll, ScrollOrigin aOrigin) {
  MOZ_ASSERT(aKind == ScrollAnimationKind::Smooth ||
             aKind == ScrollAnimationKind::SmoothMsd);
  RefPtr<SmoothScrollAnimation> result =
      new SmoothScrollAnimation(aKind, aApzc, aViewportToScroll, aOrigin);
  return result.forget();
}

/*static*/
already_AddRefed<SmoothScrollAnimation>
SmoothScrollAnimation::CreateForKeyboard(AsyncPanZoomController& aApzc,
                                         ScrollOrigin aOrigin) {
  RefPtr<SmoothScrollAnimation> result = new SmoothScrollAnimation(
      ScrollAnimationKind::Keyboard, aApzc, ViewportType::Visual, aOrigin);
  return result.forget();
}

static ScrollOrigin OriginForDeltaType(
    ScrollWheelInput::ScrollDeltaType aDeltaType) {
  switch (aDeltaType) {
    case ScrollWheelInput::SCROLLDELTA_PAGE:
      return ScrollOrigin::Pages;
    case ScrollWheelInput::SCROLLDELTA_PIXEL:
      return ScrollOrigin::Pixels;
    case ScrollWheelInput::SCROLLDELTA_LINE:
      return ScrollOrigin::MouseWheel;
  }
  // Shouldn't happen, pick a default.
  return ScrollOrigin::MouseWheel;
}

/*static*/
already_AddRefed<SmoothScrollAnimation> SmoothScrollAnimation::CreateForWheel(
    AsyncPanZoomController& aApzc,
    ScrollWheelInput::ScrollDeltaType aDeltaType) {
  RefPtr<SmoothScrollAnimation> result = new SmoothScrollAnimation(
      ScrollAnimationKind::Wheel, aApzc, ViewportType::Visual,
      OriginForDeltaType(aDeltaType));
  MOZ_ASSERT(nsLayoutUtils::IsSmoothScrollingEnabled(),
             "We shouldn't be creating a WheelScrollAnimation if smooth "
             "scrolling is disabled");
  result->mDirectionForcedToOverscroll =
      aApzc.mScrollMetadata.GetDisregardedDirection();
  return result.forget();
}

SmoothScrollAnimation::SmoothScrollAnimation(ScrollAnimationKind aKind,
                                             AsyncPanZoomController& aApzc,
                                             ViewportType aViewportToScroll,
                                             ScrollOrigin aOrigin)
    : mKind(aKind),
      mViewportToScroll(aViewportToScroll),
      mApzc(aApzc),
      mFinalDestination(
          CSSPoint::ToAppUnits(GetViewportOffset(aApzc.Metrics()))),
      mOrigin(aOrigin),
      mTriggeredByScript(ScrollTriggeredByScript::No) {
  // ScrollAnimationBezierPhysics (despite its name) handles the case of
  // general.smoothScroll being disabled whereas ScrollAnimationMSDPhysics does
  // not (ie it scrolls smoothly).
  if (mKind == ScrollAnimationKind::SmoothMsd ||
      (nsLayoutUtils::IsSmoothScrollingEnabled() &&
       StaticPrefs::general_smoothScroll_msdPhysics_enabled())) {
    nscoord smallestVisibleIncrement = 1;
    if (mKind == ScrollAnimationKind::SmoothMsd &&
        mApzc.GetFrameMetrics().GetZoom() != CSSToParentLayerScale(0)) {
      // SmoothMsdScrollAnimation used 1 ParentLayer pixel as the "smallest
      // visible increment". Note that we are passing quantities (such as the
      // destination) to ScrollAnimationMSDPhysics in app units, so the
      // increment needs to be converted to app units as well.
      smallestVisibleIncrement = CSSPixel::ToAppUnits(
          ParentLayerCoord(1) / mApzc.GetFrameMetrics().GetZoom());
    }
    mAnimationPhysics = MakeUnique<ScrollAnimationMSDPhysics>(
        mKind, mFinalDestination, smallestVisibleIncrement);
  } else {
    mAnimationPhysics = MakeUnique<ScrollAnimationBezierPhysics>(
        mFinalDestination,
        apz::ComputeBezierAnimationSettingsForOrigin(aOrigin));
  }
}

bool SmoothScrollAnimation::CanExtend(ViewportType aViewportToScroll,
                                      ScrollOrigin aOrigin) const {
  MOZ_ASSERT(mKind == ScrollAnimationKind::Smooth ||
             mKind == ScrollAnimationKind::SmoothMsd);
  // The viewport type must always match.
  if (aViewportToScroll != mViewportToScroll) {
    return false;
  }
  if (mKind == ScrollAnimationKind::SmoothMsd) {
    // We do not track the origin of SmoothMsd animations, so
    // always allow extending.
    return true;
  }
  // Otherwise, the origin must match.
  return aOrigin == mOrigin;
}

SmoothScrollAnimation* SmoothScrollAnimation::AsSmoothScrollAnimation() {
  return this;
}

void SmoothScrollAnimation::UpdateDestinationAndSnapTargets(
    TimeStamp aTime, const nsPoint& aDestination,
    const nsSize& aCurrentVelocity, ScrollSnapTargetIds&& aSnapTargetIds,
    ScrollTriggeredByScript aTriggeredByScript) {
  UpdateDestination(aTime, aDestination, aCurrentVelocity);
  mSnapTargetIds = std::move(aSnapTargetIds);
  mTriggeredByScript = aTriggeredByScript;
}

ScrollOrigin SmoothScrollAnimation::GetScrollOrigin() const { return mOrigin; }

ScrollOrigin SmoothScrollAnimation::GetScrollOriginForAction(
    KeyboardScrollAction::KeyboardScrollActionType aAction) {
  switch (aAction) {
    case KeyboardScrollAction::eScrollCharacter:
    case KeyboardScrollAction::eScrollLine: {
      return ScrollOrigin::Lines;
    }
    case KeyboardScrollAction::eScrollPage:
      return ScrollOrigin::Pages;
    case KeyboardScrollAction::eScrollComplete:
      return ScrollOrigin::Other;
    default:
      MOZ_ASSERT(false"Unknown keyboard scroll action type");
      return ScrollOrigin::Other;
  }
}

void SmoothScrollAnimation::UpdateDelta(TimeStamp aTime, const nsPoint& aDelta,
                                        const nsSize& aCurrentVelocity) {
  mFinalDestination += aDelta;

  Update(aTime, aCurrentVelocity);
}

void SmoothScrollAnimation::UpdateDestination(TimeStamp aTime,
                                              const nsPoint& aDestination,
                                              const nsSize& aCurrentVelocity) {
  mFinalDestination = aDestination;

  Update(aTime, aCurrentVelocity);
}

void SmoothScrollAnimation::Update(TimeStamp aTime,
                                   const nsSize& aCurrentVelocity) {
  // Clamp the final destination to the scrollable area.
  CSSPoint clamped = CSSPoint::FromAppUnits(mFinalDestination);
  clamped.x = mApzc.mX.ClampOriginToScrollableRect(clamped.x);
  clamped.y = mApzc.mY.ClampOriginToScrollableRect(clamped.y);
  mFinalDestination = CSSPoint::ToAppUnits(clamped);

  mAnimationPhysics->Update(aTime, mFinalDestination, aCurrentVelocity);
}

CSSPoint SmoothScrollAnimation::GetViewportOffset(
    const FrameMetrics& aMetrics) const {
  return mViewportToScroll == ViewportType::Visual
             ? aMetrics.GetVisualScrollOffset()
             : aMetrics.GetLayoutScrollOffset();
}

bool SmoothScrollAnimation::DoSample(FrameMetrics& aFrameMetrics,
                                     const TimeDuration& aDelta) {
  TimeStamp now = mApzc.GetFrameTime().Time();
  CSSToParentLayerScale zoom(aFrameMetrics.GetZoom());
  if (zoom == CSSToParentLayerScale(0)) {
    return false;
  }

  // If the animation is finished, make sure the final position is correct by
  // using one last displacement. Otherwise, compute the delta via the timing
  // function as normal.
  bool finished = mAnimationPhysics->IsFinished(now);
  nsPoint sampledDest = mAnimationPhysics->PositionAt(now);
  const CSSPoint cssDisplacement =
      CSSPoint::FromAppUnits(sampledDest) - GetViewportOffset(aFrameMetrics);

  if (finished) {
    mApzc.mX.SetVelocity(0);
    mApzc.mY.SetVelocity(0);
  } else if (!IsZero(cssDisplacement)) {
    // Convert velocity from AppUnits/Seconds to ParentLayerCoords/Milliseconds
    nsSize velocity = mAnimationPhysics->VelocityAt(now);
    ParentLayerPoint velocityPL =
        CSSPoint::FromAppUnits(nsPoint(velocity.width, velocity.height)) * zoom;
    mApzc.mX.SetVelocity(velocityPL.x / 1000.0);
    mApzc.mY.SetVelocity(velocityPL.y / 1000.0);
  }
  if (mViewportToScroll == ViewportType::Visual) {
    // Note: we ignore overscroll for generic animations.
    const ParentLayerPoint displacement = cssDisplacement * zoom;
    ParentLayerPoint adjustedOffset, overscroll;
    mApzc.mX.AdjustDisplacement(
        displacement.x, adjustedOffset.x, overscroll.x,
        mDirectionForcedToOverscroll == Some(ScrollDirection::eHorizontal));
    mApzc.mY.AdjustDisplacement(
        displacement.y, adjustedOffset.y, overscroll.y,
        mDirectionForcedToOverscroll == Some(ScrollDirection::eVertical));
    // If we expected to scroll, but there's no more scroll range on either
    // axis, then end the animation early. Note that the initial displacement
    // could be 0 if the compositor ran very quickly (<1ms) after the animation
    // was created. When that happens we want to make sure the animation
    // continues.
    SSA_LOG(
        "Sampling SmoothScrollAnimation (visual mode): time %f finished %d "
        "sampledDest %s adjustedOffset %s overscroll %s",
        (now - TimeStamp::ProcessCreation()).ToMilliseconds(), finished,
        ToString(CSSPoint::FromAppUnits(sampledDest)).c_str(),
        ToString(adjustedOffset).c_str(), ToString(overscroll).c_str());
    if (!IsZero(cssDisplacement) && IsZero(adjustedOffset / zoom)) {
      // Nothing more to do - end the animation.
      finished = true;
    } else {
      mApzc.ScrollBy(adjustedOffset / zoom);
    }
  } else {
    // Use a slightly simplified implementation for ViewportType::Layout.
    // For example, we don't need to handle mDirectionForcedToOverscroll in this
    // case.
    MOZ_ASSERT(mDirectionForcedToOverscroll.isNothing());
    MOZ_ASSERT(!mApzc.IsPhysicallyOverscrolled());
    CSSPoint offsetBefore = GetViewportOffset(aFrameMetrics);
    mApzc.ScrollByAndClamp(mViewportToScroll, cssDisplacement);
    CSSPoint offsetAfter = GetViewportOffset(aFrameMetrics);
    CSSPoint amountScrolled = offsetAfter - offsetBefore;
    if (!IsZero(cssDisplacement) && IsZero(amountScrolled)) {
      finished = true;
    }
    SSA_LOG(
        "Sampling SmoothScrollAnimation (layout mode): time %f finished %d "
        "sampledDest %s offsetAfter %s\n",
        (now - TimeStamp::ProcessCreation()).ToMilliseconds(), finished,
        ToString(CSSPoint::FromAppUnits(sampledDest)).c_str(),
        ToString(offsetAfter).c_str());
  }
  if (finished) {
    // Set the scroll offset to the exact destination. If we allow the scroll
    // offset to end up being a bit off from the destination, we can get
    // artefacts like "scroll to the next snap point in this direction"
    // scrolling to the snap point we're already supposed to be at.
    mApzc.ScrollToAndClamp(mViewportToScroll,
                           CSSPoint::FromAppUnits(mFinalDestination));
  }
  return !finished;
}

bool SmoothScrollAnimation::HandleScrollOffsetUpdate(
    const Maybe<CSSPoint>& aRelativeDelta) {
  if (aRelativeDelta) {
    mAnimationPhysics->ApplyContentShift(*aRelativeDelta);
    mFinalDestination += CSSPoint::ToAppUnits(*aRelativeDelta);
    return true;
  }
  return false;
}

}  // namespace layers
}  // namespace mozilla

Messung V0.5 in Prozent
C=88 H=100 G=94

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-08-23) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002