Bug 951793 - Store the overscroll behavior in ScrollMetadata and propagate it to APZ. r=mstange draft
authorBotond Ballo <botond@mozilla.com>
Wed, 18 Oct 2017 20:13:19 -0400
changeset 703285 f9d0f664f17f4efe34a21064cbbf259642fe3caf
parent 703284 05f2abc208016ce55bbf2c20c231ab638f0fee3d
child 703286 6e1e0fe0b3975bdd60b5cb13af950d74ea849d2f
push id90783
push userbballo@mozilla.com
push dateFri, 24 Nov 2017 21:22:10 +0000
reviewersmstange
bugs951793
milestone59.0a1
Bug 951793 - Store the overscroll behavior in ScrollMetadata and propagate it to APZ. r=mstange MozReview-Commit-ID: J7Vkd941QxK
gfx/layers/FrameMetrics.cpp
gfx/layers/FrameMetrics.h
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/ipc/LayersMessageUtils.h
ipc/glue/IPCMessageUtils.h
layout/base/nsLayoutUtils.cpp
--- 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, &paramType::SetHasScrollgrab) &&
             ReadBoolForBitfield(aMsg, aIter, aResult, &paramType::SetAllowVerticalScrollWithWheel) &&
             ReadBoolForBitfield(aMsg, aIter, aResult, &paramType::SetIsLayersIdRoot) &&
             ReadBoolForBitfield(aMsg, aIter, aResult, &paramType::SetUsesContainerScrolling) &&
-            ReadBoolForBitfield(aMsg, aIter, aResult, &paramType::SetForceDisableApz));
+            ReadBoolForBitfield(aMsg, aIter, aResult, &paramType::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);