Bug 1678505 - Add overscroll-behavior and scrollable directions into APZHandledResult. r=botond
Differential Revision: https://phabricator.services.mozilla.com/D103419
This commit is contained in:
@@ -387,12 +387,12 @@ class CompositableHandle final {
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
MOZ_DEFINE_ENUM_CLASS_WITH_BASE(ScrollDirection, uint32_t, (
|
||||
MOZ_DEFINE_ENUM_CLASS_WITH_BASE(ScrollDirection, uint8_t, (
|
||||
eVertical,
|
||||
eHorizontal
|
||||
));
|
||||
|
||||
typedef EnumSet<ScrollDirection> ScrollDirections;
|
||||
using ScrollDirections = EnumSet<ScrollDirection, uint8_t>;
|
||||
|
||||
constexpr ScrollDirections EitherScrollDirection(ScrollDirection::eVertical,ScrollDirection::eHorizontal);
|
||||
constexpr ScrollDirections HorizontalScrollDirection(ScrollDirection::eHorizontal);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "mozilla/EventForwards.h" // for WidgetInputEvent, nsEventStatus
|
||||
#include "mozilla/layers/APZPublicUtils.h" // for APZWheelAction
|
||||
#include "mozilla/layers/LayersTypes.h" // for ScrollDirections
|
||||
#include "mozilla/layers/ScrollableLayerGuid.h" // for ScrollableLayerGuid
|
||||
#include "Units.h" // for LayoutDeviceIntPoint
|
||||
|
||||
@@ -24,7 +25,7 @@ class InputBlockState;
|
||||
struct ScrollableLayerGuid;
|
||||
struct TargetConfirmationFlags;
|
||||
|
||||
enum class APZHandledResult : uint8_t {
|
||||
enum class APZHandledPlace : uint8_t {
|
||||
Unhandled = 0, // we know for sure that the event will not be handled
|
||||
// by either the root APZC or others
|
||||
HandledByRoot = 1, // we know for sure that the event will be handled
|
||||
@@ -36,6 +37,33 @@ enum class APZHandledResult : uint8_t {
|
||||
Last = Invalid
|
||||
};
|
||||
|
||||
struct APZHandledResult {
|
||||
APZHandledPlace mPlace = APZHandledPlace::Invalid;
|
||||
SideBits mScrollableDirections = SideBits::eNone;
|
||||
ScrollDirections mOverscrollDirections = ScrollDirections();
|
||||
|
||||
APZHandledResult() = default;
|
||||
APZHandledResult(APZHandledPlace aPlace,
|
||||
const AsyncPanZoomController* aTarget);
|
||||
APZHandledResult(APZHandledPlace aPlace, SideBits aScrollableDirections,
|
||||
ScrollDirections aOverscrollDirections)
|
||||
: mPlace(aPlace),
|
||||
mScrollableDirections(aScrollableDirections),
|
||||
mOverscrollDirections(aOverscrollDirections) {}
|
||||
|
||||
bool IsHandledByContent() const {
|
||||
return mPlace == APZHandledPlace::HandledByContent;
|
||||
}
|
||||
bool IsHandledByRoot() const {
|
||||
return mPlace == APZHandledPlace::HandledByRoot;
|
||||
}
|
||||
bool operator==(const APZHandledResult& aOther) const {
|
||||
return mPlace == aOther.mPlace &&
|
||||
mScrollableDirections == aOther.mScrollableDirections &&
|
||||
mOverscrollDirections == aOther.mOverscrollDirections;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents the outcome of APZ receiving and processing an input event.
|
||||
* This is returned from APZInputBridge::ReceiveInputEvent() and related APIs.
|
||||
|
||||
@@ -39,7 +39,7 @@ enum ZoomToRectBehavior : uint32_t {
|
||||
};
|
||||
|
||||
class AsyncDragMetrics;
|
||||
enum class APZHandledResult : uint8_t;
|
||||
struct APZHandledResult;
|
||||
|
||||
class IAPZCTreeManager {
|
||||
NS_INLINE_DECL_THREADSAFE_VIRTUAL_REFCOUNTING(IAPZCTreeManager)
|
||||
@@ -149,7 +149,7 @@ class IAPZCTreeManager {
|
||||
* the APZCTreeManager.
|
||||
*/
|
||||
using InputBlockCallback = std::function<void(
|
||||
uint64_t aInputBlockId, APZHandledResult aHandledResult)>;
|
||||
uint64_t aInputBlockId, const APZHandledResult& aHandledResult)>;
|
||||
virtual void AddInputBlockCallback(uint64_t aInputBlockId,
|
||||
InputBlockCallback&& aCallback) = 0;
|
||||
|
||||
|
||||
@@ -38,13 +38,15 @@ APZEventResult::APZEventResult(
|
||||
// If the initial target is not the root, this will definitely not be
|
||||
// handled by the root. (The confirmed target is either the initial
|
||||
// target, or a descendant.)
|
||||
return Some(APZHandledResult::HandledByContent);
|
||||
return Some(
|
||||
APZHandledResult{APZHandledPlace::HandledByContent, aInitialTarget});
|
||||
}
|
||||
|
||||
if (!aFlags.mDispatchToContent) {
|
||||
// If the initial target is the root and we don't need to dispatch to
|
||||
// content, the event will definitely be handled by the root.
|
||||
return Some(APZHandledResult::HandledByRoot);
|
||||
return Some(
|
||||
APZHandledResult{APZHandledPlace::HandledByRoot, aInitialTarget});
|
||||
}
|
||||
|
||||
// Otherwise, we're not sure.
|
||||
@@ -62,8 +64,9 @@ void APZEventResult::SetStatusAsConsumeDoDefault(
|
||||
const RefPtr<AsyncPanZoomController>& aTarget) {
|
||||
mStatus = nsEventStatus_eConsumeDoDefault;
|
||||
mHandledResult =
|
||||
Some(aTarget->IsRootContent() ? APZHandledResult::HandledByRoot
|
||||
: APZHandledResult::HandledByContent);
|
||||
Some(aTarget && aTarget->IsRootContent()
|
||||
? APZHandledResult{APZHandledPlace::HandledByRoot, aTarget}
|
||||
: APZHandledResult{APZHandledPlace::HandledByContent, aTarget});
|
||||
}
|
||||
|
||||
void APZEventResult::SetStatusAsConsumeDoDefaultWithTargetConfirmationFlags(
|
||||
@@ -84,9 +87,10 @@ void APZEventResult::SetStatusAsConsumeDoDefaultWithTargetConfirmationFlags(
|
||||
// mDispatchToContent, we need to change it to Nothing() so that
|
||||
// GeckoView can properly wait for results from the content on the
|
||||
// main-thread.
|
||||
mHandledResult = aFlags.mDispatchToContent
|
||||
mHandledResult =
|
||||
aFlags.mDispatchToContent
|
||||
? Nothing()
|
||||
: Some(APZHandledResult::HandledByRoot);
|
||||
: Some(APZHandledResult{APZHandledPlace::HandledByRoot, &aTarget});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,21 +256,94 @@ APZEventResult APZInputBridge::ReceiveInputEvent(WidgetInputEvent& aEvent) {
|
||||
return result;
|
||||
}
|
||||
|
||||
APZHandledResult::APZHandledResult(APZHandledPlace aPlace,
|
||||
const AsyncPanZoomController* aTarget)
|
||||
: mPlace(aPlace) {
|
||||
MOZ_ASSERT(aTarget);
|
||||
switch (aPlace) {
|
||||
case APZHandledPlace::Unhandled:
|
||||
break;
|
||||
case APZHandledPlace::HandledByContent:
|
||||
if (aTarget) {
|
||||
mScrollableDirections = aTarget->ScrollableDirections();
|
||||
mOverscrollDirections = aTarget->GetAllowedHandoffDirections();
|
||||
}
|
||||
break;
|
||||
case APZHandledPlace::HandledByRoot: {
|
||||
// The only way we can have mPlace == HandledByRoot but target is not the
|
||||
// root, is if scroll is handed off immediately from target to the root
|
||||
// because target and its ancestors (other than the root) do not have a
|
||||
// scroll range. Therefore, it's the scroll directions of the root which
|
||||
// are relevant.
|
||||
const AsyncPanZoomController* target = aTarget;
|
||||
while (target && !target->IsRootContent()) {
|
||||
target = target->GetParent();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(target && target->IsRootContent());
|
||||
if (target) {
|
||||
mScrollableDirections = target->ScrollableDirections();
|
||||
mOverscrollDirections = target->GetAllowedHandoffDirections();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Invalid APZHandledPlace");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& aOut, const SideBits& aSideBits) {
|
||||
if ((aSideBits & SideBits::eAll) == SideBits::eAll) {
|
||||
aOut << "all";
|
||||
} else {
|
||||
AutoTArray<nsCString, 4> strings;
|
||||
if (aSideBits & SideBits::eTop) {
|
||||
strings.AppendElement("top"_ns);
|
||||
}
|
||||
if (aSideBits & SideBits::eRight) {
|
||||
strings.AppendElement("right"_ns);
|
||||
}
|
||||
if (aSideBits & SideBits::eBottom) {
|
||||
strings.AppendElement("bottom"_ns);
|
||||
}
|
||||
if (aSideBits & SideBits::eLeft) {
|
||||
strings.AppendElement("left"_ns);
|
||||
}
|
||||
aOut << strings;
|
||||
}
|
||||
return aOut;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& aOut,
|
||||
const APZHandledResult& aHandledResult) {
|
||||
switch (aHandledResult) {
|
||||
case APZHandledResult::Unhandled:
|
||||
const ScrollDirections& aScrollDirections) {
|
||||
if (aScrollDirections.contains(EitherScrollDirection)) {
|
||||
aOut << "either";
|
||||
} else if (aScrollDirections.contains(HorizontalScrollDirection)) {
|
||||
aOut << "horizontal";
|
||||
} else if (aScrollDirections.contains(VerticalScrollDirection)) {
|
||||
aOut << "vertical";
|
||||
} else {
|
||||
aOut << "none";
|
||||
}
|
||||
return aOut;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& aOut,
|
||||
const APZHandledPlace& aHandledPlace) {
|
||||
switch (aHandledPlace) {
|
||||
case APZHandledPlace::Unhandled:
|
||||
aOut << "unhandled";
|
||||
break;
|
||||
case APZHandledResult::HandledByRoot: {
|
||||
case APZHandledPlace::HandledByRoot: {
|
||||
aOut << "handled-by-root";
|
||||
break;
|
||||
}
|
||||
case APZHandledResult::HandledByContent: {
|
||||
case APZHandledPlace::HandledByContent: {
|
||||
aOut << "handled-by-content";
|
||||
break;
|
||||
}
|
||||
case APZHandledResult::Invalid: {
|
||||
case APZHandledPlace::Invalid: {
|
||||
aOut << "INVALID";
|
||||
break;
|
||||
}
|
||||
@@ -274,5 +351,13 @@ std::ostream& operator<<(std::ostream& aOut,
|
||||
return aOut;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& aOut,
|
||||
const APZHandledResult& aHandledResult) {
|
||||
aOut << "handled: " << aHandledResult.mPlace << ", ";
|
||||
aOut << "scrollable: " << aHandledResult.mScrollableDirections << ", ";
|
||||
aOut << "overscroll: " << aHandledResult.mOverscrollDirections << std::endl;
|
||||
return aOut;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -874,21 +874,21 @@ static APZHandledResult GetHandledResultFor(
|
||||
const AsyncPanZoomController* aApzc,
|
||||
const InputBlockState& aCurrentInputBlock) {
|
||||
if (aCurrentInputBlock.ShouldDropEvents()) {
|
||||
return APZHandledResult::HandledByContent;
|
||||
return APZHandledResult{APZHandledPlace::HandledByContent, aApzc};
|
||||
}
|
||||
|
||||
if (aApzc && aApzc->IsRootContent()) {
|
||||
return aApzc->CanVerticalScrollWithDynamicToolbar()
|
||||
? APZHandledResult::HandledByRoot
|
||||
: APZHandledResult::Unhandled;
|
||||
? APZHandledResult{APZHandledPlace::HandledByRoot, aApzc}
|
||||
: APZHandledResult{APZHandledPlace::Unhandled, aApzc};
|
||||
}
|
||||
|
||||
// Return `HandledByRoot` if scroll positions in all relevant APZC are at the
|
||||
// bottom edge and if there are contents covered by the dynamic toolbar.
|
||||
return aApzc && aCurrentInputBlock.GetOverscrollHandoffChain()
|
||||
->ScrollingDownWillMoveDynamicToolbar(aApzc)
|
||||
? APZHandledResult::HandledByRoot
|
||||
: APZHandledResult::HandledByContent;
|
||||
? APZHandledResult{APZHandledPlace::HandledByRoot, aApzc}
|
||||
: APZHandledResult{APZHandledPlace::HandledByContent, aApzc};
|
||||
}
|
||||
|
||||
void InputQueue::ProcessQueue() {
|
||||
|
||||
@@ -37,8 +37,8 @@ class PinchGestureBlockState;
|
||||
class KeyboardBlockState;
|
||||
class AsyncDragMetrics;
|
||||
class QueuedInput;
|
||||
enum class APZHandledResult : uint8_t;
|
||||
struct APZEventResult;
|
||||
struct APZHandledResult;
|
||||
|
||||
/**
|
||||
* This class stores incoming input events, associated with "input blocks",
|
||||
|
||||
@@ -408,8 +408,8 @@ class APZCTesterBase : public ::testing::Test {
|
||||
};
|
||||
|
||||
template <class InputReceiver>
|
||||
void Tap(const RefPtr<InputReceiver>& aTarget, const ScreenIntPoint& aPoint,
|
||||
TimeDuration aTapLength,
|
||||
APZEventResult Tap(const RefPtr<InputReceiver>& aTarget,
|
||||
const ScreenIntPoint& aPoint, TimeDuration aTapLength,
|
||||
nsEventStatus (*aOutEventStatuses)[2] = nullptr,
|
||||
uint64_t* aOutInputBlockId = nullptr);
|
||||
|
||||
@@ -503,30 +503,32 @@ MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(APZCTesterBase::PanOptions)
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(APZCTesterBase::PinchOptions)
|
||||
|
||||
template <class InputReceiver>
|
||||
void APZCTesterBase::Tap(const RefPtr<InputReceiver>& aTarget,
|
||||
const ScreenIntPoint& aPoint, TimeDuration aTapLength,
|
||||
APZEventResult APZCTesterBase::Tap(const RefPtr<InputReceiver>& aTarget,
|
||||
const ScreenIntPoint& aPoint,
|
||||
TimeDuration aTapLength,
|
||||
nsEventStatus (*aOutEventStatuses)[2],
|
||||
uint64_t* aOutInputBlockId) {
|
||||
APZEventResult result = TouchDown(aTarget, aPoint, mcc->Time());
|
||||
APZEventResult touchDownResult = TouchDown(aTarget, aPoint, mcc->Time());
|
||||
if (aOutEventStatuses) {
|
||||
(*aOutEventStatuses)[0] = result.GetStatus();
|
||||
(*aOutEventStatuses)[0] = touchDownResult.GetStatus();
|
||||
}
|
||||
if (aOutInputBlockId) {
|
||||
*aOutInputBlockId = result.mInputBlockId;
|
||||
*aOutInputBlockId = touchDownResult.mInputBlockId;
|
||||
}
|
||||
mcc->AdvanceBy(aTapLength);
|
||||
|
||||
// If touch-action is enabled then simulate the allowed touch behaviour
|
||||
// notification that the main thread is supposed to deliver.
|
||||
if (StaticPrefs::layout_css_touch_action_enabled() &&
|
||||
result.GetStatus() != nsEventStatus_eConsumeNoDefault) {
|
||||
SetDefaultAllowedTouchBehavior(aTarget, result.mInputBlockId);
|
||||
touchDownResult.GetStatus() != nsEventStatus_eConsumeNoDefault) {
|
||||
SetDefaultAllowedTouchBehavior(aTarget, touchDownResult.mInputBlockId);
|
||||
}
|
||||
|
||||
result = TouchUp(aTarget, aPoint, mcc->Time());
|
||||
APZEventResult touchUpResult = TouchUp(aTarget, aPoint, mcc->Time());
|
||||
if (aOutEventStatuses) {
|
||||
(*aOutEventStatuses)[1] = result.GetStatus();
|
||||
(*aOutEventStatuses)[1] = touchUpResult.GetStatus();
|
||||
}
|
||||
return touchDownResult;
|
||||
}
|
||||
|
||||
template <class InputReceiver>
|
||||
|
||||
@@ -311,101 +311,3 @@ TEST_F(APZEventRegionsTester, Bug1117712) {
|
||||
targets.AppendElement(apzc2->GetGuid());
|
||||
manager->SetTargetAPZC(inputBlockId, targets);
|
||||
}
|
||||
|
||||
// Test that APZEventResult::GetHandledResult() is correctly
|
||||
// populated.
|
||||
TEST_F(APZEventRegionsTesterLayersOnly, HandledByRootApzcFlag) {
|
||||
// Create simple layer tree containing a dispatch-to-content region
|
||||
// that covers part but not all of its area.
|
||||
const char* layerTreeSyntax = "c";
|
||||
nsIntRegion layerVisibleRegions[] = {
|
||||
nsIntRegion(IntRect(0, 0, 100, 100)),
|
||||
};
|
||||
root = CreateLayerTree(layerTreeSyntax, layerVisibleRegions, nullptr, lm,
|
||||
layers);
|
||||
SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
|
||||
CSSRect(0, 0, 100, 200));
|
||||
ModifyFrameMetrics(root, [](ScrollMetadata& sm, FrameMetrics& metrics) {
|
||||
metrics.SetIsRootContent(true);
|
||||
});
|
||||
// away from the scrolling container layer.
|
||||
EventRegions regions(nsIntRegion(IntRect(0, 0, 100, 100)));
|
||||
// bottom half is dispatch-to-content
|
||||
regions.mDispatchToContentHitRegion = nsIntRegion(IntRect(0, 50, 100, 50));
|
||||
root->SetEventRegions(regions);
|
||||
registration =
|
||||
MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0}, root, mcc);
|
||||
UpdateHitTestingTree();
|
||||
|
||||
// Tap the top half and check that we report that the event was
|
||||
// handled by the root APZC.
|
||||
APZEventResult result =
|
||||
TouchDown(manager, ScreenIntPoint(50, 25), mcc->Time());
|
||||
TouchUp(manager, ScreenIntPoint(50, 25), mcc->Time());
|
||||
EXPECT_EQ(result.GetHandledResult(), Some(APZHandledResult::HandledByRoot));
|
||||
|
||||
// Tap the bottom half and check that we report that we're not
|
||||
// sure whether the event was handled by the root APZC.
|
||||
result = TouchDown(manager, ScreenIntPoint(50, 75), mcc->Time());
|
||||
TouchUp(manager, ScreenIntPoint(50, 75), mcc->Time());
|
||||
EXPECT_EQ(result.GetHandledResult(), Nothing());
|
||||
|
||||
// Register an input block callback that will tell us the
|
||||
// delayed answer.
|
||||
APZHandledResult delayedAnswer = APZHandledResult::Invalid;
|
||||
manager->AddInputBlockCallback(result.mInputBlockId,
|
||||
[&](uint64_t id, APZHandledResult answer) {
|
||||
EXPECT_EQ(id, result.mInputBlockId);
|
||||
delayedAnswer = answer;
|
||||
});
|
||||
|
||||
// Send APZ the relevant notifications to allow it to process the
|
||||
// input block.
|
||||
manager->SetAllowedTouchBehavior(result.mInputBlockId,
|
||||
{AllowedTouchBehavior::VERTICAL_PAN});
|
||||
manager->SetTargetAPZC(result.mInputBlockId, {result.mTargetGuid});
|
||||
manager->ContentReceivedInputBlock(result.mInputBlockId,
|
||||
/*preventDefault=*/false);
|
||||
|
||||
// Check that we received the delayed answer and it is what we expect.
|
||||
EXPECT_EQ(delayedAnswer, APZHandledResult::HandledByRoot);
|
||||
|
||||
// Now repeat the tap on the bottom half, but simulate a prevent-default.
|
||||
// This time, we expect a delayed answer of `HandledByContent`.
|
||||
result = TouchDown(manager, ScreenIntPoint(50, 75), mcc->Time());
|
||||
TouchUp(manager, ScreenIntPoint(50, 75), mcc->Time());
|
||||
EXPECT_EQ(result.GetHandledResult(), Nothing());
|
||||
manager->AddInputBlockCallback(result.mInputBlockId,
|
||||
[&](uint64_t id, APZHandledResult answer) {
|
||||
EXPECT_EQ(id, result.mInputBlockId);
|
||||
delayedAnswer = answer;
|
||||
});
|
||||
manager->SetAllowedTouchBehavior(result.mInputBlockId,
|
||||
{AllowedTouchBehavior::VERTICAL_PAN});
|
||||
manager->SetTargetAPZC(result.mInputBlockId, {result.mTargetGuid});
|
||||
manager->ContentReceivedInputBlock(result.mInputBlockId,
|
||||
/*preventDefault=*/true);
|
||||
EXPECT_EQ(delayedAnswer, APZHandledResult::HandledByContent);
|
||||
|
||||
// Shrink the scrollable area, now it's no longer scrollable.
|
||||
ModifyFrameMetrics(root, [](ScrollMetadata& sm, FrameMetrics& metrics) {
|
||||
metrics.SetScrollableRect(CSSRect(0, 0, 100, 100));
|
||||
});
|
||||
UpdateHitTestingTree();
|
||||
// Now repeat the tap on the bottom half with an event handler.
|
||||
// This time, we expect a delayed answer of `Unhandled`.
|
||||
result = TouchDown(manager, ScreenIntPoint(50, 75), mcc->Time());
|
||||
TouchUp(manager, ScreenIntPoint(50, 75), mcc->Time());
|
||||
EXPECT_EQ(result.GetHandledResult(), Nothing());
|
||||
manager->AddInputBlockCallback(result.mInputBlockId,
|
||||
[&](uint64_t id, APZHandledResult answer) {
|
||||
EXPECT_EQ(id, result.mInputBlockId);
|
||||
delayedAnswer = answer;
|
||||
});
|
||||
manager->SetAllowedTouchBehavior(result.mInputBlockId,
|
||||
{AllowedTouchBehavior::VERTICAL_PAN});
|
||||
manager->SetTargetAPZC(result.mInputBlockId, {result.mTargetGuid});
|
||||
manager->ContentReceivedInputBlock(result.mInputBlockId,
|
||||
/*preventDefault=*/false);
|
||||
EXPECT_EQ(delayedAnswer, APZHandledResult::Unhandled);
|
||||
}
|
||||
|
||||
435
gfx/layers/apz/test/gtest/TestEventResult.cpp
Normal file
435
gfx/layers/apz/test/gtest/TestEventResult.cpp
Normal file
@@ -0,0 +1,435 @@
|
||||
/* -*- 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 "APZCTreeManagerTester.h"
|
||||
#include "APZTestCommon.h"
|
||||
#include "InputUtils.h"
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include <tuple>
|
||||
|
||||
class APZEventResultTester : public APZCTreeManagerTester {
|
||||
protected:
|
||||
UniquePtr<ScopedLayerTreeRegistration> registration;
|
||||
|
||||
void UpdateOverscrollBehavior(OverscrollBehavior aX, OverscrollBehavior aY) {
|
||||
ModifyFrameMetrics(root, [aX, aY](ScrollMetadata& sm, FrameMetrics& _) {
|
||||
OverscrollBehaviorInfo overscroll;
|
||||
overscroll.mBehaviorX = aX;
|
||||
overscroll.mBehaviorY = aY;
|
||||
sm.SetOverscrollBehavior(overscroll);
|
||||
});
|
||||
UpdateHitTestingTree();
|
||||
}
|
||||
|
||||
void SetScrollOffsetOnMainThread(const CSSPoint& aPoint) {
|
||||
RefPtr<TestAsyncPanZoomController> apzc = ApzcOf(root);
|
||||
|
||||
ScrollMetadata metadata = apzc->GetScrollMetadata();
|
||||
metadata.GetMetrics().SetLayoutScrollOffset(aPoint);
|
||||
nsTArray<ScrollPositionUpdate> scrollUpdates;
|
||||
scrollUpdates.AppendElement(ScrollPositionUpdate::NewScroll(
|
||||
ScrollOrigin::Other, CSSPoint::ToAppUnits(aPoint)));
|
||||
metadata.SetScrollUpdates(scrollUpdates);
|
||||
metadata.GetMetrics().SetScrollGeneration(
|
||||
scrollUpdates.LastElement().GetGeneration());
|
||||
apzc->NotifyLayersUpdated(metadata, /*aIsFirstPaint=*/false,
|
||||
/*aThisLayerTreeUpdated=*/true);
|
||||
}
|
||||
|
||||
void CreateScrollableRootLayer() {
|
||||
const char* layerTreeSyntax = "c";
|
||||
nsIntRegion layerVisibleRegions[] = {
|
||||
nsIntRegion(IntRect(0, 0, 100, 100)),
|
||||
};
|
||||
root = CreateLayerTree(layerTreeSyntax, layerVisibleRegions, nullptr, lm,
|
||||
layers);
|
||||
SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
|
||||
CSSRect(0, 0, 200, 200));
|
||||
ModifyFrameMetrics(root, [](ScrollMetadata& sm, FrameMetrics& metrics) {
|
||||
metrics.SetIsRootContent(true);
|
||||
});
|
||||
registration = MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0},
|
||||
root, mcc);
|
||||
UpdateHitTestingTree();
|
||||
}
|
||||
|
||||
enum class PreventDefaultFlag { No, Yes };
|
||||
std::tuple<APZEventResult, APZHandledResult> TapDispatchToContent(
|
||||
const ScreenIntPoint& aPoint, PreventDefaultFlag aPreventDefaultFlag) {
|
||||
APZEventResult result =
|
||||
Tap(manager, aPoint, TimeDuration::FromMilliseconds(100));
|
||||
|
||||
APZHandledResult delayedAnswer{APZHandledPlace::Invalid, SideBits::eNone,
|
||||
ScrollDirections()};
|
||||
manager->AddInputBlockCallback(
|
||||
result.mInputBlockId, [&](uint64_t id, const APZHandledResult& answer) {
|
||||
EXPECT_EQ(id, result.mInputBlockId);
|
||||
delayedAnswer = answer;
|
||||
});
|
||||
manager->SetAllowedTouchBehavior(result.mInputBlockId,
|
||||
{AllowedTouchBehavior::VERTICAL_PAN});
|
||||
manager->SetTargetAPZC(result.mInputBlockId, {result.mTargetGuid});
|
||||
manager->ContentReceivedInputBlock(
|
||||
result.mInputBlockId, aPreventDefaultFlag == PreventDefaultFlag::Yes);
|
||||
return {result, delayedAnswer};
|
||||
}
|
||||
|
||||
void OverscrollDirectionsWithEventHandlerTest(
|
||||
PreventDefaultFlag aPreventDefaultFlag) {
|
||||
EventRegions regions(nsIntRegion(IntRect(0, 0, 100, 100)));
|
||||
regions.mDispatchToContentHitRegion = nsIntRegion(IntRect(0, 0, 100, 100));
|
||||
root->SetEventRegions(regions);
|
||||
UpdateHitTestingTree();
|
||||
|
||||
APZHandledPlace expectedPlace =
|
||||
aPreventDefaultFlag == PreventDefaultFlag::No
|
||||
? APZHandledPlace::HandledByRoot
|
||||
: APZHandledPlace::HandledByContent;
|
||||
{
|
||||
auto [result, delayedHandledResult] =
|
||||
TapDispatchToContent(ScreenIntPoint(50, 50), aPreventDefaultFlag);
|
||||
EXPECT_EQ(result.GetHandledResult(), Nothing());
|
||||
EXPECT_EQ(
|
||||
delayedHandledResult,
|
||||
(APZHandledResult{expectedPlace, SideBits::eBottom | SideBits::eRight,
|
||||
EitherScrollDirection}));
|
||||
}
|
||||
|
||||
// overscroll-behavior: contain, contain.
|
||||
UpdateOverscrollBehavior(OverscrollBehavior::Contain,
|
||||
OverscrollBehavior::Contain);
|
||||
{
|
||||
auto [result, delayedHandledResult] =
|
||||
TapDispatchToContent(ScreenIntPoint(50, 50), aPreventDefaultFlag);
|
||||
EXPECT_EQ(result.GetHandledResult(), Nothing());
|
||||
EXPECT_EQ(
|
||||
delayedHandledResult,
|
||||
(APZHandledResult{expectedPlace, SideBits::eBottom | SideBits::eRight,
|
||||
ScrollDirections()}));
|
||||
}
|
||||
|
||||
// overscroll-behavior: none, none.
|
||||
UpdateOverscrollBehavior(OverscrollBehavior::None,
|
||||
OverscrollBehavior::None);
|
||||
{
|
||||
auto [result, delayedHandledResult] =
|
||||
TapDispatchToContent(ScreenIntPoint(50, 50), aPreventDefaultFlag);
|
||||
EXPECT_EQ(result.GetHandledResult(), Nothing());
|
||||
EXPECT_EQ(
|
||||
delayedHandledResult,
|
||||
(APZHandledResult{expectedPlace, SideBits::eBottom | SideBits::eRight,
|
||||
ScrollDirections()}));
|
||||
}
|
||||
|
||||
// overscroll-behavior: auto, none.
|
||||
UpdateOverscrollBehavior(OverscrollBehavior::Auto,
|
||||
OverscrollBehavior::None);
|
||||
{
|
||||
auto [result, delayedHandledResult] =
|
||||
TapDispatchToContent(ScreenIntPoint(50, 50), aPreventDefaultFlag);
|
||||
EXPECT_EQ(result.GetHandledResult(), Nothing());
|
||||
EXPECT_EQ(
|
||||
delayedHandledResult,
|
||||
(APZHandledResult{expectedPlace, SideBits::eBottom | SideBits::eRight,
|
||||
HorizontalScrollDirection}));
|
||||
}
|
||||
|
||||
// overscroll-behavior: none, auto.
|
||||
UpdateOverscrollBehavior(OverscrollBehavior::None,
|
||||
OverscrollBehavior::Auto);
|
||||
{
|
||||
auto [result, delayedHandledResult] =
|
||||
TapDispatchToContent(ScreenIntPoint(50, 50), aPreventDefaultFlag);
|
||||
EXPECT_EQ(result.GetHandledResult(), Nothing());
|
||||
EXPECT_EQ(
|
||||
delayedHandledResult,
|
||||
(APZHandledResult{expectedPlace, SideBits::eBottom | SideBits::eRight,
|
||||
VerticalScrollDirection}));
|
||||
}
|
||||
}
|
||||
|
||||
void ScrollableDirectionsWithEventHandlerTest(
|
||||
PreventDefaultFlag aPreventDefaultFlag) {
|
||||
EventRegions regions(nsIntRegion(IntRect(0, 0, 100, 100)));
|
||||
regions.mDispatchToContentHitRegion = nsIntRegion(IntRect(0, 0, 100, 100));
|
||||
root->SetEventRegions(regions);
|
||||
UpdateHitTestingTree();
|
||||
|
||||
APZHandledPlace expectedPlace =
|
||||
aPreventDefaultFlag == PreventDefaultFlag::No
|
||||
? APZHandledPlace::HandledByRoot
|
||||
: APZHandledPlace::HandledByContent;
|
||||
{
|
||||
auto [result, delayedHandledResult] =
|
||||
TapDispatchToContent(ScreenIntPoint(50, 50), aPreventDefaultFlag);
|
||||
EXPECT_EQ(result.GetHandledResult(), Nothing());
|
||||
EXPECT_EQ(
|
||||
delayedHandledResult,
|
||||
(APZHandledResult{expectedPlace, SideBits::eBottom | SideBits::eRight,
|
||||
EitherScrollDirection}));
|
||||
}
|
||||
|
||||
// scroll down a bit.
|
||||
SetScrollOffsetOnMainThread(CSSPoint(0, 10));
|
||||
{
|
||||
auto [result, delayedHandledResult] =
|
||||
TapDispatchToContent(ScreenIntPoint(50, 50), aPreventDefaultFlag);
|
||||
EXPECT_EQ(result.GetHandledResult(), Nothing());
|
||||
EXPECT_EQ(delayedHandledResult,
|
||||
(APZHandledResult{
|
||||
expectedPlace,
|
||||
SideBits::eTop | SideBits::eBottom | SideBits::eRight,
|
||||
EitherScrollDirection}));
|
||||
}
|
||||
|
||||
// scroll to the bottom edge
|
||||
SetScrollOffsetOnMainThread(CSSPoint(0, 100));
|
||||
{
|
||||
auto [result, delayedHandledResult] =
|
||||
TapDispatchToContent(ScreenIntPoint(50, 50), aPreventDefaultFlag);
|
||||
EXPECT_EQ(result.GetHandledResult(), Nothing());
|
||||
EXPECT_EQ(
|
||||
delayedHandledResult,
|
||||
(APZHandledResult{expectedPlace, SideBits::eRight | SideBits::eTop,
|
||||
EitherScrollDirection}));
|
||||
}
|
||||
|
||||
// scroll to right a bit.
|
||||
SetScrollOffsetOnMainThread(CSSPoint(10, 100));
|
||||
{
|
||||
auto [result, delayedHandledResult] =
|
||||
TapDispatchToContent(ScreenIntPoint(50, 50), aPreventDefaultFlag);
|
||||
EXPECT_EQ(result.GetHandledResult(), Nothing());
|
||||
EXPECT_EQ(
|
||||
delayedHandledResult,
|
||||
(APZHandledResult{expectedPlace,
|
||||
SideBits::eLeft | SideBits::eRight | SideBits::eTop,
|
||||
EitherScrollDirection}));
|
||||
}
|
||||
|
||||
// scroll to the right edge.
|
||||
SetScrollOffsetOnMainThread(CSSPoint(100, 100));
|
||||
{
|
||||
auto [result, delayedHandledResult] =
|
||||
TapDispatchToContent(ScreenIntPoint(50, 50), aPreventDefaultFlag);
|
||||
EXPECT_EQ(result.GetHandledResult(), Nothing());
|
||||
EXPECT_EQ(
|
||||
delayedHandledResult,
|
||||
(APZHandledResult{expectedPlace, SideBits::eTop | SideBits::eLeft,
|
||||
EitherScrollDirection}));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(APZEventResultTester, OverscrollDirections) {
|
||||
CreateScrollableRootLayer();
|
||||
|
||||
TimeDuration tapDuration = TimeDuration::FromMilliseconds(100);
|
||||
|
||||
// The default value of overscroll-behavior is auto.
|
||||
APZEventResult result = Tap(manager, ScreenIntPoint(50, 50), tapDuration);
|
||||
EXPECT_EQ(result.GetHandledResult()->mOverscrollDirections,
|
||||
EitherScrollDirection);
|
||||
|
||||
// overscroll-behavior: contain, contain.
|
||||
UpdateOverscrollBehavior(OverscrollBehavior::Contain,
|
||||
OverscrollBehavior::Contain);
|
||||
result = Tap(manager, ScreenIntPoint(50, 50), tapDuration);
|
||||
EXPECT_EQ(result.GetHandledResult()->mOverscrollDirections,
|
||||
ScrollDirections());
|
||||
|
||||
// overscroll-behavior: none, none.
|
||||
UpdateOverscrollBehavior(OverscrollBehavior::None, OverscrollBehavior::None);
|
||||
result = Tap(manager, ScreenIntPoint(50, 50), tapDuration);
|
||||
EXPECT_EQ(result.GetHandledResult()->mOverscrollDirections,
|
||||
ScrollDirections());
|
||||
|
||||
// overscroll-behavior: auto, none.
|
||||
UpdateOverscrollBehavior(OverscrollBehavior::Auto, OverscrollBehavior::None);
|
||||
result = Tap(manager, ScreenIntPoint(50, 50), tapDuration);
|
||||
EXPECT_EQ(result.GetHandledResult()->mOverscrollDirections,
|
||||
HorizontalScrollDirection);
|
||||
|
||||
// overscroll-behavior: none, auto.
|
||||
UpdateOverscrollBehavior(OverscrollBehavior::None, OverscrollBehavior::Auto);
|
||||
result = Tap(manager, ScreenIntPoint(50, 50), tapDuration);
|
||||
EXPECT_EQ(result.GetHandledResult()->mOverscrollDirections,
|
||||
VerticalScrollDirection);
|
||||
}
|
||||
|
||||
TEST_F(APZEventResultTester, ScrollableDirections) {
|
||||
CreateScrollableRootLayer();
|
||||
|
||||
TimeDuration tapDuration = TimeDuration::FromMilliseconds(100);
|
||||
|
||||
APZEventResult result = Tap(manager, ScreenIntPoint(50, 50), tapDuration);
|
||||
// scrollable to down/right.
|
||||
EXPECT_EQ(result.GetHandledResult()->mScrollableDirections,
|
||||
SideBits::eBottom | SideBits::eRight);
|
||||
|
||||
// scroll down a bit.
|
||||
SetScrollOffsetOnMainThread(CSSPoint(0, 10));
|
||||
result = Tap(manager, ScreenIntPoint(50, 50), tapDuration);
|
||||
// also scrollable toward top.
|
||||
EXPECT_EQ(result.GetHandledResult()->mScrollableDirections,
|
||||
SideBits::eTop | SideBits::eBottom | SideBits::eRight);
|
||||
|
||||
// scroll to the bottom edge
|
||||
SetScrollOffsetOnMainThread(CSSPoint(0, 100));
|
||||
result = Tap(manager, ScreenIntPoint(50, 50), tapDuration);
|
||||
EXPECT_EQ(result.GetHandledResult()->mScrollableDirections,
|
||||
SideBits::eRight | SideBits::eTop);
|
||||
|
||||
// scroll to right a bit.
|
||||
SetScrollOffsetOnMainThread(CSSPoint(10, 100));
|
||||
result = Tap(manager, ScreenIntPoint(50, 50), tapDuration);
|
||||
EXPECT_EQ(result.GetHandledResult()->mScrollableDirections,
|
||||
SideBits::eLeft | SideBits::eRight | SideBits::eTop);
|
||||
|
||||
// scroll to the right edge.
|
||||
SetScrollOffsetOnMainThread(CSSPoint(100, 100));
|
||||
result = Tap(manager, ScreenIntPoint(50, 50), tapDuration);
|
||||
EXPECT_EQ(result.GetHandledResult()->mScrollableDirections,
|
||||
SideBits::eLeft | SideBits::eTop);
|
||||
}
|
||||
|
||||
class APZEventResultTesterLayersOnly : public APZEventResultTester {
|
||||
public:
|
||||
APZEventResultTesterLayersOnly() { mLayersOnly = true; }
|
||||
};
|
||||
|
||||
TEST_F(APZEventResultTesterLayersOnly, OverscrollDirectionsWithEventHandler) {
|
||||
CreateScrollableRootLayer();
|
||||
|
||||
OverscrollDirectionsWithEventHandlerTest(PreventDefaultFlag::No);
|
||||
}
|
||||
|
||||
TEST_F(APZEventResultTesterLayersOnly,
|
||||
OverscrollDirectionsWithPreventDefaultEventHandler) {
|
||||
CreateScrollableRootLayer();
|
||||
|
||||
OverscrollDirectionsWithEventHandlerTest(PreventDefaultFlag::Yes);
|
||||
}
|
||||
|
||||
TEST_F(APZEventResultTesterLayersOnly, ScrollableDirectionsWithEventHandler) {
|
||||
CreateScrollableRootLayer();
|
||||
|
||||
ScrollableDirectionsWithEventHandlerTest(PreventDefaultFlag::No);
|
||||
}
|
||||
|
||||
TEST_F(APZEventResultTesterLayersOnly,
|
||||
ScrollableDirectionsWithPreventDefaultEventHandler) {
|
||||
CreateScrollableRootLayer();
|
||||
|
||||
ScrollableDirectionsWithEventHandlerTest(PreventDefaultFlag::Yes);
|
||||
}
|
||||
|
||||
// Test that APZEventResult::GetHandledResult() is correctly
|
||||
// populated.
|
||||
TEST_F(APZEventResultTesterLayersOnly, HandledByRootApzcFlag) {
|
||||
// Create simple layer tree containing a dispatch-to-content region
|
||||
// that covers part but not all of its area.
|
||||
const char* layerTreeSyntax = "c";
|
||||
nsIntRegion layerVisibleRegions[] = {
|
||||
nsIntRegion(IntRect(0, 0, 100, 100)),
|
||||
};
|
||||
root = CreateLayerTree(layerTreeSyntax, layerVisibleRegions, nullptr, lm,
|
||||
layers);
|
||||
SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
|
||||
CSSRect(0, 0, 100, 200));
|
||||
ModifyFrameMetrics(root, [](ScrollMetadata& sm, FrameMetrics& metrics) {
|
||||
metrics.SetIsRootContent(true);
|
||||
});
|
||||
// away from the scrolling container layer.
|
||||
EventRegions regions(nsIntRegion(IntRect(0, 0, 100, 100)));
|
||||
// bottom half is dispatch-to-content
|
||||
regions.mDispatchToContentHitRegion = nsIntRegion(IntRect(0, 50, 100, 50));
|
||||
root->SetEventRegions(regions);
|
||||
registration =
|
||||
MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0}, root, mcc);
|
||||
UpdateHitTestingTree();
|
||||
|
||||
// Tap the top half and check that we report that the event was
|
||||
// handled by the root APZC.
|
||||
APZEventResult result =
|
||||
TouchDown(manager, ScreenIntPoint(50, 25), mcc->Time());
|
||||
TouchUp(manager, ScreenIntPoint(50, 25), mcc->Time());
|
||||
EXPECT_EQ(result.GetHandledResult(),
|
||||
Some(APZHandledResult{APZHandledPlace::HandledByRoot,
|
||||
SideBits::eBottom, EitherScrollDirection}));
|
||||
|
||||
// Tap the bottom half and check that we report that we're not
|
||||
// sure whether the event was handled by the root APZC.
|
||||
result = TouchDown(manager, ScreenIntPoint(50, 75), mcc->Time());
|
||||
TouchUp(manager, ScreenIntPoint(50, 75), mcc->Time());
|
||||
EXPECT_EQ(result.GetHandledResult(), Nothing());
|
||||
|
||||
// Register an input block callback that will tell us the
|
||||
// delayed answer.
|
||||
APZHandledResult delayedAnswer{APZHandledPlace::Invalid, SideBits::eNone,
|
||||
ScrollDirections()};
|
||||
manager->AddInputBlockCallback(
|
||||
result.mInputBlockId, [&](uint64_t id, const APZHandledResult& answer) {
|
||||
EXPECT_EQ(id, result.mInputBlockId);
|
||||
delayedAnswer = answer;
|
||||
});
|
||||
|
||||
// Send APZ the relevant notifications to allow it to process the
|
||||
// input block.
|
||||
manager->SetAllowedTouchBehavior(result.mInputBlockId,
|
||||
{AllowedTouchBehavior::VERTICAL_PAN});
|
||||
manager->SetTargetAPZC(result.mInputBlockId, {result.mTargetGuid});
|
||||
manager->ContentReceivedInputBlock(result.mInputBlockId,
|
||||
/*aPreventDefault=*/false);
|
||||
|
||||
// Check that we received the delayed answer and it is what we expect.
|
||||
EXPECT_EQ(delayedAnswer,
|
||||
(APZHandledResult{APZHandledPlace::HandledByRoot, SideBits::eBottom,
|
||||
EitherScrollDirection}));
|
||||
|
||||
// Now repeat the tap on the bottom half, but simulate a prevent-default.
|
||||
// This time, we expect a delayed answer of `HandledByContent`.
|
||||
result = TouchDown(manager, ScreenIntPoint(50, 75), mcc->Time());
|
||||
TouchUp(manager, ScreenIntPoint(50, 75), mcc->Time());
|
||||
EXPECT_EQ(result.GetHandledResult(), Nothing());
|
||||
manager->AddInputBlockCallback(
|
||||
result.mInputBlockId, [&](uint64_t id, const APZHandledResult& answer) {
|
||||
EXPECT_EQ(id, result.mInputBlockId);
|
||||
delayedAnswer = answer;
|
||||
});
|
||||
manager->SetAllowedTouchBehavior(result.mInputBlockId,
|
||||
{AllowedTouchBehavior::VERTICAL_PAN});
|
||||
manager->SetTargetAPZC(result.mInputBlockId, {result.mTargetGuid});
|
||||
manager->ContentReceivedInputBlock(result.mInputBlockId,
|
||||
/*aPreventDefault=*/true);
|
||||
EXPECT_EQ(delayedAnswer,
|
||||
(APZHandledResult{APZHandledPlace::HandledByContent,
|
||||
SideBits::eBottom, EitherScrollDirection}));
|
||||
|
||||
// Shrink the scrollable area, now it's no longer scrollable.
|
||||
ModifyFrameMetrics(root, [](ScrollMetadata& sm, FrameMetrics& metrics) {
|
||||
metrics.SetScrollableRect(CSSRect(0, 0, 100, 100));
|
||||
});
|
||||
UpdateHitTestingTree();
|
||||
// Now repeat the tap on the bottom half with an event handler.
|
||||
// This time, we expect a delayed answer of `Unhandled`.
|
||||
result = TouchDown(manager, ScreenIntPoint(50, 75), mcc->Time());
|
||||
TouchUp(manager, ScreenIntPoint(50, 75), mcc->Time());
|
||||
EXPECT_EQ(result.GetHandledResult(), Nothing());
|
||||
manager->AddInputBlockCallback(
|
||||
result.mInputBlockId, [&](uint64_t id, const APZHandledResult& answer) {
|
||||
EXPECT_EQ(id, result.mInputBlockId);
|
||||
delayedAnswer = answer;
|
||||
});
|
||||
manager->SetAllowedTouchBehavior(result.mInputBlockId,
|
||||
{AllowedTouchBehavior::VERTICAL_PAN});
|
||||
manager->SetTargetAPZC(result.mInputBlockId, {result.mTargetGuid});
|
||||
manager->ContentReceivedInputBlock(result.mInputBlockId,
|
||||
/*aPreventDefault=*/false);
|
||||
EXPECT_EQ(delayedAnswer,
|
||||
(APZHandledResult{APZHandledPlace::Unhandled, SideBits::eNone,
|
||||
ScrollDirections()}));
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
UNIFIED_SOURCES += [
|
||||
"TestBasic.cpp",
|
||||
"TestEventRegions.cpp",
|
||||
"TestEventResult.cpp",
|
||||
"TestFlingAcceleration.cpp",
|
||||
"TestGestureDetector.cpp",
|
||||
"TestHitTesting.cpp",
|
||||
|
||||
@@ -577,11 +577,48 @@ struct ParamTraits<nsEventStatus>
|
||||
nsEventStatus_eSentinel> {};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::layers::APZHandledResult>
|
||||
struct ParamTraits<mozilla::layers::APZHandledPlace>
|
||||
: public ContiguousEnumSerializer<
|
||||
mozilla::layers::APZHandledResult,
|
||||
mozilla::layers::APZHandledResult::Unhandled,
|
||||
mozilla::layers::APZHandledResult::Last> {};
|
||||
mozilla::layers::APZHandledPlace,
|
||||
mozilla::layers::APZHandledPlace::Unhandled,
|
||||
mozilla::layers::APZHandledPlace::Last> {};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::layers::ScrollDirections> {
|
||||
typedef mozilla::layers::ScrollDirections paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
WriteParam(aMsg, aParam.serialize());
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
uint8_t value;
|
||||
if (!ReadParam(aMsg, aIter, &value)) {
|
||||
return false;
|
||||
}
|
||||
aResult->deserialize(value);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::layers::APZHandledResult> {
|
||||
typedef mozilla::layers::APZHandledResult paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
WriteParam(aMsg, aParam.mPlace);
|
||||
WriteParam(aMsg, aParam.mScrollableDirections);
|
||||
WriteParam(aMsg, aParam.mOverscrollDirections);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
return (ReadParam(aMsg, aIter, &aResult->mPlace) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mScrollableDirections) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mOverscrollDirections));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::layers::APZEventResult> {
|
||||
|
||||
@@ -405,8 +405,7 @@ class NPZCSupport final
|
||||
case nsEventStatus_eIgnore:
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
case nsEventStatus_eConsumeDoDefault:
|
||||
return (result.GetHandledResult() ==
|
||||
Some(APZHandledResult::HandledByRoot))
|
||||
return result.GetHandledResult()->IsHandledByRoot()
|
||||
? INPUT_RESULT_HANDLED
|
||||
: INPUT_RESULT_HANDLED_CONTENT;
|
||||
default:
|
||||
@@ -459,14 +458,14 @@ class NPZCSupport final
|
||||
}
|
||||
|
||||
static int32_t ConvertAPZHandledResult(APZHandledResult aHandledResult) {
|
||||
switch (aHandledResult) {
|
||||
case APZHandledResult::Unhandled:
|
||||
switch (aHandledResult.mPlace) {
|
||||
case APZHandledPlace::Unhandled:
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
case APZHandledResult::HandledByRoot:
|
||||
case APZHandledPlace::HandledByRoot:
|
||||
return INPUT_RESULT_HANDLED;
|
||||
case APZHandledResult::HandledByContent:
|
||||
case APZHandledPlace::HandledByContent:
|
||||
return INPUT_RESULT_HANDLED_CONTENT;
|
||||
case APZHandledResult::Invalid:
|
||||
case APZHandledPlace::Invalid:
|
||||
MOZ_ASSERT_UNREACHABLE("The handled result should NOT be Invalid");
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
@@ -546,8 +545,7 @@ class NPZCSupport final
|
||||
case nsEventStatus_eIgnore:
|
||||
return INPUT_RESULT_UNHANDLED;
|
||||
case nsEventStatus_eConsumeDoDefault:
|
||||
return (result.GetHandledResult() ==
|
||||
Some(APZHandledResult::HandledByRoot))
|
||||
return result.GetHandledResult()->IsHandledByRoot()
|
||||
? INPUT_RESULT_HANDLED
|
||||
: INPUT_RESULT_HANDLED_CONTENT;
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user