Add APZ handling for desktop scroll wheel events. (bug 1086162 part 1, r=kats)

This commit is contained in:
David Anderson 2014-11-17 20:56:18 -08:00
parent 440327dce2
commit 028b163679
8 changed files with 189 additions and 5 deletions

View File

@ -394,10 +394,10 @@ struct ParamTraits<nsIntPoint>
}
};
template<>
struct ParamTraits<mozilla::gfx::IntSize>
template<typename T>
struct ParamTraits<mozilla::gfx::IntSizeTyped<T> >
{
typedef mozilla::gfx::IntSize paramType;
typedef mozilla::gfx::IntSizeTyped<T> paramType;
static void Write(Message* msg, const paramType& param)
{
@ -756,6 +756,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
WriteParam(aMsg, aParam.mBackgroundColor);
WriteParam(aMsg, aParam.mDoSmoothScroll);
WriteParam(aMsg, aParam.mSmoothScrollOffset);
WriteParam(aMsg, aParam.GetLineScrollAmount());
WriteParam(aMsg, aParam.GetContentDescription());
}
@ -797,6 +798,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
ReadParam(aMsg, aIter, &aResult->mBackgroundColor) &&
ReadParam(aMsg, aIter, &aResult->mDoSmoothScroll) &&
ReadParam(aMsg, aIter, &aResult->mSmoothScrollOffset) &&
ReadParam(aMsg, aIter, &aResult->mLineScrollAmount) &&
ReadContentDescription(aMsg, aIter, aResult));
}
};

View File

@ -65,6 +65,7 @@ public:
, mViewport(0, 0, 0, 0)
, mExtraResolution(1)
, mBackgroundColor(0, 0, 0, 0)
, mLineScrollAmount(0, 0)
{
}
@ -95,7 +96,8 @@ public:
mUpdateScrollOffset == aOther.mUpdateScrollOffset &&
mExtraResolution == aOther.mExtraResolution &&
mBackgroundColor == aOther.mBackgroundColor &&
mDoSmoothScroll == aOther.mDoSmoothScroll;
mDoSmoothScroll == aOther.mDoSmoothScroll &&
mLineScrollAmount == aOther.mLineScrollAmount;
}
bool operator!=(const FrameMetrics& aOther) const
{
@ -514,6 +516,16 @@ public:
mMayHaveTouchListeners = aMayHaveTouchListeners;
}
const LayoutDeviceIntSize& GetLineScrollAmount() const
{
return mLineScrollAmount;
}
void SetLineScrollAmount(const LayoutDeviceIntSize& size)
{
mLineScrollAmount = size;
}
private:
// New fields from now on should be made private and old fields should
// be refactored to be private.
@ -605,6 +617,9 @@ private:
// This is empty unless this is a scrollable layer and the
// apz.printtree pref is turned on.
nsCString mContentDescription;
// The value of GetLineScrollAmount(), for scroll frames.
LayoutDeviceIntSize mLineScrollAmount;
};
/**

View File

@ -611,6 +611,29 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
MultiTouchInput& touchInput = aEvent.AsMultiTouchInput();
result = ProcessTouchInput(touchInput, aOutTargetGuid, aOutInputBlockId);
break;
} case SCROLLWHEEL_INPUT: {
ScrollWheelInput& wheelInput = aEvent.AsScrollWheelInput();
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(wheelInput.mOrigin,
&hitResult);
if (apzc) {
MOZ_ASSERT(hitResult == ApzcHitRegion || hitResult == ApzcContentRegion);
transformToApzc = GetScreenToApzcTransform(apzc);
wheelInput.mLocalOrigin =
TransformTo<ParentLayerPixel>(transformToApzc, wheelInput.mOrigin);
result = mInputQueue->ReceiveInputEvent(
apzc,
/* aTargetConfirmed = */ hitResult,
wheelInput, aOutInputBlockId);
// Update the out-parameters so they are what the caller expects.
apzc->GetGuid(aOutTargetGuid);
Matrix4x4 transformToGecko = transformToApzc * GetApzcToGeckoTransform(apzc);
wheelInput.mOrigin =
TransformTo<ScreenPixel>(transformToGecko, wheelInput.mLocalOrigin);
}
break;
} case PANGESTURE_INPUT: {
PanGestureInput& panInput = aEvent.AsPanGestureInput();
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(panInput.mPanStartPoint,

View File

@ -1070,6 +1070,11 @@ nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent)
}
break;
}
case SCROLLWHEEL_INPUT: {
const ScrollWheelInput& scrollInput = aEvent.AsScrollWheelInput();
rv = OnScrollWheel(scrollInput);
break;
}
default: return HandleGestureEvent(aEvent);
}
@ -1453,6 +1458,72 @@ AsyncPanZoomController::ConvertToGecko(const ParentLayerPoint& aPoint, CSSPoint*
return false;
}
nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEvent)
{
double deltaX = aEvent.mDeltaX;
double deltaY = aEvent.mDeltaY;
switch (aEvent.mDeltaType) {
case ScrollWheelInput::SCROLLDELTA_LINE: {
LayoutDeviceIntSize scrollAmount = mFrameMetrics.GetLineScrollAmount();
deltaX *= scrollAmount.width;
deltaY *= scrollAmount.height;
break;
}
default:
MOZ_ASSERT_UNREACHABLE("unexpected scroll delta type");
return nsEventStatus_eConsumeNoDefault;
}
switch (aEvent.mScrollMode) {
case ScrollWheelInput::SCROLLMODE_INSTANT: {
// Decompose into pan events for simplicity.
PanGestureInput start(PanGestureInput::PANGESTURE_START, aEvent.mTime, aEvent.mTimeStamp,
aEvent.mOrigin, ScreenPoint(0, 0), aEvent.modifiers);
start.mLocalPanStartPoint = aEvent.mLocalOrigin;
OnPanBegin(start);
// Pan gestures use natural directions which are inverted from scroll
// wheel and touchpad scroll gestures, so we invert x/y here. Since the
// zoom includes any device : css pixel zoom, we convert to CSS pixels
// before applying the zoom.
LayoutDevicePoint devicePixelDelta(-deltaX, -deltaY);
ParentLayerPoint delta = (devicePixelDelta / mFrameMetrics.mDevPixelsPerCSSPixel) *
mFrameMetrics.GetZoom();
PanGestureInput move(PanGestureInput::PANGESTURE_PAN, aEvent.mTime, aEvent.mTimeStamp,
aEvent.mOrigin,
ToScreenCoordinates(delta, aEvent.mLocalOrigin),
aEvent.modifiers);
move.mLocalPanStartPoint = aEvent.mLocalOrigin;
move.mLocalPanDisplacement = delta;
OnPan(move, false);
PanGestureInput end(PanGestureInput::PANGESTURE_END, aEvent.mTime, aEvent.mTimeStamp,
aEvent.mOrigin, ScreenPoint(0, 0), aEvent.modifiers);
end.mLocalPanStartPoint = aEvent.mLocalOrigin;
OnPanEnd(start);
break;
}
case ScrollWheelInput::SCROLLMODE_SMOOTH: {
CSSPoint delta = LayoutDevicePoint(deltaX, deltaY) / mFrameMetrics.mDevPixelsPerCSSPixel;
// If we're already in a smooth scroll animation, don't cancel it. This
// lets us preserve the existing scrolling velocity.
if (mState != SMOOTH_SCROLL) {
CancelAnimation();
mFrameMetrics.SetSmoothScrollOffset(mFrameMetrics.GetScrollOffset() + delta);
} else {
mFrameMetrics.SetSmoothScrollOffset(mFrameMetrics.GetSmoothScrollOffset() + delta);
}
StartSmoothScroll();
break;
}
}
return nsEventStatus_eConsumeNoDefault;
}
nsEventStatus AsyncPanZoomController::OnPanMayBegin(const PanGestureInput& aEvent) {
APZC_LOG("%p got a pan-maybegin in state %d\n", this, mState);

View File

@ -414,6 +414,11 @@ protected:
nsEventStatus OnPanMomentumStart(const PanGestureInput& aEvent);
nsEventStatus OnPanMomentumEnd(const PanGestureInput& aEvent);
/**
* Helper methods for handling scroll wheel events.
*/
nsEventStatus OnScrollWheel(const ScrollWheelInput& aEvent);
/**
* Helper methods for long press gestures.
*/

View File

@ -236,6 +236,12 @@ struct LayoutDevicePixel {
return FromUntyped(aRect.ToNearestPixels(aAppUnitsPerDevPixel));
}
static LayoutDeviceIntSize FromAppUnitsRounded(const nsSize& aSize, nscoord aAppUnitsPerDevPixel) {
return LayoutDeviceIntSize(
NSAppUnitsToIntPixels(aSize.width, aAppUnitsPerDevPixel),
NSAppUnitsToIntPixels(aSize.height, aAppUnitsPerDevPixel));
}
static nsSize ToAppUnits(const LayoutDeviceIntSize& aSize, nscoord aAppUnitsPerDevPixel) {
return nsSize(aSize.width * aAppUnitsPerDevPixel,
aSize.height * aAppUnitsPerDevPixel);

View File

@ -723,6 +723,11 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame,
if (lastSmoothScrollOrigin) {
metrics.SetSmoothScrollOffsetUpdated(scrollableFrame->CurrentScrollGeneration());
}
nsSize lineScrollAmount = scrollableFrame->GetLineScrollAmount();
LayoutDeviceIntSize lineScrollAmountInDevPixels =
LayoutDeviceIntSize::FromAppUnitsRounded(lineScrollAmount, presContext->AppUnitsPerDevPixel());
metrics.SetLineScrollAmount(lineScrollAmountInDevPixels);
}
metrics.SetScrollId(scrollId);

View File

@ -27,13 +27,15 @@ enum InputType
MULTITOUCH_INPUT,
PANGESTURE_INPUT,
PINCHGESTURE_INPUT,
TAPGESTURE_INPUT
TAPGESTURE_INPUT,
SCROLLWHEEL_INPUT
};
class MultiTouchInput;
class PanGestureInput;
class PinchGestureInput;
class TapGestureInput;
class ScrollWheelInput;
// This looks unnecessary now, but as we add more and more classes that derive
// from InputType (eventually probably almost as many as *Events.h has), it
@ -72,6 +74,7 @@ public:
INPUTDATA_AS_CHILD_TYPE(PanGestureInput, PANGESTURE_INPUT)
INPUTDATA_AS_CHILD_TYPE(PinchGestureInput, PINCHGESTURE_INPUT)
INPUTDATA_AS_CHILD_TYPE(TapGestureInput, TAPGESTURE_INPUT)
INPUTDATA_AS_CHILD_TYPE(ScrollWheelInput, SCROLLWHEEL_INPUT)
InputData()
{
@ -431,6 +434,60 @@ public:
ParentLayerPoint mLocalPoint;
};
// Encapsulation class for scroll-wheel events. These are generated by mice
// with physical scroll wheels, and on Windows by most touchpads when using
// scroll gestures.
class ScrollWheelInput : public InputData
{
public:
enum ScrollDeltaType
{
// There are three kinds of scroll delta modes in Gecko: "page", "line" and
// "pixel". For apz, we currently only support "line" mode.
SCROLLDELTA_LINE
};
enum ScrollMode
{
SCROLLMODE_INSTANT,
SCROLLMODE_SMOOTH
};
ScrollWheelInput(uint32_t aTime,
TimeStamp aTimeStamp,
Modifiers aModifiers,
ScrollMode aScrollMode,
ScrollDeltaType aDeltaType,
const ScreenPoint& aOrigin,
double aDeltaX,
double aDeltaY)
: InputData(SCROLLWHEEL_INPUT, aTime, aTimeStamp, aModifiers),
mDeltaType(aDeltaType),
mScrollMode(aScrollMode),
mOrigin(aOrigin),
mDeltaX(aDeltaX),
mDeltaY(aDeltaY)
{}
ScrollDeltaType mDeltaType;
ScrollMode mScrollMode;
ScreenPoint mOrigin;
// Deltas are in units corresponding to the delta type. For line deltas, they
// are the number of line units to scroll. The number of device pixels for a
// horizontal and vertical line unit are in FrameMetrics::mLineScrollAmount.
//
// The horizontal (X) delta is > 0 for scrolling right and < 0 for scrolling
// left. The vertical (Y) delta is < 0 for scrolling up and > 0 for
// scrolling down.
double mDeltaX;
double mDeltaY;
// The location of the scroll in local coordinates. This is set and used by
// APZ.
ParentLayerPoint mLocalOrigin;
};
}
#endif // InputData_h__