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
This commit is contained in:
Emilio Cobos Álvarez 2022-01-04 13:31:34 +00:00
Родитель 66f45bff6a
Коммит 17025d2d80
12 изменённых файлов: 76 добавлений и 135 удалений

Просмотреть файл

@ -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<nsIBrowserChild*>(this))); // for capture by the lambda
mSetAllowedTouchBehaviorCallback =
[weakPtrThis](uint64_t aInputBlockId,
const nsTArray<TouchBehaviorFlags>& aFlags) {
if (nsCOMPtr<nsIBrowserChild> browserChild =
do_QueryReferent(weakPtrThis)) {
static_cast<BrowserChild*>(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<TouchBehaviorFlags>& aTargets) const {
if (mApzcTreeManager) {
mApzcTreeManager->SetAllowedTouchBehavior(aInputBlockId, aTargets);
}
}
bool BrowserChild::DoUpdateZoomConstraints(
const uint32_t& aPresShellId, const ViewID& aViewId,
const Maybe<ZoomConstraints>& aConstraints) {
@ -1934,10 +1915,12 @@ mozilla::ipc::IPCResult BrowserChild::RecvRealTouchEvent(
if (localEvent.mMessage == eTouchStart && AsyncPanZoomEnabled()) {
nsCOMPtr<Document> 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<DisplayportSetListener> postLayerization =
APZCCallbackHelper::SendSetTargetAPZCNotification(

Просмотреть файл

@ -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<TouchBehaviorFlags>& aFlags) const;
bool UpdateFrame(const layers::RepaintRequest& aRequest);
bool NotifyAPZStateChange(
const ViewID& aViewId,
@ -816,7 +811,6 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
RefPtr<VsyncMainChild> mVsyncChild;
RefPtr<APZEventState> mAPZEventState;
SetAllowedTouchBehaviorCallback mSetAllowedTouchBehaviorCallback;
// Position of client area relative to the outer window
LayoutDeviceIntPoint mClientOffset;

Просмотреть файл

@ -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<TouchBehaviorFlags>
APZCCallbackHelper::SendSetAllowedTouchBehaviorNotification(
nsIWidget* aWidget, dom::Document* aDocument,
const WidgetTouchEvent& aEvent, uint64_t aInputBlockId,
const SetAllowedTouchBehaviorCallback& aCallback) {
nsTArray<TouchBehaviorFlags> 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<nsIContent> targetContent = nsLayoutUtils::FindContentFor(aScrollId);

Просмотреть файл

@ -33,9 +33,6 @@ namespace layers {
struct RepaintRequest;
typedef std::function<void(uint64_t, const nsTArray<TouchBehaviorFlags>&)>
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<TouchBehaviorFlags> 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);

Просмотреть файл

@ -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<TouchBehaviorFlags> TouchActionHelper::GetAllowedTouchBehavior(
nsIWidget* aWidget, dom::Document* aDocument,
const WidgetTouchEvent& aEvent) {
nsTArray<TouchBehaviorFlags> 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

Просмотреть файл

@ -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<TouchBehaviorFlags> GetAllowedTouchBehavior(
nsIWidget* aWidget, dom::Document* aDocument,
const WidgetTouchEvent& aPoint);
};
} // namespace layers
} // namespace mozilla
} // namespace mozilla::layers
#endif /*__mozilla_layers_TouchActionHelper_h__ */

Просмотреть файл

@ -8955,30 +8955,6 @@ Maybe<ScrollMetadata> 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,

Просмотреть файл

@ -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

Просмотреть файл

@ -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::Cursor> 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) {

Просмотреть файл

@ -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,

Просмотреть файл

@ -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<IAPZCTreeManager> 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<TouchBehaviorFlags>& 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<TouchBehaviorFlags> 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);
}

Просмотреть файл

@ -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<IAPZCTreeManager> mAPZC;
RefPtr<GeckoContentController> mRootContentController;
RefPtr<APZEventState> mAPZEventState;
SetAllowedTouchBehaviorCallback mSetAllowedTouchBehaviorCallback;
RefPtr<WidgetShutdownObserver> mShutdownObserver;
RefPtr<LocalesChangedObserver> mLocalesChangedObserver;
RefPtr<TextEventDispatcher> mTextEventDispatcher;