Files
palemoon27/widget/cocoa/SwipeTracker.mm
T
roytam1 e9ba40cf6b import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1178833 - Fix for unified builds when a new file is added to layout/base. r=mstange (bf961c00fd)
- Bug 1178847 - Add a MobileViewportManager to manage setting the CSS viewport on B2G. r=botond,tn (937ba486fa)
- Bug 1178847 - Don't use the MobileViewportManager code on Mulet or Fennec yet. r=botond (3061b2c617)
- Bug 1168950. Add the document to DoProcessRestyles profile label. r=dbaron (2347b76411)
- Bug 1187792 - Don't set the SPCSPS unless meta-viewport or zooming is enabled. r=botond (a8f5ed1006)
- Bug 1193062 - Don't double-send target APZC confirmations that might race each other. r=kats (de48467401)
- Bug 1186004 - Add a pref to enable/disable APZ zooming behaviour. r=botond (fc3653c979)
- Bug 1193062 - Add a PAN_MOMENTUM state. r=kats (10c8bb1a5e)
- Bug 1148350 - Have ConvertToGecko use a live screen-to-apzc transform to avoid transform mismatches. r=botond (9eee9ea6f2)
- Bug 1169844 - Remove incorrect assertion and properly untransform wheel events for overscroll situations. r=botond (9b101b53bb)
- Bug 1169690 - Accelerate flings correctly in the presence of overscroll handoff. r=kats (49d55c05f4)
- Bug 1158424 - Extract a BreadthFirstSearch() helper function. r=kats (6a49498185)
- Bug 1158424 - Add APZCTreeManager::FindRootContentApzcForLayersId(). r=kats (d6c7ecf781)
- Bug 1158424 - Fix APZCTreeManager::GetMultitouchTarget(). r=kats (bf8571a4ca)
- Bug 1174205 - Make sure to acquire the tree lock before finding the multitouch target. r=botond (bdbd98f2c7)
- Bug 1211660 - Remove dead obj argument from two functions. r=Waldo. (efba5a2f8d)
- Bug 1158424 - Undeprecate HasNoParentWithSameLayersId(). r=kats (d994ea28f8)
- Fix AsyncCompositionManager not comparing layer tree IDs when finding scrollbar targets. (bug 1151169, r=kats) (c7dbc4776a)
- Bug 1163259. Make sure we don't look at the parent ref layer when looking for a layer with the frame metrics for a scrollbar. r=kats (8b99d2c830)
- Bug 1164340. Convert the scrollbar thumb ratio to a unitless ratio properly for non-zoomable scrollframes. r=botond (27f56cab56)
- Bug 1164340. Fix up some scrollbar related comments in AsyncCompositionManager. r=botond (b9d540bea9)
- Bug 1164767. Modify async scrollbar positioning code to deal with containerless root scrollables. r=botond (501d07592e)
- Bug 1158424 - Remove FrameMetrics::IsRootScrollable() (it just duplicated IsRootContent()). r=kats (672fd034b3)
- Bug 1120683 - Properly handle unapplying 3D projective transforms throughout APZ code. r=botond (a46612811a)
- Bug 1148868 - Make APZ wheel handling handle pixel scrolling on OS X. r=dvander, r=kats (da3bd34135)
- Bug 1193062 - Add fields to PanGestureInput and ScrollWheelInput. r=kats (716ba34e18)
- Bug 1189565 - Send resize events when backing scale factor changes. r=mstange (4e81a7bbf7)
- Bug 1193062 - Add nsCocoaUtils::ModifiersForEvent. r=smichaud (da67b22ff7)
- Bug 1016035 - Remove the ability to swipe vertically. r=kats (fa315e0b97)
- Bug 1016035 - Refactor the code that decides whether we want to start a swipe. r=kats (3091961328)
- Bug 1016035 - Make the threshold in AxisPhysicsMSDModel::IsFinished controllable by the caller. r=kip (76df4d85a2)
- Bug 1016035 - More swipe refactoring. r=kats (2abcd05b33)
- Bug 1016035 - Implement the swipe animation ourselves instead of calling the NSEvent trackSwipe API. r=kats (4842b2a728)
- Bug 1016035 - Move swipe tracking code into DispatchAPZWheelInputEvent. r=kats (bb1052b87c)
- Bug 1016035 - Also mark widgetWheelEvents that are handled by APZ with mCanStartSwipe. r=kats (21809b902d)
- Bug 1016035 - Put PanGestureInput events into a queue if they can end up as a swipe. r=kats (2ebac59047)
- Bug 1016035 - Split up MaybeTrackScrollEventAsSwipe into SendMayStartSwipe and TrackScrollEventAsSwipe. r=kats (ced10d9671)
- Bug 1016035 - Send MayStartSwipe event before sending the wheel event. r=kats (b3346b81fb)
- Fix some fields missing in the widget event IPC glue. (bug 1139711, r=kats) (1298b25705)
- Bug 1016035 - Add mCanTriggerSwipe and TriggersSwipe(). r=masayuki (664a059972)
- Bug 1016035 - Make APZEventState report defaultPrevented=true when the event started a swipe. r=kats (128d627ac7)
- Bug 1016035 - Set scroll overflow information on potential swipe start events that have been processed by APZ. r=masayuki (b5931f6320)
- Bug 1206801 - fix broken CONFIG['DEBUG'] checks in moz.build files; r=mshal (292d5ac709)
- Bug 1186424: Refactor AsmJSValidate.cpp in preparation for parallelization; r=luke (4868bc66ca)
- Bug 1129267 - Fix by backing out patch for bug 1118615. r=mstange (ea8aaba04e)
- Bug 1182411 Part 1: Make plugin quirks available to the Parent as well as the Child. r=jimm (1f2551a6b7)
- Bug 1228462 - "PluginQuirks.* uses DOS CRLF". r=jmathies (b569a6c6c8)
- Bug 1152300 - When focus shifts from a native plugin window to content, content needs to forward the request for focus change to chrome. r=enn (5bd811fadd)
- Bug 1185529: On Windows, ensure that NPAPI child window has the correct parent before setwindow is called. r=jimm (9d94fdf2ff)
- Bug 1182411 Part 2: Change winless popup surrogate to have its parent set in the chrome process. r=jimm (adee9bb012)
2022-02-02 12:04:50 +08:00

220 lines
7.2 KiB
Plaintext

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 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 "SwipeTracker.h"
#include "InputData.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/TouchEvents.h"
#include "nsAlgorithm.h"
#include "nsChildView.h"
#include "UnitTransforms.h"
// These values were tweaked to make the physics feel similar to the native swipe.
static const double kSpringForce = 250.0;
static const double kVelocityTwitchTolerance = 0.0000001;
static const double kWholePagePixelSize = 1000.0;
static const double kRubberBandResistanceFactor = 4.0;
static const double kSwipeSuccessThreshold = 0.25;
static const double kSwipeSuccessVelocityContribution = 0.3;
namespace mozilla {
static already_AddRefed<nsRefreshDriver>
GetRefreshDriver(nsIWidget& aWidget)
{
nsIWidgetListener* widgetListener = aWidget.GetWidgetListener();
nsIPresShell* presShell = widgetListener ? widgetListener->GetPresShell() : nullptr;
nsPresContext* presContext = presShell ? presShell->GetPresContext() : nullptr;
nsRefPtr<nsRefreshDriver> refreshDriver = presContext ? presContext->RefreshDriver() : nullptr;
return refreshDriver.forget();
}
SwipeTracker::SwipeTracker(nsChildView& aWidget,
const PanGestureInput& aSwipeStartEvent,
uint32_t aAllowedDirections,
uint32_t aSwipeDirection)
: mWidget(aWidget)
, mRefreshDriver(GetRefreshDriver(mWidget))
, mAxis(0.0, 0.0, 0.0, kSpringForce, 1.0)
, mEventPosition(RoundedToInt(ViewAs<LayoutDevicePixel>(aSwipeStartEvent.mPanStartPoint,
PixelCastJustification::LayoutDeviceToScreenForUntransformedEvent)))
, mLastEventTimeStamp(aSwipeStartEvent.mTimeStamp)
, mAllowedDirections(aAllowedDirections)
, mSwipeDirection(aSwipeDirection)
, mGestureAmount(0.0)
, mCurrentVelocity(0.0)
, mEventsAreControllingSwipe(true)
, mEventsHaveStartedNewGesture(false)
, mRegisteredWithRefreshDriver(false)
{
ProcessEvent(aSwipeStartEvent);
}
void
SwipeTracker::Destroy()
{
UnregisterFromRefreshDriver();
}
SwipeTracker::~SwipeTracker()
{
MOZ_ASSERT(!mRegisteredWithRefreshDriver, "Destroy needs to be called before deallocating");
}
double
SwipeTracker::SwipeSuccessTargetValue() const
{
return (mSwipeDirection == nsIDOMSimpleGestureEvent::DIRECTION_RIGHT) ? -1.0 : 1.0;
}
double
SwipeTracker::ClampToAllowedRange(double aGestureAmount) const
{
// gestureAmount needs to stay between -1 and 0 when swiping right and
// between 0 and 1 when swiping left.
double min = (mSwipeDirection == nsIDOMSimpleGestureEvent::DIRECTION_RIGHT) ? -1.0 : 0.0;
double max = (mSwipeDirection == nsIDOMSimpleGestureEvent::DIRECTION_LEFT) ? 1.0 : 0.0;
return clamped(aGestureAmount, min, max);
}
bool
SwipeTracker::ComputeSwipeSuccess() const
{
double targetValue = SwipeSuccessTargetValue();
// If the fingers were moving away from the target direction when they were
// lifted from the touchpad, abort the swipe.
if (mCurrentVelocity * targetValue < -kVelocityTwitchTolerance) {
return false;
}
return (mGestureAmount * targetValue +
mCurrentVelocity * targetValue * kSwipeSuccessVelocityContribution) >= kSwipeSuccessThreshold;
}
nsEventStatus
SwipeTracker::ProcessEvent(const PanGestureInput& aEvent)
{
// If the fingers have already been lifted, don't process this event for swiping.
if (!mEventsAreControllingSwipe) {
// Return nsEventStatus_eConsumeNoDefault for events from the swipe gesture
// and nsEventStatus_eIgnore for events of subsequent scroll gestures.
if (aEvent.mType == PanGestureInput::PANGESTURE_MAYSTART ||
aEvent.mType == PanGestureInput::PANGESTURE_START) {
mEventsHaveStartedNewGesture = true;
}
return mEventsHaveStartedNewGesture ? nsEventStatus_eIgnore : nsEventStatus_eConsumeNoDefault;
}
double delta = -aEvent.mPanDisplacement.x / mWidget.BackingScaleFactor() / kWholePagePixelSize;
if (!SwipingInAllowedDirection()) {
delta /= kRubberBandResistanceFactor;
}
mGestureAmount = ClampToAllowedRange(mGestureAmount + delta);
SendSwipeEvent(NS_SIMPLE_GESTURE_SWIPE_UPDATE, 0, mGestureAmount);
if (aEvent.mType != PanGestureInput::PANGESTURE_END) {
double elapsedSeconds = std::max(0.008, (aEvent.mTimeStamp - mLastEventTimeStamp).ToSeconds());
mCurrentVelocity = delta / elapsedSeconds;
mLastEventTimeStamp = aEvent.mTimeStamp;
} else {
mEventsAreControllingSwipe = false;
bool didSwipeSucceed = SwipingInAllowedDirection() && ComputeSwipeSuccess();
double targetValue = 0.0;
if (didSwipeSucceed) {
SendSwipeEvent(NS_SIMPLE_GESTURE_SWIPE, mSwipeDirection, 0.0);
targetValue = SwipeSuccessTargetValue();
}
StartAnimating(targetValue);
}
return nsEventStatus_eConsumeNoDefault;
}
void
SwipeTracker::StartAnimating(double aTargetValue)
{
mAxis.SetPosition(mGestureAmount);
mAxis.SetDestination(aTargetValue);
mAxis.SetVelocity(mCurrentVelocity);
mLastAnimationFrameTime = TimeStamp::Now();
// Add ourselves as a refresh driver observer. The refresh driver
// will call WillRefresh for each animation frame until we
// unregister ourselves.
MOZ_ASSERT(!mRegisteredWithRefreshDriver);
if (mRefreshDriver) {
mRefreshDriver->AddRefreshObserver(this, Flush_Style);
mRegisteredWithRefreshDriver = true;
}
}
void
SwipeTracker::WillRefresh(mozilla::TimeStamp aTime)
{
TimeStamp now = TimeStamp::Now();
mAxis.Simulate(now - mLastAnimationFrameTime);
mLastAnimationFrameTime = now;
bool isFinished = mAxis.IsFinished(1.0 / kWholePagePixelSize);
mGestureAmount = (isFinished ? mAxis.GetDestination() : mAxis.GetPosition());
SendSwipeEvent(NS_SIMPLE_GESTURE_SWIPE_UPDATE, 0, mGestureAmount);
if (isFinished) {
UnregisterFromRefreshDriver();
SwipeFinished();
}
}
void
SwipeTracker::CancelSwipe()
{
SendSwipeEvent(NS_SIMPLE_GESTURE_SWIPE_END, 0, 0.0);
}
void SwipeTracker::SwipeFinished()
{
SendSwipeEvent(NS_SIMPLE_GESTURE_SWIPE_END, 0, 0.0);
mWidget.SwipeFinished();
}
void
SwipeTracker::UnregisterFromRefreshDriver()
{
if (mRegisteredWithRefreshDriver) {
MOZ_ASSERT(mRefreshDriver, "How were we able to register, then?");
mRefreshDriver->RemoveRefreshObserver(this, Flush_Style);
}
mRegisteredWithRefreshDriver = false;
}
/* static */ WidgetSimpleGestureEvent
SwipeTracker::CreateSwipeGestureEvent(EventMessage aMsg, nsIWidget* aWidget,
const LayoutDeviceIntPoint& aPosition)
{
WidgetSimpleGestureEvent geckoEvent(true, aMsg, aWidget);
geckoEvent.modifiers = 0;
geckoEvent.timeStamp = TimeStamp::Now();
geckoEvent.refPoint = aPosition;
geckoEvent.buttons = 0;
return geckoEvent;
}
bool
SwipeTracker::SendSwipeEvent(EventMessage aMsg, uint32_t aDirection, double aDelta)
{
WidgetSimpleGestureEvent geckoEvent =
CreateSwipeGestureEvent(aMsg, &mWidget, mEventPosition);
geckoEvent.direction = aDirection;
geckoEvent.delta = aDelta;
geckoEvent.allowedDirections = mAllowedDirections;
return mWidget.DispatchWindowEvent(geckoEvent);
}
} // namespace mozilla