summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:13:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:13:27 +0000
commit40a355a42d4a9444dc753c04c6608dade2f06a23 (patch)
tree871fc667d2de662f171103ce5ec067014ef85e61 /gfx/layers/apz/src
parentAdding upstream version 124.0.1. (diff)
downloadfirefox-40a355a42d4a9444dc753c04c6608dade2f06a23.tar.xz
firefox-40a355a42d4a9444dc753c04c6608dade2f06a23.zip
Adding upstream version 125.0.1.upstream/125.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gfx/layers/apz/src')
-rw-r--r--gfx/layers/apz/src/APZCTreeManager.cpp56
-rw-r--r--gfx/layers/apz/src/APZCTreeManager.h9
-rw-r--r--gfx/layers/apz/src/APZUpdater.cpp30
-rw-r--r--gfx/layers/apz/src/AsyncPanZoomController.cpp46
-rw-r--r--gfx/layers/apz/src/AsyncPanZoomController.h2
-rw-r--r--gfx/layers/apz/src/AutoscrollAnimation.cpp2
-rw-r--r--gfx/layers/apz/src/GenericScrollAnimation.cpp9
-rw-r--r--gfx/layers/apz/src/GestureEventListener.cpp87
-rw-r--r--gfx/layers/apz/src/GestureEventListener.h3
9 files changed, 178 insertions, 66 deletions
diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp
index d28392b716..ef3cde3596 100644
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -62,6 +62,8 @@
mozilla::LazyLogModule mozilla::layers::APZCTreeManager::sLog("apz.manager");
#define APZCTM_LOG(...) \
MOZ_LOG(APZCTreeManager::sLog, LogLevel::Debug, (__VA_ARGS__))
+#define APZCTM_LOGV(...) \
+ MOZ_LOG(APZCTreeManager::sLog, LogLevel::Verbose, (__VA_ARGS__))
static mozilla::LazyLogModule sApzKeyLog("apz.key");
#define APZ_KEY_LOG(...) MOZ_LOG(sApzKeyLog, LogLevel::Debug, (__VA_ARGS__))
@@ -83,10 +85,10 @@ typedef CompositorBridgeParent::LayerTreeState LayerTreeState;
struct APZCTreeManager::TreeBuildingState {
TreeBuildingState(LayersId aRootLayersId, bool aIsFirstPaint,
LayersId aOriginatingLayersId, APZTestData* aTestData,
- uint32_t aPaintSequence)
+ uint32_t aPaintSequence, bool aIsTestLoggingEnabled)
: mIsFirstPaint(aIsFirstPaint),
mOriginatingLayersId(aOriginatingLayersId),
- mPaintLogger(aTestData, aPaintSequence) {
+ mPaintLogger(aTestData, aPaintSequence, aIsTestLoggingEnabled) {
CompositorBridgeParent::CallWithIndirectShadowTree(
aRootLayersId, [this](LayerTreeState& aState) -> void {
mCompositorController = aState.GetCompositorController();
@@ -158,6 +160,9 @@ struct APZCTreeManager::TreeBuildingState {
// cumulative EventRegionsOverride flags from the reflayers, and is used to
// apply them to descendant layers.
std::stack<EventRegionsOverride> mOverrideFlags;
+
+ // Wether the APZC correspoinding to the originating LayersId was updated.
+ bool mOriginatingLayersIdUpdated = false;
};
class APZCTreeManager::CheckerboardFlushObserver : public nsIObserver {
@@ -391,8 +396,7 @@ void APZCTreeManager::SetAllowedTouchBehavior(
uint64_t aInputBlockId, const nsTArray<TouchBehaviorFlags>& aValues) {
if (!APZThreadUtils::IsControllerThread()) {
APZThreadUtils::RunOnControllerThread(
- NewRunnableMethod<uint64_t,
- StoreCopyPassByLRef<nsTArray<TouchBehaviorFlags>>>(
+ NewRunnableMethod<uint64_t, nsTArray<TouchBehaviorFlags>>(
"layers::APZCTreeManager::SetAllowedTouchBehavior", this,
&APZCTreeManager::SetAllowedTouchBehavior, aInputBlockId,
aValues.Clone()));
@@ -420,9 +424,11 @@ void APZCTreeManager::SetBrowserGestureResponse(
mInputQueue->SetBrowserGestureResponse(aInputBlockId, aResponse);
}
-void APZCTreeManager::UpdateHitTestingTree(
- const WebRenderScrollDataWrapper& aRoot, bool aIsFirstPaint,
- LayersId aOriginatingLayersId, uint32_t aPaintSequenceNumber) {
+APZCTreeManager::OriginatingLayersIdUpdated
+APZCTreeManager::UpdateHitTestingTree(const WebRenderScrollDataWrapper& aRoot,
+ bool aIsFirstPaint,
+ LayersId aOriginatingLayersId,
+ uint32_t aPaintSequenceNumber) {
AssertOnUpdaterThread();
RecursiveMutexAutoLock lock(mTreeLock);
@@ -430,7 +436,8 @@ void APZCTreeManager::UpdateHitTestingTree(
// For testing purposes, we log some data to the APZTestData associated with
// the layers id that originated this update.
APZTestData* testData = nullptr;
- if (StaticPrefs::apz_test_logging_enabled()) {
+ const bool testLoggingEnabled = StaticPrefs::apz_test_logging_enabled();
+ if (testLoggingEnabled) {
MutexAutoLock lock(mTestDataLock);
UniquePtr<APZTestData> ptr = MakeUnique<APZTestData>();
auto result =
@@ -440,7 +447,7 @@ void APZCTreeManager::UpdateHitTestingTree(
}
TreeBuildingState state(mRootLayersId, aIsFirstPaint, aOriginatingLayersId,
- testData, aPaintSequenceNumber);
+ testData, aPaintSequenceNumber, testLoggingEnabled);
// We do this business with collecting the entire tree into an array because
// otherwise it's very hard to determine which APZC instances need to be
@@ -730,6 +737,8 @@ void APZCTreeManager::UpdateHitTestingTree(
mRootNode->Dump(" ");
}
SendSubtreeTransformsToChromeMainThread(nullptr);
+
+ return OriginatingLayersIdUpdated{state.mOriginatingLayersIdUpdated};
}
void APZCTreeManager::UpdateFocusState(LayersId aRootLayerTreeId,
@@ -763,7 +772,7 @@ void APZCTreeManager::SampleForWebRender(const Maybe<VsyncId>& aVsyncId,
controller->ScheduleRenderOnCompositorThread(
wr::RenderReasons::ANIMATED_PROPERTY);
}
- APZCTM_LOG(
+ APZCTM_LOGV(
"APZCTreeManager(%p)::SampleForWebRender, want more composites: %d\n",
this, (activeAnimations && controller));
@@ -1231,6 +1240,10 @@ HitTestingTreeNode* APZCTreeManager::PrepareNodeForLayer(
"Found APZC %p for layer %p with identifiers %" PRIx64 " %" PRId64 "\n",
apzc.get(), aLayer.GetLayer(), uint64_t(guid.mLayersId), guid.mScrollId);
+ if (aLayersId == aState.mOriginatingLayersId) {
+ aState.mOriginatingLayersIdUpdated = true;
+ }
+
// If we haven't encountered a layer already with the same metrics, then we
// need to do the full reuse-or-make-an-APZC algorithm, which is contained
// inside the block below.
@@ -1522,6 +1535,11 @@ APZEventResult APZCTreeManager::ReceiveInputEvent(
}
case MOUSE_INPUT: {
MouseInput& mouseInput = aEvent.AsMouseInput();
+ MOZ_LOG(APZCTreeManager::sLog,
+ mouseInput.mType == MouseInput::MOUSE_MOVE ? LogLevel::Verbose
+ : LogLevel::Debug,
+ ("Received mouse input type %d at %s\n", (int)mouseInput.mType,
+ ToString(mouseInput.mOrigin).c_str()));
mouseInput.mHandledByAPZ = true;
SetCurrentMousePosition(mouseInput.mOrigin);
@@ -1613,6 +1631,9 @@ APZEventResult APZCTreeManager::ReceiveInputEvent(
// Do this before early return for Fission hit testing.
ScrollWheelInput& wheelInput = aEvent.AsScrollWheelInput();
+ APZCTM_LOG("Received wheel input at %s with delta (%f, %f)\n",
+ ToString(wheelInput.mOrigin).c_str(), wheelInput.mDeltaX,
+ wheelInput.mDeltaY);
state.mHit = GetTargetAPZC(wheelInput.mOrigin);
wheelInput.mHandledByAPZ = WillHandleInput(wheelInput);
@@ -1674,6 +1695,9 @@ APZEventResult APZCTreeManager::ReceiveInputEvent(
// Do this before early return for Fission hit testing.
PanGestureInput& panInput = aEvent.AsPanGestureInput();
+ APZCTM_LOG("Received pan gesture input type %d at %s with delta %s\n",
+ (int)panInput.mType, ToString(panInput.mPanStartPoint).c_str(),
+ ToString(panInput.mPanDisplacement).c_str());
state.mHit = GetTargetAPZC(panInput.mPanStartPoint);
panInput.mHandledByAPZ = WillHandleInput(panInput);
@@ -2021,6 +2045,18 @@ APZEventResult APZCTreeManager::InputHandlingState::Finish(
void APZCTreeManager::ProcessTouchInput(InputHandlingState& aState,
MultiTouchInput& aInput) {
+ APZCTM_LOG("Received touch input type %d with touch points [%s]\n",
+ (int)aInput.mType,
+ [&] {
+ nsCString result;
+ for (const auto& touch : aInput.mTouches) {
+ result.AppendPrintf("%s",
+ ToString(touch.mScreenPoint).c_str());
+ }
+ return result;
+ }()
+ .get());
+
aInput.mHandledByAPZ = true;
nsTArray<TouchBehaviorFlags> touchBehaviors;
HitTestingTreeNodeAutoLock hitScrollbarNode;
diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h
index ff9bba51ca..71d35fd5a6 100644
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -190,10 +190,13 @@ class APZCTreeManager : public IAPZCTreeManager, public APZInputBridge {
* this layer update. Note that every child
* process' layer subtree has its own sequence
* numbers.
+ * @return OriginatingLayersIdUpdated whether the given
+ * |aOriginatingLayersId|'s data was processed.
*/
- void UpdateHitTestingTree(const WebRenderScrollDataWrapper& aRoot,
- bool aIsFirstPaint, LayersId aOriginatingLayersId,
- uint32_t aPaintSequenceNumber);
+ enum class OriginatingLayersIdUpdated : bool { No, Yes };
+ OriginatingLayersIdUpdated UpdateHitTestingTree(
+ const WebRenderScrollDataWrapper& aRoot, bool aIsFirstPaint,
+ LayersId aOriginatingLayersId, uint32_t aPaintSequenceNumber);
/**
* Called when webrender is enabled, from the sampler thread. This function
diff --git a/gfx/layers/apz/src/APZUpdater.cpp b/gfx/layers/apz/src/APZUpdater.cpp
index 2bbad6e1a7..2f1b551f3a 100644
--- a/gfx/layers/apz/src/APZUpdater.cpp
+++ b/gfx/layers/apz/src/APZUpdater.cpp
@@ -191,14 +191,38 @@ void APZUpdater::UpdateScrollDataAndTreeState(
auto isFirstPaint = aScrollData.IsFirstPaint();
auto paintSequenceNumber = aScrollData.GetPaintSequenceNumber();
+ auto previous = self->mScrollData.find(aOriginatingLayersId);
+ // If there's the previous scroll data which hasn't yet been
+ // processed, we need to merge the previous scroll position updates
+ // into the latest one.
+ if (previous != self->mScrollData.end()) {
+ WebRenderScrollData& previousData = previous->second;
+ if (previousData.GetWasUpdateSkipped()) {
+ MOZ_ASSERT(previousData.IsFirstPaint());
+ aScrollData.PrependUpdates(previousData);
+ }
+ }
+
self->mScrollData[aOriginatingLayersId] = std::move(aScrollData);
auto root = self->mScrollData.find(aRootLayerTreeId);
if (root == self->mScrollData.end()) {
return;
}
- self->mApz->UpdateHitTestingTree(
- WebRenderScrollDataWrapper(*self, &(root->second)),
- isFirstPaint, aOriginatingLayersId, paintSequenceNumber);
+ if ((self->mApz->UpdateHitTestingTree(
+ WebRenderScrollDataWrapper(*self, &(root->second)),
+ isFirstPaint, aOriginatingLayersId, paintSequenceNumber) ==
+ APZCTreeManager::OriginatingLayersIdUpdated::No) &&
+ isFirstPaint) {
+ // If the given |aOriginatingLayersId| data wasn't used for
+ // updating, it's likly that the parent process hasn't yet
+ // received the LayersId as "ReferentId", thus we need to process
+ // it in a subsequent update where we got the "ReferentId".
+ //
+ // NOTE: We restrict the above previous scroll data prepending to
+ // the first paint case, otherwise the cumulative scroll data may
+ // be exploded if we have never received the "ReferenceId".
+ self->mScrollData[aOriginatingLayersId].SetWasUpdateSkipped();
+ }
}));
}
diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp
index 342375c019..edbd2ecffa 100644
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -106,6 +106,10 @@ static mozilla::LazyLogModule sApzCtlLog("apz.controller");
APZC_LOG("%p(%s scrollId=%" PRIu64 "): " fmt, (apzc), \
(apzc)->IsRootContent() ? "root" : "subframe", \
(apzc)->GetScrollId(), ##__VA_ARGS__)
+#define APZC_LOGV_DETAIL(fmt, apzc, ...) \
+ APZC_LOGV("%p(%s scrollId=%" PRIu64 "): " fmt, (apzc), \
+ (apzc)->IsRootContent() ? "root" : "subframe", \
+ (apzc)->GetScrollId(), ##__VA_ARGS__)
#define APZC_LOG_FM_COMMON(fm, prefix, level, ...) \
if (MOZ_LOG_TEST(sApzCtlLog, level)) { \
@@ -2248,6 +2252,11 @@ CSSRect AsyncPanZoomController::GetCurrentScrollRangeInCssPixels() const {
return Metrics().CalculateScrollRange();
}
+bool AsyncPanZoomController::AllowOneTouchPinch() const {
+ return StaticPrefs::apz_one_touch_pinch_enabled() &&
+ ZoomConstraintsAllowZoom();
+}
+
// Return whether or not the underlying layer can be scrolled on either axis.
bool AsyncPanZoomController::CanScroll(const InputData& aEvent) const {
ParentLayerPoint delta = GetDeltaForEvent(aEvent);
@@ -4734,7 +4743,7 @@ bool AsyncPanZoomController::UpdateAnimation(
// Even if there's no animation, if we have a scroll offset change pending due
// to the frame delay, we need to keep compositing.
if (mLastSampleTime == aSampleTime) {
- APZC_LOG_DETAIL(
+ APZC_LOGV_DETAIL(
"UpdateAnimation short-circuit, animation=%p, pending frame-delayed "
"offset=%d\n",
this, mAnimation.get(), HavePendingFrameDelayedOffset());
@@ -4754,8 +4763,8 @@ bool AsyncPanZoomController::UpdateAnimation(
// so that e.g. a main-thread animation can stay in sync with user-driven
// scrolling or a compositor animation.
bool needComposite = SampleCompositedAsyncTransform(aProofOfLock);
- APZC_LOG_DETAIL("UpdateAnimation needComposite=%d mAnimation=%p\n", this,
- needComposite, mAnimation.get());
+ APZC_LOGV_DETAIL("UpdateAnimation needComposite=%d mAnimation=%p\n", this,
+ needComposite, mAnimation.get());
TimeDuration sampleTimeDelta = aSampleTime - mLastSampleTime;
mLastSampleTime = aSampleTime;
@@ -5581,17 +5590,6 @@ void AsyncPanZoomController::NotifyLayersUpdated(
aScrollMetadata.GetOverscrollBehavior());
}
- if (needToReclampScroll) {
- // Whenever scrollable rect or composition bounds has changed, we need to
- // re-clamp the scroll offset since it may be out of bounds. Also note that
- // we need to re-clamp before updating new scroll offsets from content since
- // we will use the last scroll offset to reflect the new offsets.
- ClampAndSetVisualScrollOffset(Metrics().GetVisualScrollOffset());
- for (auto& sampledState : mSampledState) {
- sampledState.ClampVisualScrollOffset(Metrics());
- }
- }
-
bool instantScrollMayTriggerTransform = false;
bool scrollOffsetUpdated = false;
bool smoothScrollRequested = false;
@@ -5738,20 +5736,11 @@ void AsyncPanZoomController::NotifyLayersUpdated(
relativeDelta =
Some(Metrics().ApplyPureRelativeScrollUpdateFrom(scrollUpdate));
Metrics().RecalculateLayoutViewportOffset();
- } else if (scrollUpdate.GetType() == ScrollUpdateType::MergeableAbsolute) {
- APZC_LOG("%p mergeable updating scroll offset from %s to %s\n", this,
- ToString(Metrics().GetVisualScrollOffset()).c_str(),
- ToString(scrollUpdate.GetDestination()).c_str());
- relativeDelta =
- Some(Metrics().ApplyAbsoluteScrollUpdateFrom(scrollUpdate).second);
- Metrics().RecalculateLayoutViewportOffset();
- scrollOffsetUpdated = true;
} else {
APZC_LOG("%p updating scroll offset from %s to %s\n", this,
ToString(Metrics().GetVisualScrollOffset()).c_str(),
ToString(scrollUpdate.GetDestination()).c_str());
- auto [offsetChanged, _] =
- Metrics().ApplyAbsoluteScrollUpdateFrom(scrollUpdate);
+ bool offsetChanged = Metrics().ApplyScrollUpdateFrom(scrollUpdate);
Metrics().RecalculateLayoutViewportOffset();
if (offsetChanged || scrollUpdate.GetMode() != ScrollMode::Instant ||
@@ -5788,6 +5777,15 @@ void AsyncPanZoomController::NotifyLayersUpdated(
}
}
+ if (aIsFirstPaint || needToReclampScroll) {
+ // The scrollable rect or composition bounds may have changed in a way that
+ // makes our local scroll offset out of bounds, so clamp it.
+ ClampAndSetVisualScrollOffset(Metrics().GetVisualScrollOffset());
+ for (auto& sampledState : mSampledState) {
+ sampledState.ClampVisualScrollOffset(Metrics());
+ }
+ }
+
if (scrollOffsetUpdated) {
for (auto& sampledState : mSampledState) {
if (!didCancelAnimation && cumulativeRelativeDelta.isSome()) {
diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h
index fdc72b1971..d0c4537a66 100644
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -1305,6 +1305,8 @@ class AsyncPanZoomController {
*/
CSSRect GetCurrentScrollRangeInCssPixels() const;
+ bool AllowOneTouchPinch() const;
+
private:
/**
* Advances to the next sample, if there is one, the list of sampled states
diff --git a/gfx/layers/apz/src/AutoscrollAnimation.cpp b/gfx/layers/apz/src/AutoscrollAnimation.cpp
index 8d4b8fca10..45063ef2b4 100644
--- a/gfx/layers/apz/src/AutoscrollAnimation.cpp
+++ b/gfx/layers/apz/src/AutoscrollAnimation.cpp
@@ -17,7 +17,7 @@ namespace mozilla {
namespace layers {
// Helper function for AutoscrollAnimation::DoSample().
-// Basically copied as-is from toolkit/actors/AutoScrollChild.jsm.
+// Basically copied as-is from toolkit/actors/AutoScrollChild.sys.mjs.
static float Accelerate(ScreenCoord curr, ScreenCoord start) {
static const int speed = 12;
float val = (curr - start) / speed;
diff --git a/gfx/layers/apz/src/GenericScrollAnimation.cpp b/gfx/layers/apz/src/GenericScrollAnimation.cpp
index 04ca8c4697..62f19fab35 100644
--- a/gfx/layers/apz/src/GenericScrollAnimation.cpp
+++ b/gfx/layers/apz/src/GenericScrollAnimation.cpp
@@ -15,6 +15,9 @@
#include "ScrollAnimationMSDPhysics.h"
#include "mozilla/StaticPrefs_general.h"
+static mozilla::LazyLogModule sApzScrollAnimLog("apz.scrollanimation");
+#define GSA_LOG(...) MOZ_LOG(sApzScrollAnimLog, LogLevel::Debug, (__VA_ARGS__))
+
namespace mozilla {
namespace layers {
@@ -101,6 +104,12 @@ bool GenericScrollAnimation::DoSample(FrameMetrics& aFrameMetrics,
// then end the animation early. Note that the initial displacement could be 0
// if the compositor ran very quickly (<1ms) after the animation was created.
// When that happens we want to make sure the animation continues.
+ GSA_LOG(
+ "Sampling GenericScrollAnimation: time %f finished %d sampledDest %s "
+ "adjustedOffset %s overscroll %s\n",
+ (now - TimeStamp::ProcessCreation()).ToMilliseconds(), finished,
+ ToString(CSSPoint::FromAppUnits(sampledDest)).c_str(),
+ ToString(adjustedOffset).c_str(), ToString(overscroll).c_str());
if (!IsZero(displacement / zoom) && IsZero(adjustedOffset / zoom)) {
// Nothing more to do - end the animation.
return false;
diff --git a/gfx/layers/apz/src/GestureEventListener.cpp b/gfx/layers/apz/src/GestureEventListener.cpp
index b54674b593..4300e9ba41 100644
--- a/gfx/layers/apz/src/GestureEventListener.cpp
+++ b/gfx/layers/apz/src/GestureEventListener.cpp
@@ -5,13 +5,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GestureEventListener.h"
-#include <algorithm> // for max
+#include <algorithm> // for max
+#include <ostream>
#include <math.h> // for fabsf
#include <stddef.h> // for size_t
#include "AsyncPanZoomController.h" // for AsyncPanZoomController
#include "InputBlockState.h" // for TouchBlockState
#include "base/task.h" // for CancelableTask, etc
#include "InputBlockState.h" // for TouchBlockState
+#include "mozilla/Assertions.h"
+#include "mozilla/EventForwards.h"
#include "mozilla/StaticPrefs_apz.h"
#include "mozilla/StaticPrefs_ui.h"
#include "nsDebug.h" // for NS_WARNING
@@ -83,8 +86,8 @@ GestureEventListener::~GestureEventListener() = default;
nsEventStatus GestureEventListener::HandleInputEvent(
const MultiTouchInput& aEvent) {
- GEL_LOG("Receiving event type %d with %zu touches in state %d\n",
- aEvent.mType, aEvent.mTouches.Length(), mState);
+ GEL_LOG("Receiving event type %d with %zu touches in state %s\n",
+ aEvent.mType, aEvent.mTouches.Length(), ToString(mState).c_str());
nsEventStatus rv = nsEventStatus_eIgnore;
@@ -175,16 +178,15 @@ nsEventStatus GestureEventListener::HandleInputTouchSingleStart() {
EnterFirstSingleTouchDown();
break;
case GESTURE_FIRST_SINGLE_TOUCH_UP:
+ // Bail out of any gesture that includes the first tap.
+ CancelLongTapTimeoutTask();
+ CancelMaxTapTimeoutTask();
if (SecondTapIsFar()) {
- // If the second tap goes down far away from the first, then bail out
- // of any gesture that includes the first tap.
- CancelLongTapTimeoutTask();
- CancelMaxTapTimeoutTask();
- mSingleTapSent = Nothing();
-
- // But still allow the second tap to participate in a gesture
+ // If the second tap goes down far away from the first,
+ // allow the second tap to participate in a gesture
// (e.g. lead to a single tap, or a double tap if an additional
// tap occurs near the same location).
+ mSingleTapSent = Nothing();
EnterFirstSingleTouchDown();
} else {
// Otherwise, reset the touch start position so that, if this turns into
@@ -225,9 +227,10 @@ nsEventStatus GestureEventListener::HandleInputTouchMultiStart() {
rv = nsEventStatus_eConsumeNoDefault;
break;
case GESTURE_FIRST_SINGLE_TOUCH_UP:
- case GESTURE_SECOND_SINGLE_TOUCH_DOWN:
// Cancel wait for double tap
CancelMaxTapTimeoutTask();
+ [[fallthrough]];
+ case GESTURE_SECOND_SINGLE_TOUCH_DOWN:
MOZ_ASSERT(mSingleTapSent.isSome());
if (!mSingleTapSent.value()) {
TriggerSingleTapConfirmedEvent();
@@ -307,12 +310,8 @@ nsEventStatus GestureEventListener::HandleInputTouchMove() {
// If touch has moved noticeably (within StaticPrefs::apz_max_tap_time()),
// change state.
if (MoveDistanceIsLarge()) {
- CancelLongTapTimeoutTask();
- CancelMaxTapTimeoutTask();
mSingleTapSent = Nothing();
- if (!StaticPrefs::apz_one_touch_pinch_enabled()) {
- // If the one-touch-pinch feature is disabled, bail out of the double-
- // tap gesture instead.
+ if (!mAsyncPanZoomController->AllowOneTouchPinch()) {
SetState(GESTURE_NONE);
break;
}
@@ -451,7 +450,6 @@ nsEventStatus GestureEventListener::HandleInputTouchEnd() {
}
case GESTURE_SECOND_SINGLE_TOUCH_DOWN: {
- CancelMaxTapTimeoutTask();
MOZ_ASSERT(mSingleTapSent.isSome());
mAsyncPanZoomController->HandleGestureEvent(CreateTapEvent(
mLastTouchInput, mSingleTapSent.value()
@@ -535,7 +533,9 @@ nsEventStatus GestureEventListener::HandleInputTouchCancel() {
}
void GestureEventListener::HandleInputTimeoutLongTap() {
- GEL_LOG("Running long-tap timeout task in state %d\n", mState);
+ MOZ_ASSERT(mState != GESTURE_SECOND_SINGLE_TOUCH_DOWN);
+ GEL_LOG("Running long-tap timeout task in state %s\n",
+ ToString(mState).c_str());
mLongTapTimeoutTask = nullptr;
@@ -559,14 +559,15 @@ void GestureEventListener::HandleInputTimeoutLongTap() {
}
void GestureEventListener::HandleInputTimeoutMaxTap(bool aDuringFastFling) {
- GEL_LOG("Running max-tap timeout task in state %d\n", mState);
+ MOZ_ASSERT(mState != GESTURE_SECOND_SINGLE_TOUCH_DOWN);
+ GEL_LOG("Running max-tap timeout task in state %s\n",
+ ToString(mState).c_str());
mMaxTapTimeoutTask = nullptr;
if (mState == GESTURE_FIRST_SINGLE_TOUCH_DOWN) {
SetState(GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN);
- } else if (mState == GESTURE_FIRST_SINGLE_TOUCH_UP ||
- mState == GESTURE_SECOND_SINGLE_TOUCH_DOWN) {
+ } else if (mState == GESTURE_FIRST_SINGLE_TOUCH_UP) {
MOZ_ASSERT(mSingleTapSent.isSome());
if (!aDuringFastFling && !mSingleTapSent.value()) {
TriggerSingleTapConfirmedEvent();
@@ -585,6 +586,8 @@ void GestureEventListener::TriggerSingleTapConfirmedEvent() {
}
void GestureEventListener::SetState(GestureState aState) {
+ GEL_LOG("State change from %s to %s", ToString(mState).c_str(),
+ ToString(aState).c_str());
mState = aState;
if (mState == GESTURE_NONE) {
@@ -598,10 +601,7 @@ void GestureEventListener::SetState(GestureState aState) {
}
void GestureEventListener::CancelLongTapTimeoutTask() {
- if (mState == GESTURE_SECOND_SINGLE_TOUCH_DOWN) {
- // being in this state means the task has been canceled already
- return;
- }
+ MOZ_ASSERT(mState != GESTURE_SECOND_SINGLE_TOUCH_DOWN);
if (mLongTapTimeoutTask) {
mLongTapTimeoutTask->Cancel();
@@ -628,6 +628,8 @@ void GestureEventListener::CreateLongTapTimeoutTask() {
}
void GestureEventListener::CancelMaxTapTimeoutTask() {
+ MOZ_ASSERT(mState != GESTURE_SECOND_SINGLE_TOUCH_DOWN);
+
if (mState == GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN) {
// being in this state means the timer has just been triggered
return;
@@ -659,5 +661,40 @@ void GestureEventListener::CreateMaxTapTimeoutTask() {
std::max(0L, remainingDelay));
}
+std::ostream& operator<<(std::ostream& os,
+ GestureEventListener::GestureState aState) {
+ switch (aState) {
+ case GestureEventListener::GESTURE_NONE:
+ os << "GESTURE_NONE";
+ break;
+ case GestureEventListener::GESTURE_FIRST_SINGLE_TOUCH_DOWN:
+ os << "GESTURE_FIRST_SINGLE_TOUCH_DOWN";
+ break;
+ case GestureEventListener::GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN:
+ os << "GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN";
+ break;
+ case GestureEventListener::GESTURE_FIRST_SINGLE_TOUCH_UP:
+ os << "GESTURE_FIRST_SINGLE_TOUCH_UP";
+ break;
+ case GestureEventListener::GESTURE_SECOND_SINGLE_TOUCH_DOWN:
+ os << "GESTURE_SECOND_SINGLE_TOUCH_DOWN";
+ break;
+ case GestureEventListener::GESTURE_LONG_TOUCH_DOWN:
+ os << "GESTURE_LONG_TOUCH_DOWN";
+ break;
+ case GestureEventListener::GESTURE_MULTI_TOUCH_DOWN:
+ os << "GESTURE_MULTI_TOUCH_DOWN";
+ break;
+ case GestureEventListener::GESTURE_PINCH:
+ os << "GESTURE_PINCH";
+ break;
+ case GestureEventListener::GESTURE_ONE_TOUCH_PINCH:
+ os << "GESTURE_ONE_TOUCH_PINCH";
+ break;
+ }
+
+ return os;
+}
+
} // namespace layers
} // namespace mozilla
diff --git a/gfx/layers/apz/src/GestureEventListener.h b/gfx/layers/apz/src/GestureEventListener.h
index aa51889fdd..bf50d4f40a 100644
--- a/gfx/layers/apz/src/GestureEventListener.h
+++ b/gfx/layers/apz/src/GestureEventListener.h
@@ -7,6 +7,7 @@
#ifndef mozilla_layers_GestureEventListener_h
#define mozilla_layers_GestureEventListener_h
+#include <iosfwd>
#include "InputData.h" // for MultiTouchInput, etc
#include "Units.h"
#include "mozilla/EventForwards.h" // for nsEventStatus
@@ -135,6 +136,8 @@ class GestureEventListener final {
GESTURE_ONE_TOUCH_PINCH
};
+ friend std::ostream& operator<<(std::ostream& os, GestureState aState);
+
/**
* These HandleInput* functions comprise input alphabet of the GEL
* finite-state machine triggering state transitions.