diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:27 +0000 |
commit | 40a355a42d4a9444dc753c04c6608dade2f06a23 (patch) | |
tree | 871fc667d2de662f171103ce5ec067014ef85e61 /layout/base/TouchManager.cpp | |
parent | Adding upstream version 124.0.1. (diff) | |
download | firefox-adbda400be353e676059e335c3c0aaf99e719475.tar.xz firefox-adbda400be353e676059e335c3c0aaf99e719475.zip |
Adding upstream version 125.0.1.upstream/125.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'layout/base/TouchManager.cpp')
-rw-r--r-- | layout/base/TouchManager.cpp | 130 |
1 files changed, 121 insertions, 9 deletions
diff --git a/layout/base/TouchManager.cpp b/layout/base/TouchManager.cpp index 0c34567b65..42ea78eb2e 100644 --- a/layout/base/TouchManager.cpp +++ b/layout/base/TouchManager.cpp @@ -7,9 +7,13 @@ #include "TouchManager.h" +#include "Units.h" +#include "mozilla/EventForwards.h" +#include "mozilla/PresShell.h" +#include "mozilla/StaticPrefs_test.h" +#include "mozilla/TimeStamp.h" #include "mozilla/dom/Document.h" #include "mozilla/dom/EventTarget.h" -#include "mozilla/PresShell.h" #include "mozilla/layers/InputAPZContext.h" #include "nsIContent.h" #include "nsIFrame.h" @@ -24,6 +28,8 @@ namespace mozilla { StaticAutoPtr<nsTHashMap<nsUint32HashKey, TouchManager::TouchInfo>> TouchManager::sCaptureTouchList; layers::LayersId TouchManager::sCaptureTouchLayersId; +TimeStamp TouchManager::sSingleTouchStartTimeStamp; +LayoutDeviceIntPoint TouchManager::sSingleTouchStartPoint; /*static*/ void TouchManager::InitializeStatics() { @@ -168,7 +174,7 @@ nsIFrame* TouchManager::SuppressInvalidPointsAndGetTargetedFrame( } nsIFrame* frame = nullptr; - for (int32_t i = aEvent->mTouches.Length(); i;) { + for (uint32_t i = aEvent->mTouches.Length(); i;) { --i; dom::Touch* touch = aEvent->mTouches[i]; if (TouchManager::HasCapturedTouch(touch->Identifier())) { @@ -176,9 +182,35 @@ nsIFrame* TouchManager::SuppressInvalidPointsAndGetTargetedFrame( } MOZ_ASSERT(touch->mOriginalTarget); - nsCOMPtr<nsIContent> targetContent = do_QueryInterface(touch->GetTarget()); - nsIFrame* targetFrame = - targetContent ? targetContent->GetPrimaryFrame() : nullptr; + nsIContent* const targetContent = + nsIContent::FromEventTargetOrNull(touch->GetTarget()); + if (MOZ_UNLIKELY(!targetContent)) { + touch->mIsTouchEventSuppressed = true; + continue; + } + + // Even if the target content is not connected, we should dispatch the touch + // start event except when the target content is owned by different + // document. + if (MOZ_UNLIKELY(!targetContent->IsInComposedDoc())) { + if (anyTarget && anyTarget->OwnerDoc() != targetContent->OwnerDoc()) { + touch->mIsTouchEventSuppressed = true; + continue; + } + if (!anyTarget) { + anyTarget = targetContent; + } + touch->SetTouchTarget(targetContent->GetAsElementOrParentElement()); + if (PresShell* const presShell = + targetContent->OwnerDoc()->GetPresShell()) { + if (nsIFrame* rootFrame = presShell->GetRootFrame()) { + frame = rootFrame; + } + } + continue; + } + + nsIFrame* targetFrame = targetContent->GetPrimaryFrame(); if (targetFrame && !anyTarget) { anyTarget = targetContent; } else { @@ -202,10 +234,12 @@ nsIFrame* TouchManager::SuppressInvalidPointsAndGetTargetedFrame( touch->mIsTouchEventSuppressed = true; } else { targetFrame = newTargetFrame; - targetFrame->GetContentForEvent(aEvent, getter_AddRefs(targetContent)); - touch->SetTouchTarget(targetContent - ? targetContent->GetAsElementOrParentElement() - : nullptr); + nsCOMPtr<nsIContent> newTargetContent; + targetFrame->GetContentForEvent(aEvent, + getter_AddRefs(newTargetContent)); + touch->SetTouchTarget( + newTargetContent ? newTargetContent->GetAsElementOrParentElement() + : nullptr); } } if (targetFrame) { @@ -236,8 +270,11 @@ bool TouchManager::PreHandleEvent(WidgetEvent* aEvent, nsEventStatus* aStatus, // touch event associated to. We cache layers id of the first touchstart // event, all subsequent touch events will use the same layers id. sCaptureTouchLayersId = aEvent->mLayersId; + sSingleTouchStartTimeStamp = aEvent->mTimeStamp; + sSingleTouchStartPoint = aEvent->AsTouchEvent()->mTouches[0]->mRefPoint; } else { touchEvent->mLayersId = sCaptureTouchLayersId; + sSingleTouchStartTimeStamp = TimeStamp(); } // Add any new touches to the queue WidgetTouchEvent::TouchArray& touches = touchEvent->mTouches; @@ -404,6 +441,60 @@ bool TouchManager::PreHandleEvent(WidgetEvent* aEvent, nsEventStatus* aStatus, return true; } +void TouchManager::PostHandleEvent(const WidgetEvent* aEvent, + const nsEventStatus* aStatus) { + switch (aEvent->mMessage) { + case eTouchMove: { + if (sSingleTouchStartTimeStamp.IsNull()) { + break; + } + if (*aStatus == nsEventStatus_eConsumeNoDefault) { + sSingleTouchStartTimeStamp = TimeStamp(); + break; + } + const WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent(); + if (touchEvent->mTouches.Length() > 1) { + sSingleTouchStartTimeStamp = TimeStamp(); + break; + } + if (touchEvent->mTouches.Length() == 1) { + // If the touch moved too far from the start point, don't treat the + // touch as a tap. + const float distance = + static_cast<float>((sSingleTouchStartPoint - + aEvent->AsTouchEvent()->mTouches[0]->mRefPoint) + .Length()); + const float maxDistance = + StaticPrefs::apz_touch_start_tolerance() * + (MOZ_LIKELY(touchEvent->mWidget) ? touchEvent->mWidget->GetDPI() + : 96.0f); + if (distance > maxDistance) { + sSingleTouchStartTimeStamp = TimeStamp(); + } + } + break; + } + case eTouchStart: + case eTouchEnd: + if (*aStatus == nsEventStatus_eConsumeNoDefault && + !sSingleTouchStartTimeStamp.IsNull()) { + sSingleTouchStartTimeStamp = TimeStamp(); + } + break; + case eTouchCancel: + case eTouchPointerCancel: + case eMouseLongTap: + case eContextMenu: { + if (!sSingleTouchStartTimeStamp.IsNull()) { + sSingleTouchStartTimeStamp = TimeStamp(); + } + break; + } + default: + break; + } +} + /*static*/ already_AddRefed<nsIContent> TouchManager::GetAnyCapturedTouchTarget() { nsCOMPtr<nsIContent> result = nullptr; @@ -473,4 +564,25 @@ bool TouchManager::ShouldConvertTouchToPointer(const Touch* aTouch, return true; } +/* static */ +bool TouchManager::IsSingleTapEndToDoDefault( + const WidgetTouchEvent* aTouchEndEvent) { + MOZ_ASSERT(aTouchEndEvent); + MOZ_ASSERT(aTouchEndEvent->mFlags.mIsSynthesizedForTests); + MOZ_ASSERT(!StaticPrefs::test_events_async_enabled()); + if (sSingleTouchStartTimeStamp.IsNull() || + aTouchEndEvent->mTouches.Length() != 1) { + return false; + } + // If it's pressed long time, we should not treat it as a single tap because + // a long press should cause opening context menu by default. + if ((aTouchEndEvent->mTimeStamp - sSingleTouchStartTimeStamp) + .ToMilliseconds() > StaticPrefs::apz_max_tap_time()) { + return false; + } + NS_WARNING_ASSERTION(aTouchEndEvent->mTouches[0]->mChanged, + "The single tap end should be changed"); + return true; +} + } // namespace mozilla |