--- a/gfx/layers/apz/src/AsyncPanZoomAnimation.h
+++ b/gfx/layers/apz/src/AsyncPanZoomAnimation.h
@@ -13,16 +13,17 @@
#include "FrameMetrics.h"
#include "nsISupportsImpl.h"
#include "nsTArray.h"
namespace mozilla {
namespace layers {
class WheelScrollAnimation;
+class KeyboardScrollAnimation;
class SmoothScrollAnimation;
class AsyncPanZoomAnimation {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomAnimation)
public:
explicit AsyncPanZoomAnimation()
{ }
@@ -45,16 +46,19 @@ public:
/**
* Get the deferred tasks in |mDeferredTasks| and place them in |aTasks|. See
* |mDeferredTasks| for more information. Clears |mDeferredTasks|.
*/
nsTArray<RefPtr<Runnable>> TakeDeferredTasks() {
return Move(mDeferredTasks);
}
+ virtual KeyboardScrollAnimation* AsKeyboardScrollAnimation() {
+ return nullptr;
+ }
virtual WheelScrollAnimation* AsWheelScrollAnimation() {
return nullptr;
}
virtual SmoothScrollAnimation* AsSmoothScrollAnimation() {
return nullptr;
}
virtual bool WantsRepaints() {
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -72,16 +72,17 @@
#include "nsStyleStruct.h" // for nsTimingFunction
#include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc
#include "nsThreadUtils.h" // for NS_IsMainThread
#include "nsViewportInfo.h" // for kViewportMinScale, kViewportMaxScale
#include "prsystem.h" // for PR_GetPhysicalMemorySize
#include "SharedMemoryBasic.h" // for SharedMemoryBasic
#include "ScrollSnap.h" // for ScrollSnapUtils
#include "WheelScrollAnimation.h"
+#include "KeyboardScrollAnimation.h"
#if defined(MOZ_WIDGET_ANDROID)
#include "AndroidAPZ.h"
#include "mozilla/layers/AndroidDynamicToolbarAnimator.h"
#endif // defined(MOZ_WIDGET_ANDROID)
#define ENABLE_APZC_LOGGING 0
// #define ENABLE_APZC_LOGGING 1
@@ -999,16 +1000,21 @@ nsEventStatus AsyncPanZoomController::Ha
TapGestureInput tapInput = aEvent.AsTapGestureInput();
if (!tapInput.TransformToLocal(aTransformToApzc)) {
return rv;
}
rv = HandleGestureEvent(tapInput);
break;
}
+ case KEYBOARD_INPUT: {
+ KeyboardInput keyInput = aEvent.AsKeyboardInput();
+ rv = OnKeyboard(keyInput);
+ break;
+ }
case SENTINEL_INPUT: {
MOZ_ASSERT_UNREACHABLE("Invalid value");
break;
}
}
return rv;
}
@@ -1061,16 +1067,17 @@ nsEventStatus AsyncPanZoomController::On
ParentLayerPoint point = GetFirstTouchPoint(aEvent);
switch (mState) {
case FLING:
case ANIMATING_ZOOM:
case SMOOTH_SCROLL:
case OVERSCROLL_ANIMATION:
case WHEEL_SCROLL:
+ case KEYBOARD_SCROLL:
case PAN_MOMENTUM:
MOZ_ASSERT(GetCurrentTouchBlock());
GetCurrentTouchBlock()->GetOverscrollHandoffChain()->CancelAnimations(ExcludeOverscroll);
MOZ_FALLTHROUGH;
case NOTHING: {
mX.StartTouch(point.x, aEvent.mTime);
mY.StartTouch(point.y, aEvent.mTime);
if (RefPtr<GeckoContentController> controller = GetGeckoContentController()) {
@@ -1136,16 +1143,17 @@ nsEventStatus AsyncPanZoomController::On
return nsEventStatus_eConsumeNoDefault;
case PINCHING:
// The scale gesture listener should have handled this.
NS_WARNING("Gesture listener should have handled pinching in OnTouchMove.");
return nsEventStatus_eIgnore;
case WHEEL_SCROLL:
+ case KEYBOARD_SCROLL:
case OVERSCROLL_ANIMATION:
// Should not receive a touch-move in the OVERSCROLL_ANIMATION state
// as touch blocks that begin in an overscrolled state cancel the
// animation. The same is true for wheel scroll animations.
NS_WARNING("Received impossible touch in OnTouchMove");
break;
}
@@ -1216,16 +1224,17 @@ nsEventStatus AsyncPanZoomController::On
}
case PINCHING:
SetState(NOTHING);
// Scale gesture listener should have handled this.
NS_WARNING("Gesture listener should have handled pinching in OnTouchEnd.");
return nsEventStatus_eIgnore;
case WHEEL_SCROLL:
+ case KEYBOARD_SCROLL:
case OVERSCROLL_ANIMATION:
// Should not receive a touch-end in the OVERSCROLL_ANIMATION state
// as touch blocks that begin in an overscrolled state cancel the
// animation. The same is true for WHEEL_SCROLL.
NS_WARNING("Received impossible touch in OnTouchEnd");
break;
}
@@ -1647,16 +1656,127 @@ AsyncPanZoomController::GetScrollWheelDe
delta.y = (delta.y >= 0)
? pageScrollSize.height
: -pageScrollSize.height;
}
return delta;
}
+nsEventStatus
+AsyncPanZoomController::OnKeyboard(const KeyboardInput& aEvent)
+{
+ // Calculate the destination for this keyboard scroll action
+ nsPoint destination = CSSPoint::ToAppUnits(GetKeyboardDestination(aEvent.mAction));
+
+ // The lock must be held across the entire update operation, so the
+ // compositor doesn't end the animation before we get a chance to
+ // update it.
+ ReentrantMonitorAutoEnter lock(mMonitor);
+
+ // Use a keyboard scroll animation to scroll, reusing an existing one if it exists
+ if (mState != KEYBOARD_SCROLL) {
+ CancelAnimation();
+ SetState(KEYBOARD_SCROLL);
+
+ nsPoint initialPosition = CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset());
+ StartAnimation(new KeyboardScrollAnimation(*this, initialPosition, aEvent.mAction.mType));
+ }
+
+ // Cast velocity from ParentLayerPoints/ms to CSSPoints/ms then convert to
+ // appunits/second. We perform a cast to ParentLayerPoints/ms without a
+ // conversion so that the scroll duration isn't affected by zoom
+ nsPoint velocity =
+ CSSPoint::ToAppUnits(CSSPoint(mX.GetVelocity(), mY.GetVelocity())) * 1000.0f;
+
+ KeyboardScrollAnimation* animation = mAnimation->AsKeyboardScrollAnimation();
+ MOZ_ASSERT(animation);
+
+ animation->UpdateDestination(aEvent.mTimeStamp, destination, nsSize(velocity.x, velocity.y));
+
+ return nsEventStatus_eConsumeNoDefault;
+}
+
+CSSPoint
+AsyncPanZoomController::GetKeyboardDestination(const KeyboardScrollAction& aAction) const
+{
+ CSSSize lineScrollSize;
+ CSSSize pageScrollSize;
+ CSSPoint scrollOffset;
+ CSSRect scrollRect;
+
+ {
+ // Grab the lock to access the frame metrics.
+ ReentrantMonitorAutoEnter lock(mMonitor);
+
+ lineScrollSize = mScrollMetadata.GetLineScrollAmount() /
+ mFrameMetrics.GetDevPixelsPerCSSPixel();
+ pageScrollSize = mScrollMetadata.GetPageScrollAmount() /
+ mFrameMetrics.GetDevPixelsPerCSSPixel();
+
+ if (mState == WHEEL_SCROLL) {
+ scrollOffset = mAnimation->AsWheelScrollAnimation()->GetDestination();
+ } else if (mState == SMOOTH_SCROLL) {
+ scrollOffset = mAnimation->AsSmoothScrollAnimation()->GetDestination();
+ } else if (mState == KEYBOARD_SCROLL) {
+ scrollOffset = mAnimation->AsKeyboardScrollAnimation()->GetDestination();
+ } else {
+ scrollOffset = mFrameMetrics.GetScrollOffset();
+ }
+
+ scrollRect = mFrameMetrics.GetScrollableRect();
+ }
+
+ // Calculate the scroll destination based off of the scroll type and direction
+ CSSPoint scrollDestination = scrollOffset;
+
+ switch (aAction.mType) {
+ case KeyboardScrollAction::eScrollCharacter: {
+ int32_t scrollDistance = gfxPrefs::ToolkitHorizontalScrollDistance();
+
+ if (aAction.mForward) {
+ scrollDestination.x += scrollDistance * lineScrollSize.width;
+ } else {
+ scrollDestination.x -= scrollDistance * lineScrollSize.width;
+ }
+ break;
+ }
+ case KeyboardScrollAction::eScrollLine: {
+ int32_t scrollDistance = gfxPrefs::ToolkitVerticalScrollDistance();
+
+ if (aAction.mForward) {
+ scrollDestination.y += scrollDistance * lineScrollSize.height;
+ } else {
+ scrollDestination.y -= scrollDistance * lineScrollSize.height;
+ }
+ break;
+ }
+ case KeyboardScrollAction::eScrollPage: {
+ if (aAction.mForward) {
+ scrollDestination.y += pageScrollSize.height;
+ } else {
+ scrollDestination.y -= pageScrollSize.height;
+ }
+ break;
+ }
+ case KeyboardScrollAction::eScrollComplete: {
+ if (aAction.mForward) {
+ scrollDestination.y = scrollRect.YMost();
+ } else {
+ scrollDestination.y = scrollRect.y;
+ }
+ break;
+ }
+ case KeyboardScrollAction::eSentinel:
+ MOZ_ASSERT_UNREACHABLE("unexpected keyboard delta type");
+ }
+
+ return scrollDestination;
+}
+
// Return whether or not the underlying layer can be scrolled on either axis.
bool
AsyncPanZoomController::CanScroll(const InputData& aEvent) const
{
ParentLayerPoint delta;
if (aEvent.mInputType == SCROLLWHEEL_INPUT) {
delta = GetScrollWheelDelta(aEvent.AsScrollWheelInput());
} else if (aEvent.mInputType == PANGESTURE_INPUT) {
@@ -1813,16 +1933,18 @@ nsEventStatus AsyncPanZoomController::On
CSSPoint startPosition = mFrameMetrics.GetScrollOffset();
// If we're already in a wheel scroll or smooth scroll animation,
// the delta is applied to its destination, not to the current
// scroll position. Take this into account when finding a snap point.
if (mState == WHEEL_SCROLL) {
startPosition = mAnimation->AsWheelScrollAnimation()->GetDestination();
} else if (mState == SMOOTH_SCROLL) {
startPosition = mAnimation->AsSmoothScrollAnimation()->GetDestination();
+ } else if (mState == KEYBOARD_SCROLL) {
+ startPosition = mAnimation->AsKeyboardScrollAnimation()->GetDestination();
}
if (MaybeAdjustDeltaForScrollSnapping(aEvent, delta, startPosition)) {
// 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.
APZC_LOG("%p wheel scrolling to snap point %s\n", this, Stringify(startPosition).c_str());
SmoothScrollTo(startPosition);
break;
@@ -1836,17 +1958,18 @@ nsEventStatus AsyncPanZoomController::On
nsPoint initialPosition = CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset());
StartAnimation(new WheelScrollAnimation(
*this, initialPosition, aEvent.mDeltaType));
}
nsPoint deltaInAppUnits =
CSSPoint::ToAppUnits(delta / mFrameMetrics.GetZoom());
// Cast velocity from ParentLayerPoints/ms to CSSPoints/ms then convert to
- // appunits/second
+ // appunits/second. We perform a cast to ParentLayerPoints/ms without a
+ // conversion so that the scroll duration isn't affected by zoom
nsPoint velocity =
CSSPoint::ToAppUnits(CSSPoint(mX.GetVelocity(), mY.GetVelocity())) * 1000.0f;
WheelScrollAnimation* animation = mAnimation->AsWheelScrollAnimation();
animation->UpdateDelta(aEvent.mTimeStamp, deltaInAppUnits, nsSize(velocity.x, velocity.y));
break;
}
@@ -2593,17 +2716,18 @@ void AsyncPanZoomController::SmoothScrol
RefPtr<SmoothScrollAnimation> animation(
static_cast<SmoothScrollAnimation*>(mAnimation.get()));
animation->SetDestination(CSSPoint::ToAppUnits(aDestination));
} else {
CancelAnimation();
SetState(SMOOTH_SCROLL);
nsPoint initialPosition = CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset());
// Cast velocity from ParentLayerPoints/ms to CSSPoints/ms then convert to
- // appunits/second
+ // appunits/second. We perform a cast to ParentLayerPoints/ms without a
+ // conversion so that the scroll duration isn't affected by zoom
nsPoint initialVelocity = CSSPoint::ToAppUnits(CSSPoint(mX.GetVelocity(),
mY.GetVelocity())) * 1000.0f;
nsPoint destination = CSSPoint::ToAppUnits(aDestination);
StartAnimation(new SmoothScrollAnimation(*this,
initialPosition, initialVelocity,
destination,
gfxPrefs::ScrollBehaviorSpringConstant(),
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -56,16 +56,17 @@ class TouchBlockState;
class PanGestureBlockState;
class OverscrollHandoffChain;
class StateChangeNotificationBlocker;
class CheckerboardEvent;
class OverscrollEffectBase;
class WidgetOverscrollEffect;
class GenericOverscrollEffect;
class AndroidSpecificState;
+struct KeyboardScrollAction;
// Base class for grouping platform-specific APZC state variables.
class PlatformSpecificStateBase {
public:
virtual ~PlatformSpecificStateBase() {}
virtual AndroidSpecificState* AsAndroidSpecificState() { return nullptr; }
};
@@ -478,16 +479,23 @@ protected:
/**
* Helper methods for handling scroll wheel events.
*/
nsEventStatus OnScrollWheel(const ScrollWheelInput& aEvent);
ParentLayerPoint GetScrollWheelDelta(const ScrollWheelInput& aEvent) const;
/**
+ * Helper methods for handling keyboard events.
+ */
+ nsEventStatus OnKeyboard(const KeyboardInput& aEvent);
+
+ CSSPoint GetKeyboardDestination(const KeyboardScrollAction& aAction) const;
+
+ /**
* Helper methods for long press gestures.
*/
nsEventStatus OnLongPress(const TapGestureInput& aEvent);
nsEventStatus OnLongPressUp(const TapGestureInput& aEvent);
/**
* Helper method for single tap gestures.
*/
@@ -834,17 +842,18 @@ protected:
PAN_MOMENTUM, /* like PANNING, but controlled by momentum PanGestureInput events */
PINCHING, /* nth touch-start, where n > 1. this mode allows pan and zoom */
ANIMATING_ZOOM, /* animated zoom to a new rect */
OVERSCROLL_ANIMATION, /* Spring-based animation used to relieve overscroll once
the finger is lifted. */
SMOOTH_SCROLL, /* Smooth scrolling to destination. Used by
CSSOM-View smooth scroll-behavior */
- WHEEL_SCROLL /* Smooth scrolling to a destination for a wheel event. */
+ WHEEL_SCROLL, /* Smooth scrolling to a destination for a wheel event. */
+ KEYBOARD_SCROLL /* Smooth scrolling to a destination for a keyboard event. */
};
// This is in theory protected by |mMonitor|; that is, it should be held whenever
// this is updated. In practice though... see bug 897017.
PanZoomState mState;
private:
friend class StateChangeNotificationBlocker;
@@ -933,16 +942,17 @@ public:
private:
friend class AndroidFlingAnimation;
friend class GenericFlingAnimation;
friend class OverscrollAnimation;
friend class SmoothScrollAnimation;
friend class GenericScrollAnimation;
friend class WheelScrollAnimation;
+ friend class KeyboardScrollAnimation;
friend class GenericOverscrollEffect;
friend class WidgetOverscrollEffect;
// The initial velocity of the most recent fling.
ParentLayerPoint mLastFlingVelocity;
// The time at which the most recent fling started.
TimeStamp mLastFlingTime;
--- a/gfx/layers/apz/src/GenericScrollAnimation.cpp
+++ b/gfx/layers/apz/src/GenericScrollAnimation.cpp
@@ -20,22 +20,36 @@ GenericScrollAnimation::GenericScrollAni
, mFinalDestination(aInitialPosition)
, mForceVerticalOverscroll(false)
{
}
void
GenericScrollAnimation::UpdateDelta(TimeStamp aTime, nsPoint aDelta, const nsSize& aCurrentVelocity)
{
+ mFinalDestination += aDelta;
+
+ Update(aTime, aCurrentVelocity);
+}
+
+void
+GenericScrollAnimation::UpdateDestination(TimeStamp aTime, nsPoint aDestination, const nsSize& aCurrentVelocity)
+{
+ mFinalDestination = aDestination;
+
+ Update(aTime, aCurrentVelocity);
+}
+
+void
+GenericScrollAnimation::Update(TimeStamp aTime, const nsSize& aCurrentVelocity)
+{
if (mIsFirstIteration) {
InitializeHistory(aTime);
}
- mFinalDestination += aDelta;
-
// 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);
AsyncScrollBase::Update(aTime, mFinalDestination, aCurrentVelocity);
}
--- a/gfx/layers/apz/src/GenericScrollAnimation.h
+++ b/gfx/layers/apz/src/GenericScrollAnimation.h
@@ -19,22 +19,27 @@ class GenericScrollAnimation
: public AsyncPanZoomAnimation,
public AsyncScrollBase
{
public:
GenericScrollAnimation(AsyncPanZoomController& aApzc,
const nsPoint& aInitialPosition);
bool DoSample(FrameMetrics& aFrameMetrics, const TimeDuration& aDelta) override;
+
void UpdateDelta(TimeStamp aTime, nsPoint aDelta, const nsSize& aCurrentVelocity);
+ void UpdateDestination(TimeStamp aTime, nsPoint aDestination, const nsSize& aCurrentVelocity);
CSSPoint GetDestination() const {
return CSSPoint::FromAppUnits(mFinalDestination);
}
+private:
+ void Update(TimeStamp aTime, const nsSize& aCurrentVelocity);
+
protected:
AsyncPanZoomController& mApzc;
nsPoint mFinalDestination;
bool mForceVerticalOverscroll;
};
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/apz/src/Keyboard.cpp
+++ b/gfx/layers/apz/src/Keyboard.cpp
@@ -5,46 +5,16 @@
#include "mozilla/layers/Keyboard.h"
#include "mozilla/TextEvents.h" // for IgnoreModifierState, ShortcutKeyCandidate
namespace mozilla {
namespace layers {
-/* static */ nsIScrollableFrame::ScrollUnit
-KeyboardScrollAction::GetScrollUnit(KeyboardScrollAction::KeyboardScrollActionType aDeltaType)
-{
- switch (aDeltaType) {
- case KeyboardScrollAction::eScrollCharacter:
- return nsIScrollableFrame::LINES;
- case KeyboardScrollAction::eScrollLine:
- return nsIScrollableFrame::LINES;
- case KeyboardScrollAction::eScrollPage:
- return nsIScrollableFrame::PAGES;
- case KeyboardScrollAction::eScrollComplete:
- return nsIScrollableFrame::WHOLE;
- case KeyboardScrollAction::eSentinel:
- MOZ_ASSERT_UNREACHABLE("Invalid KeyboardScrollActionType.");
- return nsIScrollableFrame::WHOLE;
- }
-}
-
-KeyboardScrollAction::KeyboardScrollAction()
- : mType(KeyboardScrollAction::eScrollCharacter)
- , mForward(false)
-{
-}
-
-KeyboardScrollAction::KeyboardScrollAction(KeyboardScrollActionType aType, bool aForward)
- : mType(aType)
- , mForward(aForward)
-{
-}
-
KeyboardShortcut::KeyboardShortcut()
{
}
KeyboardShortcut::KeyboardShortcut(KeyboardInput::KeyboardEventType aEventType,
uint32_t aKeyCode,
uint32_t aCharCode,
Modifiers aModifiers,
--- a/gfx/layers/apz/src/Keyboard.h
+++ b/gfx/layers/apz/src/Keyboard.h
@@ -7,55 +7,27 @@
#define mozilla_layers_Keyboard_h
#include <stdint.h> // for uint32_t
#include "InputData.h" // for KeyboardInput
#include "nsIScrollableFrame.h" // for nsIScrollableFrame::ScrollUnit
#include "nsTArray.h" // for nsTArray
#include "mozilla/Maybe.h" // for mozilla::Maybe
+#include "KeyboardScrollAction.h" // for KeyboardScrollAction
namespace mozilla {
struct IgnoreModifierState;
namespace layers {
class KeyboardMap;
/**
- * This class represents a scrolling action to be performed on a scrollable layer.
- */
-struct KeyboardScrollAction final
-{
-public:
- enum KeyboardScrollActionType : uint8_t
- {
- eScrollCharacter,
- eScrollLine,
- eScrollPage,
- eScrollComplete,
-
- // Used as an upper bound for ContiguousEnumSerializer
- eSentinel,
- };
-
- static nsIScrollableFrame::ScrollUnit
- GetScrollUnit(KeyboardScrollActionType aDeltaType);
-
- KeyboardScrollAction();
- KeyboardScrollAction(KeyboardScrollActionType aType, bool aForward);
-
- // The type of scroll to perform for this action
- KeyboardScrollActionType mType;
- // Whether to scroll forward or backward along the axis of this action type
- bool mForward;
-};
-
-/**
* This class is an off main-thread <xul:handler> for scrolling commands.
*/
class KeyboardShortcut final
{
public:
KeyboardShortcut();
/**
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/src/KeyboardScrollAction.cpp
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "mozilla/layers/KeyboardScrollAction.h"
+
+namespace mozilla {
+namespace layers {
+
+/* static */ nsIScrollableFrame::ScrollUnit
+KeyboardScrollAction::GetScrollUnit(KeyboardScrollAction::KeyboardScrollActionType aDeltaType)
+{
+ switch (aDeltaType) {
+ case KeyboardScrollAction::eScrollCharacter:
+ return nsIScrollableFrame::LINES;
+ case KeyboardScrollAction::eScrollLine:
+ return nsIScrollableFrame::LINES;
+ case KeyboardScrollAction::eScrollPage:
+ return nsIScrollableFrame::PAGES;
+ case KeyboardScrollAction::eScrollComplete:
+ return nsIScrollableFrame::WHOLE;
+ case KeyboardScrollAction::eSentinel:
+ MOZ_ASSERT_UNREACHABLE("Invalid KeyboardScrollActionType.");
+ return nsIScrollableFrame::WHOLE;
+ }
+}
+
+KeyboardScrollAction::KeyboardScrollAction()
+ : mType(KeyboardScrollAction::eScrollCharacter)
+ , mForward(false)
+{
+}
+
+KeyboardScrollAction::KeyboardScrollAction(KeyboardScrollActionType aType, bool aForward)
+ : mType(aType)
+ , mForward(aForward)
+{
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/src/KeyboardScrollAction.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef mozilla_layers_KeyboardScrollAction_h
+#define mozilla_layers_KeyboardScrollAction_h
+
+#include "nsIScrollableFrame.h" // for nsIScrollableFrame::ScrollUnit
+
+namespace mozilla {
+namespace layers {
+
+/**
+ * This class represents a scrolling action to be performed on a scrollable layer.
+ */
+struct KeyboardScrollAction final
+{
+public:
+ enum KeyboardScrollActionType : uint8_t
+ {
+ eScrollCharacter,
+ eScrollLine,
+ eScrollPage,
+ eScrollComplete,
+
+ // Used as an upper bound for ContiguousEnumSerializer
+ eSentinel,
+ };
+
+ static nsIScrollableFrame::ScrollUnit
+ GetScrollUnit(KeyboardScrollActionType aDeltaType);
+
+ KeyboardScrollAction();
+ KeyboardScrollAction(KeyboardScrollActionType aType, bool aForward);
+
+ // The type of scroll to perform for this action
+ KeyboardScrollActionType mType;
+ // Whether to scroll forward or backward along the axis of this action type
+ bool mForward;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif // mozilla_layers_KeyboardScrollAction_h
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/src/KeyboardScrollAnimation.cpp
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* 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 "KeyboardScrollAnimation.h"
+
+#include "gfxPrefs.h"
+
+namespace mozilla {
+namespace layers {
+
+KeyboardScrollAnimation::KeyboardScrollAnimation(AsyncPanZoomController& aApzc,
+ const nsPoint& aInitialPosition,
+ KeyboardScrollAction::KeyboardScrollActionType aType)
+ : GenericScrollAnimation(aApzc, aInitialPosition)
+{
+ switch (aType) {
+ case KeyboardScrollAction::eScrollCharacter:
+ case KeyboardScrollAction::eScrollLine: {
+ mOriginMaxMS = clamped(gfxPrefs::LineSmoothScrollMaxDurationMs(), 0, 10000);
+ mOriginMinMS = clamped(gfxPrefs::LineSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+ break;
+ }
+ case KeyboardScrollAction::eScrollPage: {
+ mOriginMaxMS = clamped(gfxPrefs::PageSmoothScrollMaxDurationMs(), 0, 10000);
+ mOriginMinMS = clamped(gfxPrefs::PageSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+ break;
+ }
+ case KeyboardScrollAction::eScrollComplete: {
+ mOriginMaxMS = clamped(gfxPrefs::OtherSmoothScrollMaxDurationMs(), 0, 10000);
+ mOriginMinMS = clamped(gfxPrefs::OtherSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+ break;
+ }
+ case KeyboardScrollAction::eSentinel: {
+ MOZ_ASSERT_UNREACHABLE("Invalid KeyboardScrollActionType.");
+ }
+ }
+
+ // The pref is 100-based int percentage, while mIntervalRatio is 1-based ratio
+ mIntervalRatio = ((double)gfxPrefs::SmoothScrollDurationToIntervalRatio()) / 100.0;
+ mIntervalRatio = std::max(1.0, mIntervalRatio);
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/src/KeyboardScrollAnimation.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* 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/. */
+
+#ifndef mozilla_layers_KeyboardScrollAnimation_h_
+#define mozilla_layers_KeyboardScrollAnimation_h_
+
+#include "GenericScrollAnimation.h"
+#include "mozilla/layers/Keyboard.h"
+
+namespace mozilla {
+namespace layers {
+
+class AsyncPanZoomController;
+
+class KeyboardScrollAnimation
+ : public GenericScrollAnimation
+{
+public:
+ KeyboardScrollAnimation(AsyncPanZoomController& aApzc,
+ const nsPoint& aInitialPosition,
+ KeyboardScrollAction::KeyboardScrollActionType aType);
+
+ KeyboardScrollAnimation* AsKeyboardScrollAnimation() override {
+ return this;
+ }
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif // mozilla_layers_KeyboardScrollAnimation_h_
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -98,16 +98,17 @@ EXPORTS.mozilla.layers += [
# proper interface for the code there
'apz/src/APZCTreeManager.h',
'apz/src/APZUtils.h',
'apz/src/AsyncDragMetrics.h',
'apz/src/AsyncPanZoomAnimation.h',
'apz/src/FocusState.h',
'apz/src/FocusTarget.h',
'apz/src/Keyboard.h',
+ 'apz/src/KeyboardScrollAction.h',
'apz/src/TouchCounter.h',
'apz/testutil/APZTestData.h',
'apz/util/ActiveElementManager.h',
'apz/util/APZCCallbackHelper.h',
'apz/util/APZEventState.h',
'apz/util/APZThreadUtils.h',
'apz/util/ChromeProcessController.h',
'apz/util/ContentProcessController.h',
@@ -283,16 +284,18 @@ UNIFIED_SOURCES += [
'apz/src/FocusState.cpp',
'apz/src/FocusTarget.cpp',
'apz/src/GenericScrollAnimation.cpp',
'apz/src/GestureEventListener.cpp',
'apz/src/HitTestingTreeNode.cpp',
'apz/src/InputBlockState.cpp',
'apz/src/InputQueue.cpp',
'apz/src/Keyboard.cpp',
+ 'apz/src/KeyboardScrollAction.cpp',
+ 'apz/src/KeyboardScrollAnimation.cpp',
'apz/src/OverscrollHandoffState.cpp',
'apz/src/PotentialCheckerboardDurationTracker.cpp',
'apz/src/QueuedInput.cpp',
'apz/src/TouchCounter.cpp',
'apz/src/WheelScrollAnimation.cpp',
'apz/testutil/APZTestData.cpp',
'apz/util/ActiveElementManager.cpp',
'apz/util/APZCCallbackHelper.cpp',
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -361,21 +361,30 @@ private:
DECL_GFX_PREF(Live, "dom.w3c_pointer_events.enabled", PointerEventsEnabled, bool, false);
DECL_GFX_PREF(Live, "dom.w3c_touch_events.enabled", TouchEventsEnabled, int32_t, 0);
DECL_GFX_PREF(Live, "general.smoothScroll", SmoothScrollEnabled, bool, true);
DECL_GFX_PREF(Live, "general.smoothScroll.currentVelocityWeighting",
SmoothScrollCurrentVelocityWeighting, float, 0.25);
DECL_GFX_PREF(Live, "general.smoothScroll.durationToIntervalRatio",
SmoothScrollDurationToIntervalRatio, int32_t, 200);
+ DECL_GFX_PREF(Live, "general.smoothScroll.lines", LineSmoothScrollEnabled, bool, true);
+ DECL_GFX_PREF(Live, "general.smoothScroll.lines.durationMaxMS",
+ LineSmoothScrollMaxDurationMs, int32_t, 150);
+ DECL_GFX_PREF(Live, "general.smoothScroll.lines.durationMinMS",
+ LineSmoothScrollMinDurationMs, int32_t, 150);
DECL_GFX_PREF(Live, "general.smoothScroll.mouseWheel", WheelSmoothScrollEnabled, bool, true);
DECL_GFX_PREF(Live, "general.smoothScroll.mouseWheel.durationMaxMS",
WheelSmoothScrollMaxDurationMs, int32_t, 400);
DECL_GFX_PREF(Live, "general.smoothScroll.mouseWheel.durationMinMS",
WheelSmoothScrollMinDurationMs, int32_t, 200);
+ DECL_GFX_PREF(Live, "general.smoothScroll.other.durationMaxMS",
+ OtherSmoothScrollMaxDurationMs, int32_t, 150);
+ DECL_GFX_PREF(Live, "general.smoothScroll.other.durationMinMS",
+ OtherSmoothScrollMinDurationMs, int32_t, 150);
DECL_GFX_PREF(Live, "general.smoothScroll.pages", PageSmoothScrollEnabled, bool, true);
DECL_GFX_PREF(Live, "general.smoothScroll.pages.durationMaxMS",
PageSmoothScrollMaxDurationMs, int32_t, 150);
DECL_GFX_PREF(Live, "general.smoothScroll.pages.durationMinMS",
PageSmoothScrollMinDurationMs, int32_t, 150);
DECL_GFX_PREF(Live, "general.smoothScroll.pixels", PixelSmoothScrollEnabled, bool, true);
DECL_GFX_PREF(Live, "general.smoothScroll.pixels.durationMaxMS",
PixelSmoothScrollMaxDurationMs, int32_t, 150);
@@ -646,16 +655,19 @@ private:
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, "toolkit.scrollbox.horizontalScrollDistance", ToolkitHorizontalScrollDistance, int32_t, 5);
+ DECL_GFX_PREF(Live, "toolkit.scrollbox.verticalScrollDistance", ToolkitVerticalScrollDistance, int32_t, 3);
+
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);
DECL_GFX_PREF(Live, "webgl.angle.try-d3d11", WebGLANGLETryD3D11, bool, false);
DECL_GFX_PREF(Live, "webgl.angle.force-warp", WebGLANGLEForceWARP, bool, false);
DECL_GFX_PREF(Live, "webgl.bypass-shader-validation", WebGLBypassShaderValidator, bool, true);
--- a/widget/InputData.h
+++ b/widget/InputData.h
@@ -10,16 +10,17 @@
#include "nsIDOMWheelEvent.h"
#include "nsIScrollableFrame.h"
#include "nsPoint.h"
#include "nsTArray.h"
#include "Units.h"
#include "mozilla/EventForwards.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/gfx/MatrixFwd.h"
+#include "mozilla/layers/KeyboardScrollAction.h"
template<class E> struct already_AddRefed;
class nsIWidget;
namespace mozilla {
namespace layers {
class PAPZCTreeManagerParent;
@@ -618,16 +619,18 @@ public:
bool mMayHaveMomentum;
bool mIsMomentum;
bool mAllowToOverrideSystemScrollSpeed;
};
class KeyboardInput : public InputData
{
public:
+ typedef mozilla::layers::KeyboardScrollAction KeyboardScrollAction;
+
enum KeyboardEventType
{
KEY_DOWN,
KEY_PRESS,
KEY_UP,
// Any other key event such as eKeyDownOnPlugin
KEY_OTHER,
@@ -642,16 +645,20 @@ public:
KeyboardEventType mType;
uint32_t mKeyCode;
uint32_t mCharCode;
nsTArray<ShortcutKeyCandidate> mShortcutCandidates;
bool mHandledByAPZ;
+ // The scroll action to perform on a layer for this keyboard input. This is
+ // only used in APZ and is NOT serialized over IPC.
+ KeyboardScrollAction mAction;
+
protected:
friend mozilla::layers::PAPZCTreeManagerParent;
friend mozilla::layers::APZCTreeManagerChild;
KeyboardInput();
};
} // namespace mozilla