Add APZ support for mousewheel.acceleration prefs. (bug 1214170 part 1, r=kats)

This commit is contained in:
David Anderson 2015-12-01 13:45:49 -08:00
parent 4ba22afe35
commit 5a4ffc917f
10 changed files with 65 additions and 17 deletions

View File

@ -21,6 +21,7 @@
#include "nsPresContext.h"
#include "prtime.h"
#include "Units.h"
#include "AsyncScrollBase.h"
namespace mozilla {
@ -137,7 +138,7 @@ WheelTransaction::UpdateTransaction(WidgetWheelEvent* aEvent)
SetTimeout();
if (sScrollSeriesCounter != 0 && OutOfTime(sTime, kScrollSeriesTimeout)) {
if (sScrollSeriesCounter != 0 && OutOfTime(sTime, kScrollSeriesTimeoutMs)) {
sScrollSeriesCounter = 0;
}
sScrollSeriesCounter++;
@ -383,14 +384,9 @@ WheelTransaction::AccelerateWheelDelta(WidgetWheelEvent* aEvent,
}
/* static */ double
WheelTransaction::ComputeAcceleratedWheelDelta(double aDelta,
int32_t aFactor)
WheelTransaction::ComputeAcceleratedWheelDelta(double aDelta, int32_t aFactor)
{
if (aDelta == 0.0) {
return 0;
}
return (aDelta * sScrollSeriesCounter * (double)aFactor / 10);
return mozilla::ComputeAcceleratedWheelDelta(aDelta, sScrollSeriesCounter, aFactor);
}
/* static */ int32_t

View File

@ -151,8 +151,6 @@ public:
bool aAllowScrollSpeedOverride);
protected:
static const uint32_t kScrollSeriesTimeout = 80; // in milliseconds
static void BeginTransaction(nsIFrame* aTargetFrame,
WidgetWheelEvent* aEvent);
// Be careful, UpdateTransaction may fire a DOM event, therefore, the target

View File

@ -625,8 +625,8 @@ static bool
WillHandleWheelEvent(WidgetWheelEvent* aEvent)
{
return EventStateManager::WheelEventIsScrollAction(aEvent) &&
(aEvent->deltaMode == nsIDOMWheelEvent::DOM_DELTA_LINE
|| aEvent->deltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL) &&
(aEvent->deltaMode == nsIDOMWheelEvent::DOM_DELTA_LINE ||
aEvent->deltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL) &&
!EventStateManager::WheelEventNeedsDeltaMultipliers(aEvent);
}

View File

@ -1616,6 +1616,21 @@ AsyncPanZoomController::GetScrollWheelDelta(const ScrollWheelInput& aEvent) cons
}
}
// If this is a line scroll, and this event was part of a scroll series, then
// it might need extra acceleration. See WheelHandlingHelper.cpp.
if (aEvent.mDeltaType == ScrollWheelInput::SCROLLDELTA_LINE &&
aEvent.mScrollSeriesNumber > 0)
{
int32_t start = gfxPrefs::MouseWheelAccelerationStart();
if (start >= 0 && aEvent.mScrollSeriesNumber >= uint32_t(start)) {
int32_t factor = gfxPrefs::MouseWheelAccelerationFactor();
if (factor > 0) {
delta.x = ComputeAcceleratedWheelDelta(delta.x, aEvent.mScrollSeriesNumber, factor);
delta.y = ComputeAcceleratedWheelDelta(delta.y, aEvent.mScrollSeriesNumber, factor);
}
}
}
if (Abs(delta.x) > pageScrollSize.width) {
delta.x = (delta.x >= 0)
? pageScrollSize.width

View File

@ -6,6 +6,7 @@
#include "InputBlockState.h"
#include "AsyncPanZoomController.h" // for AsyncPanZoomController
#include "AsyncScrollBase.h" // for kScrollSeriesTimeoutMs
#include "gfxPrefs.h" // for gfxPrefs
#include "mozilla/MouseEvents.h"
#include "mozilla/SizePrintfMacros.h" // for PRIuSIZE
@ -244,6 +245,7 @@ WheelBlockState::WheelBlockState(const RefPtr<AsyncPanZoomController>& aTargetAp
bool aTargetConfirmed,
const ScrollWheelInput& aInitialEvent)
: CancelableBlockState(aTargetApzc, aTargetConfirmed)
, mScrollSeriesCounter(0)
, mTransactionEnded(false)
{
sLastWheelBlockId = GetBlockId();
@ -295,7 +297,7 @@ WheelBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aT
}
void
WheelBlockState::Update(const ScrollWheelInput& aEvent)
WheelBlockState::Update(ScrollWheelInput& aEvent)
{
// We might not be in a transaction if the block never started in a
// transaction - for example, if nothing was scrollable.
@ -303,6 +305,18 @@ WheelBlockState::Update(const ScrollWheelInput& aEvent)
return;
}
// The current "scroll series" is a like a sub-transaction. It has a separate
// timeout of 80ms. Since we need to compute wheel deltas at different phases
// of a transaction (for example, when it is updated, and later when the
// event action is taken), we affix the scroll series counter to the event.
// This makes GetScrollWheelDelta() consistent.
if (!mLastEventTime.IsNull() &&
(aEvent.mTimeStamp - mLastEventTime).ToMilliseconds() > kScrollSeriesTimeoutMs)
{
mScrollSeriesCounter = 0;
}
aEvent.mScrollSeriesNumber = ++mScrollSeriesCounter;
// If we can't scroll in the direction of the wheel event, we don't update
// the last move time. This allows us to timeout a transaction even if the
// mouse isn't moving.

View File

@ -244,7 +244,7 @@ public:
/**
* Update the wheel transaction state for a new event.
*/
void Update(const ScrollWheelInput& aEvent);
void Update(ScrollWheelInput& aEvent);
protected:
void UpdateTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc) override;
@ -253,6 +253,7 @@ private:
nsTArray<ScrollWheelInput> mEvents;
TimeStamp mLastEventTime;
TimeStamp mLastMouseMove;
uint32_t mScrollSeriesCounter;
bool mTransactionEnded;
};

View File

@ -277,15 +277,17 @@ InputQueue::ReceiveScrollWheelInput(const RefPtr<AsyncPanZoomController>& aTarge
*aOutInputBlockId = block->GetBlockId();
}
block->Update(aEvent);
// Copy the event, since WheelBlockState needs to affix a counter.
ScrollWheelInput event(aEvent);
block->Update(event);
// Note that the |aTarget| the APZCTM sent us may contradict the confirmed
// target set on the block. In this case the confirmed target (which may be
// null) should take priority. This is equivalent to just always using the
// target (confirmed or not) from the block, which is what
// MaybeHandleCurrentBlock() does.
if (!MaybeHandleCurrentBlock(block, aEvent)) {
block->AddEvent(aEvent.AsScrollWheelInput());
if (!MaybeHandleCurrentBlock(block, event)) {
block->AddEvent(event);
}
return nsEventStatus_eConsumeDoDefault;

View File

@ -383,6 +383,10 @@ private:
// This and code dependent on it should be removed once containerless scrolling looks stable.
DECL_GFX_PREF(Once, "layout.scroll.root-frame-containers", LayoutUseContainersForRootFrames, bool, true);
// These affect how line scrolls from wheel events will be accelerated.
DECL_GFX_PREF(Live, "mousewheel.acceleration.factor", MouseWheelAccelerationFactor, int32_t, -1);
DECL_GFX_PREF(Live, "mousewheel.acceleration.start", MouseWheelAccelerationStart, int32_t, -1);
// This affects whether events will be routed through APZ or not.
DECL_GFX_PREF(Live, "mousewheel.system_scroll_override_on_root_content.enabled",
MouseWheelHasRootScrollDeltaOverride, bool, false);

View File

@ -87,6 +87,19 @@ protected:
nsSMILKeySpline mTimingFunctionY;
};
// Helper for accelerated wheel deltas. This can be called from the main thread
// or the APZ Controller thread.
static inline double
ComputeAcceleratedWheelDelta(double aDelta, int32_t aCounter, int32_t aFactor)
{
if (!aDelta) {
return aDelta;
}
return (aDelta * aCounter * double(aFactor) / 10);
}
static const uint32_t kScrollSeriesTimeoutMs = 80; // in milliseconds
} // namespace mozilla
#endif // mozilla_layout_AsyncScrollBase_h_

View File

@ -582,6 +582,7 @@ public:
mDeltaY(aDeltaY),
mLineOrPageDeltaX(0),
mLineOrPageDeltaY(0),
mScrollSeriesNumber(0),
mIsMomentum(false)
{}
@ -615,6 +616,10 @@ public:
int32_t mLineOrPageDeltaX;
int32_t mLineOrPageDeltaY;
// Indicates the order in which this event was added to a transaction. The
// first event is 1; if not a member of a transaction, this is 0.
uint32_t mScrollSeriesNumber;
bool mIsMomentum;
};