From 17025d2d80df5a314ff50619d83b4a1b2c38aa84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 4 Jan 2022 13:31:34 +0000 Subject: [PATCH] Bug 1748174 - Clean-up a bit touch-action code. r=hiro This shouldn't change behavior but makes following the code a bit easier. There's no point in using callbacks for touch-action as: * We return the computed flags anyways. * Each caller wants to do something different. * (more importantly) The callback gets called synchronously. So move the relevant code to TouchActionHelper and make the callers deal with the flags as they please. I've preserved the behavior of only doing the thing if the flags array is non-empty. Differential Revision: https://phabricator.services.mozilla.com/D134933 --- dom/ipc/BrowserChild.cpp | 31 +++++---------------- dom/ipc/BrowserChild.h | 6 ---- gfx/layers/apz/util/APZCCallbackHelper.cpp | 24 ---------------- gfx/layers/apz/util/APZCCallbackHelper.h | 11 -------- gfx/layers/apz/util/TouchActionHelper.cpp | 32 +++++++++++++++++----- gfx/layers/apz/util/TouchActionHelper.h | 27 ++++++++++-------- layout/base/nsLayoutUtils.cpp | 24 ---------------- layout/base/nsLayoutUtils.h | 5 ---- layout/generic/nsIFrame.cpp | 16 +++++++++-- layout/generic/nsIFrame.h | 1 + widget/nsBaseWidget.cpp | 31 +++++++++------------ widget/nsBaseWidget.h | 3 -- 12 files changed, 76 insertions(+), 135 deletions(-) diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp index 65942f7d4837..0a772a8f2d47 100644 --- a/dom/ipc/BrowserChild.cpp +++ b/dom/ipc/BrowserChild.cpp @@ -83,6 +83,7 @@ #include "mozilla/ipc/PBackgroundChild.h" #include "mozilla/ipc/URIUtils.h" #include "mozilla/layers/APZCCallbackHelper.h" +#include "mozilla/layers/TouchActionHelper.h" #include "mozilla/layers/APZCTreeManagerChild.h" #include "mozilla/layers/APZChild.h" #include "mozilla/layers/APZEventState.h" @@ -347,18 +348,6 @@ BrowserChild::BrowserChild(ContentChild* aManager, const TabId& aTabId, mCancelContentJSEpoch(0) { mozilla::HoldJSObjects(this); - nsWeakPtr weakPtrThis(do_GetWeakReference( - static_cast(this))); // for capture by the lambda - mSetAllowedTouchBehaviorCallback = - [weakPtrThis](uint64_t aInputBlockId, - const nsTArray& aFlags) { - if (nsCOMPtr browserChild = - do_QueryReferent(weakPtrThis)) { - static_cast(browserChild.get()) - ->SetAllowedTouchBehavior(aInputBlockId, aFlags); - } - }; - // preloaded BrowserChild should not be added to child map if (mUniqueId) { MOZ_ASSERT(NestedBrowserChildMap().find(mUniqueId) == @@ -426,14 +415,6 @@ void BrowserChild::SetTargetAPZC( } } -void BrowserChild::SetAllowedTouchBehavior( - uint64_t aInputBlockId, - const nsTArray& aTargets) const { - if (mApzcTreeManager) { - mApzcTreeManager->SetAllowedTouchBehavior(aInputBlockId, aTargets); - } -} - bool BrowserChild::DoUpdateZoomConstraints( const uint32_t& aPresShellId, const ViewID& aViewId, const Maybe& aConstraints) { @@ -1934,10 +1915,12 @@ mozilla::ipc::IPCResult BrowserChild::RecvRealTouchEvent( if (localEvent.mMessage == eTouchStart && AsyncPanZoomEnabled()) { nsCOMPtr document = GetTopLevelDocument(); if (StaticPrefs::layout_css_touch_action_enabled()) { - allowedTouchBehaviors = - APZCCallbackHelper::SendSetAllowedTouchBehaviorNotification( - mPuppetWidget, document, localEvent, aInputBlockId, - mSetAllowedTouchBehaviorCallback); + allowedTouchBehaviors = TouchActionHelper::GetAllowedTouchBehavior( + mPuppetWidget, document, localEvent); + if (!allowedTouchBehaviors.IsEmpty() && mApzcTreeManager) { + mApzcTreeManager->SetAllowedTouchBehavior(aInputBlockId, + allowedTouchBehaviors); + } } RefPtr postLayerization = APZCCallbackHelper::SendSetTargetAPZCNotification( diff --git a/dom/ipc/BrowserChild.h b/dom/ipc/BrowserChild.h index 9e3f55419dce..c4cfa250f65a 100644 --- a/dom/ipc/BrowserChild.h +++ b/dom/ipc/BrowserChild.h @@ -170,8 +170,6 @@ class BrowserChild final : public nsMessageManagerScriptExecutor, using CoalescedMouseData = mozilla::dom::CoalescedMouseData; using CoalescedWheelData = mozilla::dom::CoalescedWheelData; using APZEventState = mozilla::layers::APZEventState; - using SetAllowedTouchBehaviorCallback = - mozilla::layers::SetAllowedTouchBehaviorCallback; using TouchBehaviorFlags = mozilla::layers::TouchBehaviorFlags; friend class PBrowserChild; @@ -608,9 +606,6 @@ class BrowserChild final : public nsMessageManagerScriptExecutor, const LayoutDevicePoint& aPoint, const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid, const uint64_t& aInputBlockId); - void SetAllowedTouchBehavior( - uint64_t aInputBlockId, const nsTArray& aFlags) const; - bool UpdateFrame(const layers::RepaintRequest& aRequest); bool NotifyAPZStateChange( const ViewID& aViewId, @@ -816,7 +811,6 @@ class BrowserChild final : public nsMessageManagerScriptExecutor, RefPtr mVsyncChild; RefPtr mAPZEventState; - SetAllowedTouchBehaviorCallback mSetAllowedTouchBehaviorCallback; // Position of client area relative to the outer window LayoutDeviceIntPoint mClientOffset; diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index 9a88ade4d658..862a846ccec0 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -6,7 +6,6 @@ #include "APZCCallbackHelper.h" -#include "TouchActionHelper.h" #include "gfxPlatform.h" // For gfxPlatform::UseTiling #include "mozilla/EventForwards.h" @@ -19,7 +18,6 @@ #include "mozilla/layers/WebRenderBridgeChild.h" #include "mozilla/DisplayPortUtils.h" #include "mozilla/PresShell.h" -#include "mozilla/TouchEvents.h" #include "mozilla/ToString.h" #include "mozilla/ViewportUtils.h" #include "nsContainerFrame.h" @@ -785,28 +783,6 @@ APZCCallbackHelper::SendSetTargetAPZCNotification(nsIWidget* aWidget, return nullptr; } -nsTArray -APZCCallbackHelper::SendSetAllowedTouchBehaviorNotification( - nsIWidget* aWidget, dom::Document* aDocument, - const WidgetTouchEvent& aEvent, uint64_t aInputBlockId, - const SetAllowedTouchBehaviorCallback& aCallback) { - nsTArray flags; - if (!aWidget || !aDocument) { - return flags; - } - if (PresShell* presShell = aDocument->GetPresShell()) { - if (nsIFrame* rootFrame = presShell->GetRootFrame()) { - for (uint32_t i = 0; i < aEvent.mTouches.Length(); i++) { - flags.AppendElement(TouchActionHelper::GetAllowedTouchBehavior( - aWidget, RelativeTo{rootFrame, ViewportType::Visual}, - aEvent.mTouches[i]->mRefPoint)); - } - aCallback(aInputBlockId, flags); - } - } - return flags; -} - void APZCCallbackHelper::NotifyMozMouseScrollEvent( const ScrollableLayerGuid::ViewID& aScrollId, const nsString& aEvent) { nsCOMPtr targetContent = nsLayoutUtils::FindContentFor(aScrollId); diff --git a/gfx/layers/apz/util/APZCCallbackHelper.h b/gfx/layers/apz/util/APZCCallbackHelper.h index b566a3b9f4fa..89e3e0787ccc 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.h +++ b/gfx/layers/apz/util/APZCCallbackHelper.h @@ -33,9 +33,6 @@ namespace layers { struct RepaintRequest; -typedef std::function&)> - SetAllowedTouchBehaviorCallback; - /* Refer to documentation on SendSetTargetAPZCNotification for this class */ class DisplayportSetListener : public ManagedPostRefreshObserver { public: @@ -149,14 +146,6 @@ class APZCCallbackHelper { const WidgetGUIEvent& aEvent, const LayersId& aLayersId, uint64_t aInputBlockId); - /* Figure out the allowed touch behaviors of each touch point in |aEvent| - * and send that information to the provided callback. Also returns the - * allowed touch behaviors. */ - static nsTArray SendSetAllowedTouchBehaviorNotification( - nsIWidget* aWidget, mozilla::dom::Document* aDocument, - const WidgetTouchEvent& aEvent, uint64_t aInputBlockId, - const SetAllowedTouchBehaviorCallback& aCallback); - /* Notify content of a mouse scroll testing event. */ static void NotifyMozMouseScrollEvent( const ScrollableLayerGuid::ViewID& aScrollId, const nsString& aEvent); diff --git a/gfx/layers/apz/util/TouchActionHelper.cpp b/gfx/layers/apz/util/TouchActionHelper.cpp index 1cac71467f49..4442da134d61 100644 --- a/gfx/layers/apz/util/TouchActionHelper.cpp +++ b/gfx/layers/apz/util/TouchActionHelper.cpp @@ -7,13 +7,14 @@ #include "TouchActionHelper.h" #include "mozilla/layers/IAPZCTreeManager.h" +#include "mozilla/PresShell.h" +#include "mozilla/TouchEvents.h" #include "nsContainerFrame.h" #include "nsIFrameInlines.h" #include "nsIScrollableFrame.h" #include "nsLayoutUtils.h" -namespace mozilla { -namespace layers { +namespace mozilla::layers { static void UpdateAllowedBehavior(StyleTouchAction aTouchActionValue, bool aConsiderPanning, @@ -48,7 +49,7 @@ static void UpdateAllowedBehavior(StyleTouchAction aTouchActionValue, } } -TouchBehaviorFlags TouchActionHelper::GetAllowedTouchBehavior( +static TouchBehaviorFlags GetAllowedTouchBehaviorForPoint( nsIWidget* aWidget, RelativeTo aRootFrame, const LayoutDeviceIntPoint& aPoint) { TouchBehaviorFlags behavior = AllowedTouchBehavior::VERTICAL_PAN | @@ -89,8 +90,7 @@ TouchBehaviorFlags TouchActionHelper::GetAllowedTouchBehavior( for (nsIFrame* frame = target; frame && frame->GetContent() && behavior; frame = frame->GetInFlowParent()) { - UpdateAllowedBehavior(nsLayoutUtils::GetTouchActionFromFrame(frame), - considerPanning, behavior); + UpdateAllowedBehavior(frame->UsedTouchAction(), considerPanning, behavior); if (frame == nearestScrollableFrame) { // We met the scrollable element, after it we shouldn't consider @@ -102,5 +102,23 @@ TouchBehaviorFlags TouchActionHelper::GetAllowedTouchBehavior( return behavior; } -} // namespace layers -} // namespace mozilla +nsTArray TouchActionHelper::GetAllowedTouchBehavior( + nsIWidget* aWidget, dom::Document* aDocument, + const WidgetTouchEvent& aEvent) { + nsTArray flags; + if (!aWidget || !aDocument) { + return flags; + } + if (PresShell* presShell = aDocument->GetPresShell()) { + if (nsIFrame* rootFrame = presShell->GetRootFrame()) { + for (auto& touch : aEvent.mTouches) { + flags.AppendElement(GetAllowedTouchBehaviorForPoint( + aWidget, RelativeTo{rootFrame, ViewportType::Visual}, + touch->mRefPoint)); + } + } + } + return flags; +} + +} // namespace mozilla::layers diff --git a/gfx/layers/apz/util/TouchActionHelper.h b/gfx/layers/apz/util/TouchActionHelper.h index 723b276997ec..e23f36780fc7 100644 --- a/gfx/layers/apz/util/TouchActionHelper.h +++ b/gfx/layers/apz/util/TouchActionHelper.h @@ -10,11 +10,17 @@ #include "mozilla/layers/LayersTypes.h" // for TouchBehaviorFlags #include "RelativeTo.h" // for RelativeTo -class nsIFrame; class nsIWidget; - namespace mozilla { -namespace layers { + +namespace dom { +class Document; +} // namespace dom + +class WidgetTouchEvent; +} // namespace mozilla + +namespace mozilla::layers { /* * Helper class to figure out the allowed touch behavior for frames, as per @@ -23,17 +29,16 @@ namespace layers { class TouchActionHelper { public: /* - * Performs hit testing on content, finds frame that corresponds to the aPoint - * and retrieves touch-action css property value from it according the rules - * specified in the spec: + * Performs hit testing on content, finds frame that corresponds to the touch + * points of aEvent and retrieves touch-action CSS property value from it + * according the rules specified in the spec: * http://www.w3.org/TR/pointerevents/#the-touch-action-css-property. */ - static TouchBehaviorFlags GetAllowedTouchBehavior( - nsIWidget* aWidget, RelativeTo aRootFrame, - const LayoutDeviceIntPoint& aPoint); + static nsTArray GetAllowedTouchBehavior( + nsIWidget* aWidget, dom::Document* aDocument, + const WidgetTouchEvent& aPoint); }; -} // namespace layers -} // namespace mozilla +} // namespace mozilla::layers #endif /*__mozilla_layers_TouchActionHelper_h__ */ diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index f1aebe60b16c..bdffdbea78b1 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -8955,30 +8955,6 @@ Maybe nsLayoutUtils::GetRootMetadata( return Nothing(); } -/* static */ -StyleTouchAction nsLayoutUtils::GetTouchActionFromFrame(nsIFrame* aFrame) { - if (!aFrame) { - return StyleTouchAction::AUTO; - } - - // The touch-action CSS property applies to: all elements except: - // non-replaced inline elements, table rows, row groups, table columns, and - // column groups - bool isNonReplacedInlineElement = - aFrame->IsFrameOfType(nsIFrame::eLineParticipant); - if (isNonReplacedInlineElement) { - return StyleTouchAction::AUTO; - } - - const nsStyleDisplay* disp = aFrame->StyleDisplay(); - bool isTableElement = disp->IsInternalTableStyleExceptCell(); - if (isTableElement) { - return StyleTouchAction::AUTO; - } - - return disp->mTouchAction; -} - /* static */ void nsLayoutUtils::TransformToAncestorAndCombineRegions( const nsRegion& aRegion, nsIFrame* aFrame, const nsIFrame* aAncestorFrame, diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index db13a71cce77..45ad1872ba6f 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -2581,11 +2581,6 @@ class nsLayoutUtils { static void AssertTreeOnlyEmptyNextInFlows(nsIFrame* aSubtreeRoot); #endif - /** - * Helper method to get touch action behaviour from the frame - */ - static mozilla::StyleTouchAction GetTouchActionFromFrame(nsIFrame* aFrame); - /** * Helper method to transform |aBounds| from aFrame to aAncestorFrame, * and combine it with |aPreciseTargetDest| if it is axis-aligned, or diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp index 49a68d0a6cea..a0728c1ccea4 100644 --- a/layout/generic/nsIFrame.cpp +++ b/layout/generic/nsIFrame.cpp @@ -5755,6 +5755,19 @@ StyleImageRendering nsIFrame::UsedImageRendering() const { return style->StyleVisibility()->mImageRendering; } +// The touch-action CSS property applies to: all elements except: non-replaced +// inline elements, table rows, row groups, table columns, and column groups. +StyleTouchAction nsIFrame::UsedTouchAction() const { + if (IsFrameOfType(eLineParticipant)) { + return StyleTouchAction::AUTO; + } + auto& disp = *StyleDisplay(); + if (disp.IsInternalTableStyleExceptCell()) { + return StyleTouchAction::AUTO; + } + return disp.mTouchAction; +} + Maybe nsIFrame::GetCursor(const nsPoint&) { StyleCursorKind kind = StyleUI()->Cursor().keyword; if (kind == StyleCursorKind::Auto) { @@ -11408,8 +11421,7 @@ CompositorHitTestInfo nsIFrame::GetCompositorHitTestInfo( result += inheritedTouchAction; - const StyleTouchAction touchAction = - nsLayoutUtils::GetTouchActionFromFrame(touchActionFrame); + const StyleTouchAction touchAction = touchActionFrame->UsedTouchAction(); // The CSS allows the syntax auto | none | [pan-x || pan-y] | manipulation // so we can eliminate some combinations of things. if (touchAction == StyleTouchAction::AUTO) { diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index d2f18d199d6a..c990811f5249 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -2233,6 +2233,7 @@ class nsIFrame : public nsQueryFrame { void DisassociateImage(const mozilla::StyleImage&); mozilla::StyleImageRendering UsedImageRendering() const; + mozilla::StyleTouchAction UsedTouchAction() const; enum class AllowCustomCursorImage { No, diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index ec7191c195e2..16421040f826 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -41,6 +41,7 @@ #include "mozilla/gfx/GPUProcessManager.h" #include "mozilla/gfx/gfxVars.h" #include "mozilla/layers/APZCCallbackHelper.h" +#include "mozilla/layers/TouchActionHelper.h" #include "mozilla/layers/APZEventState.h" #include "mozilla/layers/APZInputBridge.h" #include "mozilla/layers/APZThreadUtils.h" @@ -842,22 +843,14 @@ void nsBaseWidget::ConfigureAPZCTreeManager() { mAPZC->SetKeyboardMap(map); } - RefPtr treeManager = mAPZC; // for capture by the lambdas - ContentReceivedInputBlockCallback callback( - [treeManager](uint64_t aInputBlockId, bool aPreventDefault) { + [treeManager = RefPtr{mAPZC.get()}](uint64_t aInputBlockId, + bool aPreventDefault) { MOZ_ASSERT(NS_IsMainThread()); treeManager->ContentReceivedInputBlock(aInputBlockId, aPreventDefault); }); mAPZEventState = new APZEventState(this, std::move(callback)); - mSetAllowedTouchBehaviorCallback = - [treeManager](uint64_t aInputBlockId, - const nsTArray& aFlags) { - MOZ_ASSERT(NS_IsMainThread()); - treeManager->SetAllowedTouchBehavior(aInputBlockId, aFlags); - }; - mRootContentController = CreateRootContentController(); if (mRootContentController) { mCompositorSession->SetContentController(mRootContentController); @@ -940,15 +933,17 @@ nsEventStatus nsBaseWidget::ProcessUntransformedAPZEvent( if (WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent()) { nsTArray allowedTouchBehaviors; if (touchEvent->mMessage == eTouchStart) { + auto& originalEvent = *original->AsTouchEvent(); if (StaticPrefs::layout_css_touch_action_enabled()) { - allowedTouchBehaviors = - APZCCallbackHelper::SendSetAllowedTouchBehaviorNotification( - this, GetDocument(), *(original->AsTouchEvent()), - inputBlockId, mSetAllowedTouchBehaviorCallback); + MOZ_ASSERT(NS_IsMainThread()); + allowedTouchBehaviors = TouchActionHelper::GetAllowedTouchBehavior( + this, GetDocument(), originalEvent); + if (!allowedTouchBehaviors.IsEmpty()) { + mAPZC->SetAllowedTouchBehavior(inputBlockId, allowedTouchBehaviors); + } } postLayerization = APZCCallbackHelper::SendSetTargetAPZCNotification( - this, GetDocument(), *(original->AsTouchEvent()), rootLayersId, - inputBlockId); + this, GetDocument(), originalEvent, rootLayersId, inputBlockId); } mAPZEventState->ProcessTouchEvent(*touchEvent, targetGuid, inputBlockId, aApzResult.GetStatus(), status, @@ -956,7 +951,7 @@ nsEventStatus nsBaseWidget::ProcessUntransformedAPZEvent( } else if (WidgetWheelEvent* wheelEvent = aEvent->AsWheelEvent()) { MOZ_ASSERT(wheelEvent->mFlags.mHandledByAPZ); postLayerization = APZCCallbackHelper::SendSetTargetAPZCNotification( - this, GetDocument(), *(original->AsWheelEvent()), rootLayersId, + this, GetDocument(), *original->AsWheelEvent(), rootLayersId, inputBlockId); if (wheelEvent->mCanTriggerSwipe) { ReportSwipeStarted(inputBlockId, wheelEvent->TriggersSwipe()); @@ -965,7 +960,7 @@ nsEventStatus nsBaseWidget::ProcessUntransformedAPZEvent( } else if (WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent()) { MOZ_ASSERT(mouseEvent->mFlags.mHandledByAPZ); postLayerization = APZCCallbackHelper::SendSetTargetAPZCNotification( - this, GetDocument(), *(original->AsMouseEvent()), rootLayersId, + this, GetDocument(), *original->AsMouseEvent(), rootLayersId, inputBlockId); mAPZEventState->ProcessMouseEvent(*mouseEvent, inputBlockId); } diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index 60eb466bd91b..45b090df17e1 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -144,8 +144,6 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference { typedef mozilla::layers::GeckoContentController GeckoContentController; typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid; typedef mozilla::layers::APZEventState APZEventState; - typedef mozilla::layers::SetAllowedTouchBehaviorCallback - SetAllowedTouchBehaviorCallback; typedef mozilla::CSSIntRect CSSIntRect; typedef mozilla::CSSRect CSSRect; typedef mozilla::ScreenRotation ScreenRotation; @@ -673,7 +671,6 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference { RefPtr mAPZC; RefPtr mRootContentController; RefPtr mAPZEventState; - SetAllowedTouchBehaviorCallback mSetAllowedTouchBehaviorCallback; RefPtr mShutdownObserver; RefPtr mLocalesChangedObserver; RefPtr mTextEventDispatcher;