зеркало из https://github.com/mozilla/gecko-dev.git
Bug 951793 - Obey overscroll-behavior for wheel and pan gesture events. r=kats
MozReview-Commit-ID: EmbsMu9Esww --HG-- extra : rebase_source : f681f55f274757be4965e6c912e514e81e8b1c8f
This commit is contained in:
Родитель
15d10c1b0d
Коммит
bfb1cd4ddd
|
@ -11,6 +11,7 @@
|
||||||
#include "LayersTypes.h"
|
#include "LayersTypes.h"
|
||||||
#include "UnitTransforms.h"
|
#include "UnitTransforms.h"
|
||||||
#include "mozilla/gfx/Point.h"
|
#include "mozilla/gfx/Point.h"
|
||||||
|
#include "mozilla/EnumSet.h"
|
||||||
#include "mozilla/FloatingPoint.h"
|
#include "mozilla/FloatingPoint.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -42,6 +43,8 @@ operator|(CancelAnimationFlags a, CancelAnimationFlags b)
|
||||||
| static_cast<int>(b));
|
| static_cast<int>(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef EnumSet<ScrollDirection> ScrollDirections;
|
||||||
|
|
||||||
enum class ScrollSource {
|
enum class ScrollSource {
|
||||||
// scrollTo() or something similar.
|
// scrollTo() or something similar.
|
||||||
DOM,
|
DOM,
|
||||||
|
|
|
@ -1914,9 +1914,8 @@ AsyncPanZoomController::GetKeyboardDestination(const KeyboardScrollAction& aActi
|
||||||
return scrollDestination;
|
return scrollDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return whether or not the underlying layer can be scrolled on either axis.
|
ParentLayerPoint
|
||||||
bool
|
AsyncPanZoomController::GetDeltaForEvent(const InputData& aEvent) const
|
||||||
AsyncPanZoomController::CanScroll(const InputData& aEvent) const
|
|
||||||
{
|
{
|
||||||
ParentLayerPoint delta;
|
ParentLayerPoint delta;
|
||||||
if (aEvent.mInputType == SCROLLWHEEL_INPUT) {
|
if (aEvent.mInputType == SCROLLWHEEL_INPUT) {
|
||||||
|
@ -1925,6 +1924,14 @@ AsyncPanZoomController::CanScroll(const InputData& aEvent) const
|
||||||
const PanGestureInput& panInput = aEvent.AsPanGestureInput();
|
const PanGestureInput& panInput = aEvent.AsPanGestureInput();
|
||||||
delta = ToParentLayerCoordinates(panInput.UserMultipliedPanDisplacement(), panInput.mPanStartPoint);
|
delta = ToParentLayerCoordinates(panInput.UserMultipliedPanDisplacement(), panInput.mPanStartPoint);
|
||||||
}
|
}
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return whether or not the underlying layer can be scrolled on either axis.
|
||||||
|
bool
|
||||||
|
AsyncPanZoomController::CanScroll(const InputData& aEvent) const
|
||||||
|
{
|
||||||
|
ParentLayerPoint delta = GetDeltaForEvent(aEvent);
|
||||||
if (!delta.x && !delta.y) {
|
if (!delta.x && !delta.y) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1932,6 +1939,20 @@ AsyncPanZoomController::CanScroll(const InputData& aEvent) const
|
||||||
return CanScrollWithWheel(delta);
|
return CanScrollWithWheel(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScrollDirections
|
||||||
|
AsyncPanZoomController::GetAllowedHandoffDirections() const
|
||||||
|
{
|
||||||
|
ScrollDirections result;
|
||||||
|
RecursiveMutexAutoLock lock(mRecursiveMutex);
|
||||||
|
if (mX.OverscrollBehaviorAllowsHandoff()) {
|
||||||
|
result += ScrollDirection::eHorizontal;
|
||||||
|
}
|
||||||
|
if (mY.OverscrollBehaviorAllowsHandoff()) {
|
||||||
|
result += ScrollDirection::eVertical;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AsyncPanZoomController::CanScrollWithWheel(const ParentLayerPoint& aDelta) const
|
AsyncPanZoomController::CanScrollWithWheel(const ParentLayerPoint& aDelta) const
|
||||||
{
|
{
|
||||||
|
@ -1999,6 +2020,19 @@ ScrollInputMethodForWheelDeltaType(ScrollWheelInput::ScrollDeltaType aDeltaType)
|
||||||
return ScrollInputMethod::ApzWheelLine;
|
return ScrollInputMethod::ApzWheelLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
AdjustDeltaForAllowedScrollDirections(
|
||||||
|
ParentLayerPoint& aDelta,
|
||||||
|
const ScrollDirections& aAllowedScrollDirections)
|
||||||
|
{
|
||||||
|
if (!aAllowedScrollDirections.contains(ScrollDirection::eHorizontal)) {
|
||||||
|
aDelta.x = 0;
|
||||||
|
}
|
||||||
|
if (!aAllowedScrollDirections.contains(ScrollDirection::eVertical)) {
|
||||||
|
aDelta.y = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEvent)
|
nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEvent)
|
||||||
{
|
{
|
||||||
ParentLayerPoint delta = GetScrollWheelDelta(aEvent);
|
ParentLayerPoint delta = GetScrollWheelDelta(aEvent);
|
||||||
|
@ -2017,6 +2051,10 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
|
||||||
return nsEventStatus_eConsumeNoDefault;
|
return nsEventStatus_eConsumeNoDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(mInputQueue->GetCurrentWheelBlock());
|
||||||
|
AdjustDeltaForAllowedScrollDirections(delta,
|
||||||
|
mInputQueue->GetCurrentWheelBlock()->GetAllowedScrollDirections());
|
||||||
|
|
||||||
if (delta.x == 0 && delta.y == 0) {
|
if (delta.x == 0 && delta.y == 0) {
|
||||||
// Avoid spurious state changes and unnecessary work
|
// Avoid spurious state changes and unnecessary work
|
||||||
return nsEventStatus_eIgnore;
|
return nsEventStatus_eIgnore;
|
||||||
|
@ -2040,7 +2078,6 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
|
||||||
|
|
||||||
CancelAnimation();
|
CancelAnimation();
|
||||||
|
|
||||||
MOZ_ASSERT(mInputQueue->GetCurrentWheelBlock());
|
|
||||||
OverscrollHandoffState handoffState(
|
OverscrollHandoffState handoffState(
|
||||||
*mInputQueue->GetCurrentWheelBlock()->GetOverscrollHandoffChain(),
|
*mInputQueue->GetCurrentWheelBlock()->GetOverscrollHandoffChain(),
|
||||||
distance,
|
distance,
|
||||||
|
@ -2217,6 +2254,10 @@ nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent, bool
|
||||||
ScreenPoint physicalPanDisplacement = aEvent.mPanDisplacement;
|
ScreenPoint physicalPanDisplacement = aEvent.mPanDisplacement;
|
||||||
ParentLayerPoint logicalPanDisplacement = aEvent.UserMultipliedLocalPanDisplacement();
|
ParentLayerPoint logicalPanDisplacement = aEvent.UserMultipliedLocalPanDisplacement();
|
||||||
|
|
||||||
|
MOZ_ASSERT(GetCurrentPanGestureBlock());
|
||||||
|
AdjustDeltaForAllowedScrollDirections(logicalPanDisplacement,
|
||||||
|
GetCurrentPanGestureBlock()->GetAllowedScrollDirections());
|
||||||
|
|
||||||
// We need to update the axis velocity in order to get a useful display port
|
// We need to update the axis velocity in order to get a useful display port
|
||||||
// size and position. We need to do so even if this is a momentum pan (i.e.
|
// size and position. We need to do so even if this is a momentum pan (i.e.
|
||||||
// aFingersOnTouchpad == false); in that case the "with touch" part is not
|
// aFingersOnTouchpad == false); in that case the "with touch" part is not
|
||||||
|
@ -2230,7 +2271,6 @@ nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent, bool
|
||||||
(uint32_t) ScrollInputMethod::ApzPanGesture);
|
(uint32_t) ScrollInputMethod::ApzPanGesture);
|
||||||
|
|
||||||
ScreenPoint panDistance(fabs(physicalPanDisplacement.x), fabs(physicalPanDisplacement.y));
|
ScreenPoint panDistance(fabs(physicalPanDisplacement.x), fabs(physicalPanDisplacement.y));
|
||||||
MOZ_ASSERT(GetCurrentPanGestureBlock());
|
|
||||||
OverscrollHandoffState handoffState(
|
OverscrollHandoffState handoffState(
|
||||||
*GetCurrentPanGestureBlock()->GetOverscrollHandoffChain(),
|
*GetCurrentPanGestureBlock()->GetOverscrollHandoffChain(),
|
||||||
panDistance,
|
panDistance,
|
||||||
|
|
|
@ -420,6 +420,10 @@ public:
|
||||||
// direction.
|
// direction.
|
||||||
bool CanScroll(const InputData& aEvent) const;
|
bool CanScroll(const InputData& aEvent) const;
|
||||||
|
|
||||||
|
// Return the directions in which this APZC allows handoff (as governed by
|
||||||
|
// overscroll-behavior).
|
||||||
|
ScrollDirections GetAllowedHandoffDirections() const;
|
||||||
|
|
||||||
// Return whether or not a scroll delta will be able to scroll in either
|
// Return whether or not a scroll delta will be able to scroll in either
|
||||||
// direction.
|
// direction.
|
||||||
bool CanScrollWithWheel(const ParentLayerPoint& aDelta) const;
|
bool CanScrollWithWheel(const ParentLayerPoint& aDelta) const;
|
||||||
|
@ -1182,6 +1186,8 @@ private:
|
||||||
*/
|
*/
|
||||||
void OverscrollBy(ParentLayerPoint& aOverscroll);
|
void OverscrollBy(ParentLayerPoint& aOverscroll);
|
||||||
|
|
||||||
|
// Helper function for CanScroll().
|
||||||
|
ParentLayerPoint GetDeltaForEvent(const InputData& aEvent) const;
|
||||||
|
|
||||||
/* ===================================================================
|
/* ===================================================================
|
||||||
* The functions and members in this section are used to maintain the
|
* The functions and members in this section are used to maintain the
|
||||||
|
|
|
@ -322,7 +322,8 @@ WheelBlockState::WheelBlockState(const RefPtr<AsyncPanZoomController>& aTargetAp
|
||||||
// content should have found a scrollable apzc, so we don't need to handle
|
// content should have found a scrollable apzc, so we don't need to handle
|
||||||
// that case.
|
// that case.
|
||||||
RefPtr<AsyncPanZoomController> apzc =
|
RefPtr<AsyncPanZoomController> apzc =
|
||||||
mOverscrollHandoffChain->FindFirstScrollable(aInitialEvent);
|
mOverscrollHandoffChain->FindFirstScrollable(
|
||||||
|
aInitialEvent, &mAllowedScrollDirections);
|
||||||
|
|
||||||
// If nothing is scrollable, we don't consider this block as starting a
|
// If nothing is scrollable, we don't consider this block as starting a
|
||||||
// transaction.
|
// transaction.
|
||||||
|
@ -356,7 +357,8 @@ WheelBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aT
|
||||||
// one by looking for the first apzc the next pending event can scroll.
|
// one by looking for the first apzc the next pending event can scroll.
|
||||||
RefPtr<AsyncPanZoomController> apzc = aTargetApzc;
|
RefPtr<AsyncPanZoomController> apzc = aTargetApzc;
|
||||||
if (apzc && aFirstInput) {
|
if (apzc && aFirstInput) {
|
||||||
apzc = apzc->BuildOverscrollHandoffChain()->FindFirstScrollable(*aFirstInput);
|
apzc = apzc->BuildOverscrollHandoffChain()->FindFirstScrollable(
|
||||||
|
*aFirstInput, &mAllowedScrollDirections);
|
||||||
}
|
}
|
||||||
|
|
||||||
InputBlockState::SetConfirmedTargetApzc(apzc, aState, aFirstInput);
|
InputBlockState::SetConfirmedTargetApzc(apzc, aState, aFirstInput);
|
||||||
|
@ -553,7 +555,8 @@ PanGestureBlockState::PanGestureBlockState(const RefPtr<AsyncPanZoomController>&
|
||||||
// content should have found a scrollable apzc, so we don't need to handle
|
// content should have found a scrollable apzc, so we don't need to handle
|
||||||
// that case.
|
// that case.
|
||||||
RefPtr<AsyncPanZoomController> apzc =
|
RefPtr<AsyncPanZoomController> apzc =
|
||||||
mOverscrollHandoffChain->FindFirstScrollable(aInitialEvent);
|
mOverscrollHandoffChain->FindFirstScrollable(
|
||||||
|
aInitialEvent, &mAllowedScrollDirections);
|
||||||
|
|
||||||
if (apzc && apzc != GetTargetApzc()) {
|
if (apzc && apzc != GetTargetApzc()) {
|
||||||
UpdateTargetApzc(apzc);
|
UpdateTargetApzc(apzc);
|
||||||
|
@ -572,7 +575,8 @@ PanGestureBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController
|
||||||
RefPtr<AsyncPanZoomController> apzc = aTargetApzc;
|
RefPtr<AsyncPanZoomController> apzc = aTargetApzc;
|
||||||
if (apzc && aFirstInput) {
|
if (apzc && aFirstInput) {
|
||||||
RefPtr<AsyncPanZoomController> scrollableApzc =
|
RefPtr<AsyncPanZoomController> scrollableApzc =
|
||||||
apzc->BuildOverscrollHandoffChain()->FindFirstScrollable(*aFirstInput);
|
apzc->BuildOverscrollHandoffChain()->FindFirstScrollable(
|
||||||
|
*aFirstInput, &mAllowedScrollDirections);
|
||||||
if (scrollableApzc) {
|
if (scrollableApzc) {
|
||||||
apzc = scrollableApzc;
|
apzc = scrollableApzc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,6 +282,8 @@ public:
|
||||||
*/
|
*/
|
||||||
void Update(ScrollWheelInput& aEvent);
|
void Update(ScrollWheelInput& aEvent);
|
||||||
|
|
||||||
|
ScrollDirections GetAllowedScrollDirections() const { return mAllowedScrollDirections; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void UpdateTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc) override;
|
void UpdateTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc) override;
|
||||||
|
|
||||||
|
@ -290,6 +292,7 @@ private:
|
||||||
TimeStamp mLastMouseMove;
|
TimeStamp mLastMouseMove;
|
||||||
uint32_t mScrollSeriesCounter;
|
uint32_t mScrollSeriesCounter;
|
||||||
bool mTransactionEnded;
|
bool mTransactionEnded;
|
||||||
|
ScrollDirections mAllowedScrollDirections;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -354,9 +357,12 @@ public:
|
||||||
|
|
||||||
void SetNeedsToWaitForContentResponse(bool aWaitForContentResponse);
|
void SetNeedsToWaitForContentResponse(bool aWaitForContentResponse);
|
||||||
|
|
||||||
|
ScrollDirections GetAllowedScrollDirections() const { return mAllowedScrollDirections; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mInterrupted;
|
bool mInterrupted;
|
||||||
bool mWaitingForContentResponse;
|
bool mWaitingForContentResponse;
|
||||||
|
ScrollDirections mAllowedScrollDirections;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -318,9 +318,13 @@ CanScrollTargetHorizontally(const PanGestureInput& aInitialEvent,
|
||||||
{
|
{
|
||||||
PanGestureInput horizontalComponent = aInitialEvent;
|
PanGestureInput horizontalComponent = aInitialEvent;
|
||||||
horizontalComponent.mPanDisplacement.y = 0;
|
horizontalComponent.mPanDisplacement.y = 0;
|
||||||
|
ScrollDirections allowedScrollDirections;
|
||||||
RefPtr<AsyncPanZoomController> horizontallyScrollableAPZC =
|
RefPtr<AsyncPanZoomController> horizontallyScrollableAPZC =
|
||||||
aBlock->GetOverscrollHandoffChain()->FindFirstScrollable(horizontalComponent);
|
aBlock->GetOverscrollHandoffChain()->FindFirstScrollable(
|
||||||
return horizontallyScrollableAPZC && horizontallyScrollableAPZC == aBlock->GetTargetApzc();
|
horizontalComponent, &allowedScrollDirections);
|
||||||
|
return horizontallyScrollableAPZC &&
|
||||||
|
horizontallyScrollableAPZC == aBlock->GetTargetApzc() &&
|
||||||
|
allowedScrollDirections.contains(ScrollDirection::eHorizontal);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsEventStatus
|
nsEventStatus
|
||||||
|
|
|
@ -161,12 +161,24 @@ OverscrollHandoffChain::HasFastFlungApzc() const
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<AsyncPanZoomController>
|
RefPtr<AsyncPanZoomController>
|
||||||
OverscrollHandoffChain::FindFirstScrollable(const InputData& aInput) const
|
OverscrollHandoffChain::FindFirstScrollable(
|
||||||
|
const InputData& aInput,
|
||||||
|
ScrollDirections* aOutAllowedScrollDirections) const
|
||||||
{
|
{
|
||||||
|
// Start by allowing scrolling in both directions. As we do handoff
|
||||||
|
// overscroll-behavior may restrict one or both of the directions.
|
||||||
|
*aOutAllowedScrollDirections += ScrollDirection::eVertical;
|
||||||
|
*aOutAllowedScrollDirections += ScrollDirection::eHorizontal;
|
||||||
|
|
||||||
for (size_t i = 0; i < Length(); i++) {
|
for (size_t i = 0; i < Length(); i++) {
|
||||||
if (mChain[i]->CanScroll(aInput)) {
|
if (mChain[i]->CanScroll(aInput)) {
|
||||||
return mChain[i];
|
return mChain[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*aOutAllowedScrollDirections &= mChain[i]->GetAllowedHandoffDirections();
|
||||||
|
if (aOutAllowedScrollDirections->isEmpty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,13 @@ public:
|
||||||
// Determine whether any APZC along this handoff chain has been flung fast.
|
// Determine whether any APZC along this handoff chain has been flung fast.
|
||||||
bool HasFastFlungApzc() const;
|
bool HasFastFlungApzc() const;
|
||||||
|
|
||||||
RefPtr<AsyncPanZoomController> FindFirstScrollable(const InputData& aInput) const;
|
// Find the first APZC in this handoff chain that can be scrolled by |aInput|.
|
||||||
|
// Since overscroll-behavior can restrict handoff in some directions,
|
||||||
|
// |aOutAllowedScrollDirections| is populated with the scroll directions
|
||||||
|
// in which scrolling of the returned APZC is allowed.
|
||||||
|
RefPtr<AsyncPanZoomController> FindFirstScrollable(
|
||||||
|
const InputData& aInput,
|
||||||
|
ScrollDirections* aOutAllowedScrollDirections) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<RefPtr<AsyncPanZoomController>> mChain;
|
std::vector<RefPtr<AsyncPanZoomController>> mChain;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче