зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1259296 - Scroll snap in the compositor in response to wheel events. r=kats
MozReview-Commit-ID: 9fOlssstgvR --HG-- extra : source : fbdee753c4618cbc1a7c79e3ec07b7479f93a05d extra : histedit_source : dd42dfa282ea2e14fe5c9e028acc699746fcf8bc
This commit is contained in:
Родитель
4d0aaaafea
Коммит
4058840cb9
|
@ -1819,6 +1819,11 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
|
|||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS,
|
||||
(uint32_t) ScrollInputMethodForWheelDeltaType(aEvent.mDeltaType));
|
||||
|
||||
// Wheel events from "clicky" mouse wheels trigger scroll snapping to the
|
||||
// next snap point. Check for this, and adjust the delta to take into
|
||||
// account the snap point.
|
||||
bool scrollSnapping = MaybeAdjustDeltaForScrollSnapping(delta, aEvent);
|
||||
|
||||
switch (aEvent.mScrollMode) {
|
||||
case ScrollWheelInput::SCROLLMODE_INSTANT: {
|
||||
ScreenPoint distance = ToScreenCoordinates(
|
||||
|
@ -1850,6 +1855,14 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
|
|||
// update it.
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
|
||||
if (scrollSnapping) {
|
||||
// If we're scroll snapping use a smooth scroll animation to get
|
||||
// the desired physics. Note that SmoothScrollTo() will re-use an
|
||||
// existing smooth scroll animation if there is one.
|
||||
CSSPoint snapPoint = mFrameMetrics.GetScrollOffset() + (delta / mFrameMetrics.GetZoom());
|
||||
SmoothScrollTo(snapPoint);
|
||||
} else {
|
||||
// Otherwise, use a wheel scroll animation, also reusing one if possible.
|
||||
if (mState != WHEEL_SCROLL) {
|
||||
CancelAnimation();
|
||||
SetState(WHEEL_SCROLL);
|
||||
|
@ -1868,6 +1881,7 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
|
|||
|
||||
WheelScrollAnimation* animation = mAnimation->AsWheelScrollAnimation();
|
||||
animation->Update(aEvent.mTimeStamp, deltaInAppUnits, nsSize(velocity.x, velocity.y));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -3937,13 +3951,14 @@ void AsyncPanZoomController::ShareCompositorFrameMetrics() {
|
|||
}
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::ScrollSnapNear(const CSSPoint& aDestination) {
|
||||
Maybe<CSSPoint> AsyncPanZoomController::FindSnapPointNear(
|
||||
const CSSPoint& aDestination, nsIScrollableFrame::ScrollUnit aUnit) {
|
||||
mMonitor.AssertCurrentThreadIn();
|
||||
APZC_LOG("%p scroll snapping near %s\n", this, Stringify(aDestination).c_str());
|
||||
CSSRect scrollRange = mFrameMetrics.CalculateScrollRange();
|
||||
if (Maybe<nsPoint> snapPoint = ScrollSnapUtils::GetSnapPointForDestination(
|
||||
mScrollMetadata.GetSnapInfo(),
|
||||
nsIScrollableFrame::DEVICE_PIXELS,
|
||||
aUnit,
|
||||
CSSSize::ToAppUnits(mFrameMetrics.CalculateCompositedSizeInCssPixels()),
|
||||
CSSRect::ToAppUnits(scrollRange),
|
||||
CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset()),
|
||||
|
@ -3953,8 +3968,15 @@ void AsyncPanZoomController::ScrollSnapNear(const CSSPoint& aDestination) {
|
|||
// of the scroll frame's scroll range. Clamp it here (this matches the
|
||||
// behaviour of the main-thread code path, which clamps it in
|
||||
// nsGfxScrollFrame::ScrollTo()).
|
||||
cssSnapPoint = scrollRange.ClampPoint(cssSnapPoint);
|
||||
SmoothScrollTo(cssSnapPoint);
|
||||
return Some(scrollRange.ClampPoint(cssSnapPoint));
|
||||
}
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::ScrollSnapNear(const CSSPoint& aDestination) {
|
||||
if (Maybe<CSSPoint> snapPoint =
|
||||
FindSnapPointNear(aDestination, nsIScrollableFrame::DEVICE_PIXELS)) {
|
||||
SmoothScrollTo(*snapPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3996,5 +4018,29 @@ void AsyncPanZoomController::ScrollSnapToDestination() {
|
|||
}
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::MaybeAdjustDeltaForScrollSnapping(
|
||||
ParentLayerPoint& aDelta, const ScrollWheelInput& aEvent)
|
||||
{
|
||||
// Don't scroll snap for pixel scrolls. This matches the main thread
|
||||
// behaviour in EventStateManager::DoScrollText().
|
||||
if (aEvent.mDeltaType == ScrollWheelInput::SCROLLDELTA_PIXEL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
CSSPoint scrollOffset = mFrameMetrics.GetScrollOffset();
|
||||
CSSToParentLayerScale2D zoom = mFrameMetrics.GetZoom();
|
||||
CSSPoint destination = mFrameMetrics.CalculateScrollRange().ClampPoint(
|
||||
scrollOffset + (aDelta / zoom));
|
||||
nsIScrollableFrame::ScrollUnit unit =
|
||||
ScrollWheelInput::ScrollUnitForDeltaType(aEvent.mDeltaType);
|
||||
|
||||
if (Maybe<CSSPoint> snapPoint = FindSnapPointNear(destination, unit)) {
|
||||
aDelta = (*snapPoint - scrollOffset) * zoom;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "Layers.h" // for Layer::ScrollDirection
|
||||
#include "LayersTypes.h"
|
||||
#include "mozilla/gfx/Matrix.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsRegion.h"
|
||||
#include "PotentialCheckerboardDurationTracker.h"
|
||||
|
||||
|
@ -622,15 +623,6 @@ protected:
|
|||
// Common processing at the end of a touch block.
|
||||
void OnTouchEndOrCancel();
|
||||
|
||||
// Snap to a snap position nearby the current scroll position, if appropriate.
|
||||
void ScrollSnap();
|
||||
// Snap to a snap position nearby the destination predicted based on the
|
||||
// current velocity, if appropriate.
|
||||
void ScrollSnapToDestination();
|
||||
|
||||
// Helper function for ScrollSnap() and ScrollSnapToDestination().
|
||||
void ScrollSnapNear(const CSSPoint& aDestination);
|
||||
|
||||
uint64_t mLayersId;
|
||||
RefPtr<CompositorBridgeParent> mCompositorBridgeParent;
|
||||
|
||||
|
@ -763,7 +755,6 @@ public:
|
|||
AsyncTransformComponentMatrix GetCurrentAsyncTransformWithOverscroll(AsyncMode aMode) const;
|
||||
|
||||
|
||||
|
||||
/* ===================================================================
|
||||
* The functions and members in this section are used to manage
|
||||
* the state that tracks what this APZC is doing with the input events.
|
||||
|
@ -1156,6 +1147,35 @@ private:
|
|||
// be checkerboarding. Combined with other info, this allows us to meaningfully
|
||||
// say how frequently users actually encounter checkerboarding.
|
||||
PotentialCheckerboardDurationTracker mPotentialCheckerboardTracker;
|
||||
|
||||
|
||||
/* ===================================================================
|
||||
* The functions in this section are used for CSS scroll snapping.
|
||||
*/
|
||||
|
||||
// If |aEvent| should trigger scroll snapping, adjust |aDelta| to reflect
|
||||
// the snapping (that is, make it a delta that will take us to the desired
|
||||
// snap point). Returns true iff. the delta was so adjusted.
|
||||
bool MaybeAdjustDeltaForScrollSnapping(ParentLayerPoint& aDelta,
|
||||
const ScrollWheelInput& aEvent);
|
||||
|
||||
// Snap to a snap position nearby the current scroll position, if appropriate.
|
||||
void ScrollSnap();
|
||||
|
||||
// Snap to a snap position nearby the destination predicted based on the
|
||||
// current velocity, if appropriate.
|
||||
void ScrollSnapToDestination();
|
||||
|
||||
// Snap to a snap position nearby the provided destination, if appropriate.
|
||||
void ScrollSnapNear(const CSSPoint& aDestination);
|
||||
|
||||
// Find a snap point near |aDestination| that we should snap to.
|
||||
// Returns the snap point if one was found, or an empty Maybe otherwise.
|
||||
// |aUnit| affects the snapping behaviour (see ScrollSnapUtils::
|
||||
// GetSnapPointForDestination). It should generally be determined by the
|
||||
// type of event that's triggering the scroll.
|
||||
Maybe<CSSPoint> FindSnapPointNear(const CSSPoint& aDestination,
|
||||
nsIScrollableFrame::ScrollUnit aUnit);
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
#ifndef InputData_h__
|
||||
#define InputData_h__
|
||||
|
||||
#include "nsIDOMWheelEvent.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsIDOMWheelEvent.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsPoint.h"
|
||||
#include "nsTArray.h"
|
||||
#include "Units.h"
|
||||
|
@ -577,6 +578,22 @@ public:
|
|||
return SCROLLDELTA_LINE;
|
||||
}
|
||||
|
||||
static nsIScrollableFrame::ScrollUnit
|
||||
ScrollUnitForDeltaType(ScrollDeltaType aDeltaType)
|
||||
{
|
||||
switch (aDeltaType) {
|
||||
case SCROLLDELTA_LINE:
|
||||
return nsIScrollableFrame::LINES;
|
||||
case SCROLLDELTA_PAGE:
|
||||
return nsIScrollableFrame::PAGES;
|
||||
case SCROLLDELTA_PIXEL:
|
||||
return nsIScrollableFrame::DEVICE_PIXELS;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
return nsIScrollableFrame::LINES;
|
||||
}
|
||||
|
||||
enum ScrollMode
|
||||
{
|
||||
SCROLLMODE_INSTANT,
|
||||
|
|
Загрузка…
Ссылка в новой задаче