зеркало из 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 "UnitTransforms.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
#include "mozilla/EnumSet.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -42,6 +43,8 @@ operator|(CancelAnimationFlags a, CancelAnimationFlags b)
|
|||
| static_cast<int>(b));
|
||||
}
|
||||
|
||||
typedef EnumSet<ScrollDirection> ScrollDirections;
|
||||
|
||||
enum class ScrollSource {
|
||||
// scrollTo() or something similar.
|
||||
DOM,
|
||||
|
|
|
@ -1914,9 +1914,8 @@ AsyncPanZoomController::GetKeyboardDestination(const KeyboardScrollAction& aActi
|
|||
return scrollDestination;
|
||||
}
|
||||
|
||||
// Return whether or not the underlying layer can be scrolled on either axis.
|
||||
bool
|
||||
AsyncPanZoomController::CanScroll(const InputData& aEvent) const
|
||||
ParentLayerPoint
|
||||
AsyncPanZoomController::GetDeltaForEvent(const InputData& aEvent) const
|
||||
{
|
||||
ParentLayerPoint delta;
|
||||
if (aEvent.mInputType == SCROLLWHEEL_INPUT) {
|
||||
|
@ -1925,6 +1924,14 @@ AsyncPanZoomController::CanScroll(const InputData& aEvent) const
|
|||
const PanGestureInput& panInput = aEvent.AsPanGestureInput();
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1932,6 +1939,20 @@ AsyncPanZoomController::CanScroll(const InputData& aEvent) const
|
|||
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
|
||||
AsyncPanZoomController::CanScrollWithWheel(const ParentLayerPoint& aDelta) const
|
||||
{
|
||||
|
@ -1999,6 +2020,19 @@ ScrollInputMethodForWheelDeltaType(ScrollWheelInput::ScrollDeltaType aDeltaType)
|
|||
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)
|
||||
{
|
||||
ParentLayerPoint delta = GetScrollWheelDelta(aEvent);
|
||||
|
@ -2017,6 +2051,10 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
|
|||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mInputQueue->GetCurrentWheelBlock());
|
||||
AdjustDeltaForAllowedScrollDirections(delta,
|
||||
mInputQueue->GetCurrentWheelBlock()->GetAllowedScrollDirections());
|
||||
|
||||
if (delta.x == 0 && delta.y == 0) {
|
||||
// Avoid spurious state changes and unnecessary work
|
||||
return nsEventStatus_eIgnore;
|
||||
|
@ -2040,7 +2078,6 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
|
|||
|
||||
CancelAnimation();
|
||||
|
||||
MOZ_ASSERT(mInputQueue->GetCurrentWheelBlock());
|
||||
OverscrollHandoffState handoffState(
|
||||
*mInputQueue->GetCurrentWheelBlock()->GetOverscrollHandoffChain(),
|
||||
distance,
|
||||
|
@ -2217,6 +2254,10 @@ nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent, bool
|
|||
ScreenPoint physicalPanDisplacement = aEvent.mPanDisplacement;
|
||||
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
|
||||
// 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
|
||||
|
@ -2230,7 +2271,6 @@ nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent, bool
|
|||
(uint32_t) ScrollInputMethod::ApzPanGesture);
|
||||
|
||||
ScreenPoint panDistance(fabs(physicalPanDisplacement.x), fabs(physicalPanDisplacement.y));
|
||||
MOZ_ASSERT(GetCurrentPanGestureBlock());
|
||||
OverscrollHandoffState handoffState(
|
||||
*GetCurrentPanGestureBlock()->GetOverscrollHandoffChain(),
|
||||
panDistance,
|
||||
|
|
|
@ -420,6 +420,10 @@ public:
|
|||
// direction.
|
||||
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
|
||||
// direction.
|
||||
bool CanScrollWithWheel(const ParentLayerPoint& aDelta) const;
|
||||
|
@ -1182,6 +1186,8 @@ private:
|
|||
*/
|
||||
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
|
||||
|
|
|
@ -322,7 +322,8 @@ WheelBlockState::WheelBlockState(const RefPtr<AsyncPanZoomController>& aTargetAp
|
|||
// content should have found a scrollable apzc, so we don't need to handle
|
||||
// that case.
|
||||
RefPtr<AsyncPanZoomController> apzc =
|
||||
mOverscrollHandoffChain->FindFirstScrollable(aInitialEvent);
|
||||
mOverscrollHandoffChain->FindFirstScrollable(
|
||||
aInitialEvent, &mAllowedScrollDirections);
|
||||
|
||||
// If nothing is scrollable, we don't consider this block as starting a
|
||||
// transaction.
|
||||
|
@ -356,7 +357,8 @@ WheelBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aT
|
|||
// one by looking for the first apzc the next pending event can scroll.
|
||||
RefPtr<AsyncPanZoomController> apzc = aTargetApzc;
|
||||
if (apzc && aFirstInput) {
|
||||
apzc = apzc->BuildOverscrollHandoffChain()->FindFirstScrollable(*aFirstInput);
|
||||
apzc = apzc->BuildOverscrollHandoffChain()->FindFirstScrollable(
|
||||
*aFirstInput, &mAllowedScrollDirections);
|
||||
}
|
||||
|
||||
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
|
||||
// that case.
|
||||
RefPtr<AsyncPanZoomController> apzc =
|
||||
mOverscrollHandoffChain->FindFirstScrollable(aInitialEvent);
|
||||
mOverscrollHandoffChain->FindFirstScrollable(
|
||||
aInitialEvent, &mAllowedScrollDirections);
|
||||
|
||||
if (apzc && apzc != GetTargetApzc()) {
|
||||
UpdateTargetApzc(apzc);
|
||||
|
@ -572,7 +575,8 @@ PanGestureBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController
|
|||
RefPtr<AsyncPanZoomController> apzc = aTargetApzc;
|
||||
if (apzc && aFirstInput) {
|
||||
RefPtr<AsyncPanZoomController> scrollableApzc =
|
||||
apzc->BuildOverscrollHandoffChain()->FindFirstScrollable(*aFirstInput);
|
||||
apzc->BuildOverscrollHandoffChain()->FindFirstScrollable(
|
||||
*aFirstInput, &mAllowedScrollDirections);
|
||||
if (scrollableApzc) {
|
||||
apzc = scrollableApzc;
|
||||
}
|
||||
|
|
|
@ -282,6 +282,8 @@ public:
|
|||
*/
|
||||
void Update(ScrollWheelInput& aEvent);
|
||||
|
||||
ScrollDirections GetAllowedScrollDirections() const { return mAllowedScrollDirections; }
|
||||
|
||||
protected:
|
||||
void UpdateTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc) override;
|
||||
|
||||
|
@ -290,6 +292,7 @@ private:
|
|||
TimeStamp mLastMouseMove;
|
||||
uint32_t mScrollSeriesCounter;
|
||||
bool mTransactionEnded;
|
||||
ScrollDirections mAllowedScrollDirections;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -354,9 +357,12 @@ public:
|
|||
|
||||
void SetNeedsToWaitForContentResponse(bool aWaitForContentResponse);
|
||||
|
||||
ScrollDirections GetAllowedScrollDirections() const { return mAllowedScrollDirections; }
|
||||
|
||||
private:
|
||||
bool mInterrupted;
|
||||
bool mWaitingForContentResponse;
|
||||
ScrollDirections mAllowedScrollDirections;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -318,9 +318,13 @@ CanScrollTargetHorizontally(const PanGestureInput& aInitialEvent,
|
|||
{
|
||||
PanGestureInput horizontalComponent = aInitialEvent;
|
||||
horizontalComponent.mPanDisplacement.y = 0;
|
||||
ScrollDirections allowedScrollDirections;
|
||||
RefPtr<AsyncPanZoomController> horizontallyScrollableAPZC =
|
||||
aBlock->GetOverscrollHandoffChain()->FindFirstScrollable(horizontalComponent);
|
||||
return horizontallyScrollableAPZC && horizontallyScrollableAPZC == aBlock->GetTargetApzc();
|
||||
aBlock->GetOverscrollHandoffChain()->FindFirstScrollable(
|
||||
horizontalComponent, &allowedScrollDirections);
|
||||
return horizontallyScrollableAPZC &&
|
||||
horizontallyScrollableAPZC == aBlock->GetTargetApzc() &&
|
||||
allowedScrollDirections.contains(ScrollDirection::eHorizontal);
|
||||
}
|
||||
|
||||
nsEventStatus
|
||||
|
|
|
@ -161,12 +161,24 @@ OverscrollHandoffChain::HasFastFlungApzc() const
|
|||
}
|
||||
|
||||
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++) {
|
||||
if (mChain[i]->CanScroll(aInput)) {
|
||||
return mChain[i];
|
||||
}
|
||||
|
||||
*aOutAllowedScrollDirections &= mChain[i]->GetAllowedHandoffDirections();
|
||||
if (aOutAllowedScrollDirections->isEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -89,7 +89,13 @@ public:
|
|||
// Determine whether any APZC along this handoff chain has been flung fast.
|
||||
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:
|
||||
std::vector<RefPtr<AsyncPanZoomController>> mChain;
|
||||
|
|
Загрузка…
Ссылка в новой задаче