Bug 1352863 - Implement support for slider.snapMultiplier during APZ dragging. r=kats
MozReview-Commit-ID: EbmjdNLVsq7
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -829,17 +829,18 @@ AsyncPanZoomController::ArePointerEvents
if (!consumable) {
return false;
}
return true;
}
nsEventStatus AsyncPanZoomController::HandleDragEvent(const MouseInput& aEvent,
- const AsyncDragMetrics& aDragMetrics)
+ const AsyncDragMetrics& aDragMetrics,
+ CSSCoord aInitialThumbPos)
{
if (!gfxPrefs::APZDragEnabled()) {
return nsEventStatus_eIgnore;
}
if (!GetApzcTreeManager()) {
return nsEventStatus_eConsumeNoDefault;
}
@@ -858,19 +859,41 @@ nsEventStatus AsyncPanZoomController::Ha
return nsEventStatus_eConsumeNoDefault;
}
const ScrollThumbData& thumbData = node->GetScrollThumbData();
mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS,
(uint32_t) ScrollInputMethod::ApzScrollbarDrag);
+ bool isMouseAwayFromThumb = false;
+ if (int snapMultiplier = gfxPrefs::SliderSnapMultiplier()) {
+ // It's fine to ignore the async component of the thumb's transform,
+ // because any async transform of the thumb will be in the direction of
+ // scrolling, but here we're interested in the other direction.
+ ParentLayerRect thumbRect =
+ (node->GetTransform() * AsyncTransformMatrix()).TransformBounds(
+ LayerRect(node->GetVisibleRegion().GetBounds()));
+ ScrollDirection otherDirection = GetPerpendicularDirection(aDragMetrics.mDirection);
+ ParentLayerCoord distance = GetAxisStart(otherDirection,
+ thumbRect.DistanceTo(aEvent.mLocalOrigin));
+ ParentLayerCoord thumbWidth = GetAxisLength(otherDirection, thumbRect);
+ if (thumbWidth * snapMultiplier < distance) {
+ isMouseAwayFromThumb = true;
+ }
+ }
+
ReentrantMonitorAutoEnter lock(mMonitor);
- CSSCoord thumbPosition = ConvertScrollbarPoint(aEvent.mLocalOrigin, thumbData) -
- aDragMetrics.mScrollbarDragOffset;
+ CSSCoord thumbPosition;
+ if (isMouseAwayFromThumb) {
+ thumbPosition = aInitialThumbPos;
+ } else {
+ thumbPosition = ConvertScrollbarPoint(aEvent.mLocalOrigin, thumbData) -
+ aDragMetrics.mScrollbarDragOffset;
+ }
CSSCoord maxThumbPos = thumbData.mScrollTrackLength;
maxThumbPos -= thumbData.mThumbLength;
float scrollPercent = thumbPosition / maxThumbPos;
CSSCoord minScrollPosition =
GetAxisStart(aDragMetrics.mDirection, mFrameMetrics.GetScrollableRect().TopLeft());
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -256,17 +256,18 @@ public:
* checkerboard immediately. This includes a bunch of logic, including
* algorithms to bias painting in the direction of the velocity.
*/
static const ScreenMargin CalculatePendingDisplayPort(
const FrameMetrics& aFrameMetrics,
const ParentLayerPoint& aVelocity);
nsEventStatus HandleDragEvent(const MouseInput& aEvent,
- const AsyncDragMetrics& aDragMetrics);
+ const AsyncDragMetrics& aDragMetrics,
+ CSSCoord aInitialThumbPos);
/**
* Handler for events which should not be intercepted by the touch listener.
*/
nsEventStatus HandleInputEvent(const InputData& aEvent,
const ScreenToParentLayerMatrix4x4& aTransformToApzc);
/**
--- a/gfx/layers/apz/src/InputBlockState.cpp
+++ b/gfx/layers/apz/src/InputBlockState.cpp
@@ -286,17 +286,17 @@ DragBlockState::SetDragMetrics(const Asy
void
DragBlockState::DispatchEvent(const InputData& aEvent) const
{
MouseInput mouseInput = aEvent.AsMouseInput();
if (!mouseInput.TransformToLocal(mTransformToApzc)) {
return;
}
- GetTargetApzc()->HandleDragEvent(mouseInput, mDragMetrics);
+ GetTargetApzc()->HandleDragEvent(mouseInput, mDragMetrics, mInitialThumbPos);
}
bool
DragBlockState::MustStayActive()
{
return !mReceivedMouseUp;
}
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -637,16 +637,18 @@ private:
MouseWheelRootScrollHorizontalFactor, int32_t, 0);
DECL_GFX_PREF(Live, "mousewheel.system_scroll_override_on_root_content.vertical.factor",
MouseWheelRootScrollVerticalFactor, int32_t, 0);
DECL_GFX_PREF(Live, "mousewheel.transaction.ignoremovedelay",MouseWheelIgnoreMoveDelayMs, int32_t, (int32_t)100);
DECL_GFX_PREF(Live, "mousewheel.transaction.timeout", MouseWheelTransactionTimeoutMs, int32_t, (int32_t)1500);
DECL_GFX_PREF(Live, "nglayout.debug.widget_update_flashing", WidgetUpdateFlashing, bool, false);
+ DECL_GFX_PREF(Once, "slider.snapMultiplier", SliderSnapMultiplier, int32_t, 0);
+
DECL_GFX_PREF(Live, "test.events.async.enabled", TestEventsAsyncEnabled, bool, false);
DECL_GFX_PREF(Live, "test.mousescroll", MouseScrollTestingEnabled, bool, false);
DECL_GFX_PREF(Live, "ui.click_hold_context_menus.delay", UiClickHoldContextMenusDelay, int32_t, 500);
// WebGL (for pref access from Worker threads)
DECL_GFX_PREF(Live, "webgl.all-angle-options", WebGLAllANGLEOptions, bool, false);
DECL_GFX_PREF(Live, "webgl.angle.force-d3d11", WebGLANGLEForceD3D11, bool, false);