Bug 951793 - Store the overscroll behavior in ScrollMetadata and propagate it to APZ. r=mstange
MozReview-Commit-ID: J7Vkd941QxK
--- a/gfx/layers/FrameMetrics.cpp
+++ b/gfx/layers/FrameMetrics.cpp
@@ -1,24 +1,50 @@
/* -*- 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 "FrameMetrics.h"
#include "gfxPrefs.h"
+#include "nsStyleConsts.h"
namespace mozilla {
namespace layers {
const FrameMetrics::ViewID FrameMetrics::NULL_SCROLL_ID = 0;
void
ScrollMetadata::SetUsesContainerScrolling(bool aValue) {
MOZ_ASSERT_IF(aValue, gfxPrefs::LayoutUseContainersForRootFrames());
mUsesContainerScrolling = aValue;
}
+static OverscrollBehavior
+ToOverscrollBehavior(StyleOverscrollBehavior aBehavior)
+{
+ switch (aBehavior) {
+ case StyleOverscrollBehavior::Auto:
+ return OverscrollBehavior::Auto;
+ case StyleOverscrollBehavior::Contain:
+ return OverscrollBehavior::Contain;
+ case StyleOverscrollBehavior::None:
+ return OverscrollBehavior::None;
+ }
+ MOZ_ASSERT_UNREACHABLE("Invalid overscroll behavior");
+ return OverscrollBehavior::Auto;
+}
+
+OverscrollBehaviorInfo
+OverscrollBehaviorInfo::FromStyleConstants(StyleOverscrollBehavior aBehaviorX,
+ StyleOverscrollBehavior aBehaviorY)
+{
+ OverscrollBehaviorInfo result;
+ result.mBehaviorX = ToOverscrollBehavior(aBehaviorX);
+ result.mBehaviorY = ToOverscrollBehavior(aBehaviorY);
+ return result;
+}
+
StaticAutoPtr<const ScrollMetadata> ScrollMetadata::sNullMetadata;
}
}
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -716,16 +716,42 @@ struct ScrollSnapInfo {
// shipping the raw nsStyleCoord::CalcValue over IPC).
nsPoint mScrollSnapDestination;
// The scroll-snap-coordinates of any descendant frames of the scroll frame,
// relative to the origin of the scrolled frame.
nsTArray<nsPoint> mScrollSnapCoordinates;
};
+MOZ_DEFINE_ENUM_CLASS_WITH_BASE(
+ OverscrollBehavior, uint8_t, (
+ Auto,
+ Contain,
+ None
+));
+
+struct OverscrollBehaviorInfo {
+ OverscrollBehaviorInfo()
+ : mBehaviorX(OverscrollBehavior::Auto)
+ , mBehaviorY(OverscrollBehavior::Auto)
+ {}
+
+ // Construct from StyleOverscrollBehavior values.
+ static OverscrollBehaviorInfo FromStyleConstants(StyleOverscrollBehavior aBehaviorX,
+ StyleOverscrollBehavior aBehaviorY);
+
+ bool operator==(const OverscrollBehaviorInfo& aOther) const {
+ return mBehaviorX == aOther.mBehaviorX &&
+ mBehaviorY == aOther.mBehaviorY;
+ }
+
+ OverscrollBehavior mBehaviorX;
+ OverscrollBehavior mBehaviorY;
+};
+
/**
* A clip that applies to a layer, that may be scrolled by some of the
* scroll frames associated with the layer.
*/
struct LayerClip {
friend struct IPC::ParamTraits<mozilla::layers::LayerClip>;
public:
@@ -792,33 +818,35 @@ public:
, mLineScrollAmount(0, 0)
, mPageScrollAmount(0, 0)
, mScrollClip()
, mHasScrollgrab(false)
, mAllowVerticalScrollWithWheel(false)
, mIsLayersIdRoot(false)
, mUsesContainerScrolling(false)
, mForceDisableApz(false)
+ , mOverscrollBehavior()
{}
bool operator==(const ScrollMetadata& aOther) const
{
return mMetrics == aOther.mMetrics &&
mSnapInfo == aOther.mSnapInfo &&
mScrollParentId == aOther.mScrollParentId &&
mBackgroundColor == aOther.mBackgroundColor &&
// don't compare mContentDescription
mLineScrollAmount == aOther.mLineScrollAmount &&
mPageScrollAmount == aOther.mPageScrollAmount &&
mScrollClip == aOther.mScrollClip &&
mHasScrollgrab == aOther.mHasScrollgrab &&
mAllowVerticalScrollWithWheel == aOther.mAllowVerticalScrollWithWheel &&
mIsLayersIdRoot == aOther.mIsLayersIdRoot &&
mUsesContainerScrolling == aOther.mUsesContainerScrolling &&
- mForceDisableApz == aOther.mForceDisableApz;
+ mForceDisableApz == aOther.mForceDisableApz &&
+ mOverscrollBehavior == aOther.mOverscrollBehavior;
}
bool operator!=(const ScrollMetadata& aOther) const
{
return !operator==(aOther);
}
bool IsDefault() const
@@ -918,16 +946,23 @@ public:
}
void SetForceDisableApz(bool aForceDisable) {
mForceDisableApz = aForceDisable;
}
bool IsApzForceDisabled() const {
return mForceDisableApz;
}
+ void SetOverscrollBehavior(const OverscrollBehaviorInfo& aOverscrollBehavior) {
+ mOverscrollBehavior = aOverscrollBehavior;
+ }
+ const OverscrollBehaviorInfo& GetOverscrollBehavior() const {
+ return mOverscrollBehavior;
+ }
+
private:
FrameMetrics mMetrics;
// Information used to determine where to snap to for a given scroll.
ScrollSnapInfo mSnapInfo;
// The ViewID of the scrollable frame to which overscroll should be handed off.
ViewID mScrollParentId;
@@ -967,16 +1002,19 @@ private:
// True if scrolling using containers, false otherwise. This can be removed
// when containerful scrolling is eliminated.
bool mUsesContainerScrolling:1;
// Whether or not the compositor should actually do APZ-scrolling on this
// scrollframe.
bool mForceDisableApz:1;
+ // The overscroll behavior for this scroll frame.
+ OverscrollBehaviorInfo mOverscrollBehavior;
+
// WARNING!!!!
//
// When adding new fields to ScrollMetadata, the following places should be
// updated to include them (as needed):
// ScrollMetadata::operator ==
// AsyncPanZoomController::NotifyLayersUpdated
// The ParamTraits specialization in GfxMessageUtils.h
//
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -3854,16 +3854,17 @@ void AsyncPanZoomController::NotifyLayer
// The scroll clip can differ between layers associated a given scroll frame,
// so APZC (which keeps a single copy of ScrollMetadata per scroll frame)
// has no business using it.
mScrollMetadata.SetScrollClip(Nothing());
mScrollMetadata.SetIsLayersIdRoot(aScrollMetadata.IsLayersIdRoot());
mScrollMetadata.SetUsesContainerScrolling(aScrollMetadata.UsesContainerScrolling());
mFrameMetrics.SetIsScrollInfoLayer(aLayerMetrics.IsScrollInfoLayer());
mScrollMetadata.SetForceDisableApz(aScrollMetadata.IsApzForceDisabled());
+ mScrollMetadata.SetOverscrollBehavior(aScrollMetadata.GetOverscrollBehavior());
if (scrollOffsetUpdated) {
APZC_LOG("%p updating scroll offset from %s to %s\n", this,
ToString(mFrameMetrics.GetScrollOffset()).c_str(),
ToString(aLayerMetrics.GetScrollOffset()).c_str());
// Send an acknowledgement with the new scroll generation so that any
// repaint requests later in this function go through.
--- a/gfx/layers/ipc/LayersMessageUtils.h
+++ b/gfx/layers/ipc/LayersMessageUtils.h
@@ -73,16 +73,24 @@ struct ParamTraits<mozilla::layers::Scro
template<>
struct ParamTraits<mozilla::layers::FrameMetrics::ScrollOffsetUpdateType>
: public ContiguousEnumSerializerInclusive<
mozilla::layers::FrameMetrics::ScrollOffsetUpdateType,
mozilla::layers::FrameMetrics::ScrollOffsetUpdateType::eNone,
mozilla::layers::FrameMetrics::sHighestScrollOffsetUpdateType>
{};
+template <>
+struct ParamTraits<mozilla::layers::OverscrollBehavior>
+ : public ContiguousEnumSerializerInclusive<
+ mozilla::layers::OverscrollBehavior,
+ mozilla::layers::OverscrollBehavior::Auto,
+ mozilla::layers::kHighestOverscrollBehavior>
+{};
+
template<>
struct ParamTraits<mozilla::layers::LayerHandle>
{
typedef mozilla::layers::LayerHandle paramType;
static void Write(Message* msg, const paramType& param) {
WriteParam(msg, param.mHandle);
}
@@ -220,16 +228,37 @@ struct ParamTraits<mozilla::layers::Scro
ReadParam(aMsg, aIter, &aResult->mScrollSnapIntervalX) &&
ReadParam(aMsg, aIter, &aResult->mScrollSnapIntervalY) &&
ReadParam(aMsg, aIter, &aResult->mScrollSnapDestination) &&
ReadParam(aMsg, aIter, &aResult->mScrollSnapCoordinates));
}
};
template <>
+struct ParamTraits<mozilla::layers::OverscrollBehaviorInfo>
+{
+ // Not using PlainOldDataSerializer so we get enum validation
+ // for the members.
+
+ typedef mozilla::layers::OverscrollBehaviorInfo paramType;
+
+ static void Write(Message* aMsg, const paramType& aParam)
+ {
+ WriteParam(aMsg, aParam.mBehaviorX);
+ WriteParam(aMsg, aParam.mBehaviorY);
+ }
+
+ static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+ {
+ return (ReadParam(aMsg, aIter, &aResult->mBehaviorX) &&
+ ReadParam(aMsg, aIter, &aResult->mBehaviorY));
+ }
+};
+
+template <>
struct ParamTraits<mozilla::layers::LayerClip>
{
typedef mozilla::layers::LayerClip paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mClipRect);
WriteParam(aMsg, aParam.mMaskLayerIndex);
@@ -258,16 +287,17 @@ struct ParamTraits<mozilla::layers::Scro
WriteParam(aMsg, aParam.mLineScrollAmount);
WriteParam(aMsg, aParam.mPageScrollAmount);
WriteParam(aMsg, aParam.mScrollClip);
WriteParam(aMsg, aParam.mHasScrollgrab);
WriteParam(aMsg, aParam.mAllowVerticalScrollWithWheel);
WriteParam(aMsg, aParam.mIsLayersIdRoot);
WriteParam(aMsg, aParam.mUsesContainerScrolling);
WriteParam(aMsg, aParam.mForceDisableApz);
+ WriteParam(aMsg, aParam.mOverscrollBehavior);
}
static bool ReadContentDescription(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
nsCString str;
if (!ReadParam(aMsg, aIter, &str)) {
return false;
}
@@ -284,17 +314,18 @@ struct ParamTraits<mozilla::layers::Scro
ReadContentDescription(aMsg, aIter, aResult) &&
ReadParam(aMsg, aIter, &aResult->mLineScrollAmount) &&
ReadParam(aMsg, aIter, &aResult->mPageScrollAmount) &&
ReadParam(aMsg, aIter, &aResult->mScrollClip) &&
ReadBoolForBitfield(aMsg, aIter, aResult, ¶mType::SetHasScrollgrab) &&
ReadBoolForBitfield(aMsg, aIter, aResult, ¶mType::SetAllowVerticalScrollWithWheel) &&
ReadBoolForBitfield(aMsg, aIter, aResult, ¶mType::SetIsLayersIdRoot) &&
ReadBoolForBitfield(aMsg, aIter, aResult, ¶mType::SetUsesContainerScrolling) &&
- ReadBoolForBitfield(aMsg, aIter, aResult, ¶mType::SetForceDisableApz));
+ ReadBoolForBitfield(aMsg, aIter, aResult, ¶mType::SetForceDisableApz) &&
+ ReadParam(aMsg, aIter, &aResult->mOverscrollBehavior));
}
};
template<>
struct ParamTraits<mozilla::layers::TextureFactoryIdentifier>
{
typedef mozilla::layers::TextureFactoryIdentifier paramType;
--- a/ipc/glue/IPCMessageUtils.h
+++ b/ipc/glue/IPCMessageUtils.h
@@ -251,16 +251,21 @@ struct BitFlagsEnumSerializer
/**
* A helper class for serializing plain-old data (POD) structures.
* The memory representation of the structure is written to and read from
* the serialized stream directly, without individual processing of the
* structure's members.
*
* Derive ParamTraits<T> from PlainOldDataSerializer<T> if T is POD.
+ *
+ * Note: For POD structures with enumeration fields, this will not do
+ * validation of the enum values the way serializing the fields
+ * individually would. Prefer serializing the fields individually
+ * in such cases.
*/
template <typename T>
struct PlainOldDataSerializer
{
// TODO: Once the mozilla::IsPod trait is in good enough shape (bug 900042),
// static_assert that mozilla::IsPod<T>::value is true.
typedef T paramType;
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -9352,16 +9352,21 @@ nsLayoutUtils::ComputeScrollMetadata(nsI
EventStateManager::CanVerticallyScrollFrameWithWheel(aScrollFrame->GetParent()))
{
metadata.SetAllowVerticalScrollWithWheel(true);
}
metadata.SetUsesContainerScrolling(scrollableFrame->UsesContainerScrolling());
metadata.SetSnapInfo(scrollableFrame->GetScrollSnapInfo());
+
+ ScrollbarStyles scrollbarStyles = scrollableFrame->GetScrollbarStyles();
+ metadata.SetOverscrollBehavior(OverscrollBehaviorInfo::FromStyleConstants(
+ scrollbarStyles.mOverscrollBehaviorX,
+ scrollbarStyles.mOverscrollBehaviorY));
}
// If we have the scrollparent being the same as the scroll id, the
// compositor-side code could get into an infinite loop while building the
// overscroll handoff chain.
MOZ_ASSERT(aScrollParentId == FrameMetrics::NULL_SCROLL_ID || scrollId != aScrollParentId);
metrics.SetScrollId(scrollId);
metrics.SetIsRootContent(aIsRootContent);