Bug 1358017 - Part 5: Implements the "honour root" functionality for the auto-dir scrolling feature in APZ r?kats
With this commit, all the auto-dir scrolling functionalities are completed in
APZ.
MozReview-Commit-ID: L7qa3xOD8t9
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -828,16 +828,17 @@ public:
, mScrollParentId(FrameMetrics::NULL_SCROLL_ID)
, mBackgroundColor()
, mContentDescription()
, mLineScrollAmount(0, 0)
, mPageScrollAmount(0, 0)
, mScrollClip()
, mHasScrollgrab(false)
, mIsLayersIdRoot(false)
+ , mIsAutoDirRootContentRTL(false)
, mUsesContainerScrolling(false)
, mForceDisableApz(false)
, mOverscrollBehavior()
{}
bool operator==(const ScrollMetadata& aOther) const
{
return mMetrics == aOther.mMetrics &&
@@ -845,16 +846,17 @@ public:
mScrollParentId == aOther.mScrollParentId &&
mBackgroundColor == aOther.mBackgroundColor &&
// don't compare mContentDescription
mLineScrollAmount == aOther.mLineScrollAmount &&
mPageScrollAmount == aOther.mPageScrollAmount &&
mScrollClip == aOther.mScrollClip &&
mHasScrollgrab == aOther.mHasScrollgrab &&
mIsLayersIdRoot == aOther.mIsLayersIdRoot &&
+ mIsAutoDirRootContentRTL == aOther.mIsAutoDirRootContentRTL &&
mUsesContainerScrolling == aOther.mUsesContainerScrolling &&
mForceDisableApz == aOther.mForceDisableApz &&
mDisregardedDirection == aOther.mDisregardedDirection &&
mOverscrollBehavior == aOther.mOverscrollBehavior;
}
bool operator!=(const ScrollMetadata& aOther) const
{
@@ -939,16 +941,22 @@ public:
return mHasScrollgrab;
}
void SetIsLayersIdRoot(bool aValue) {
mIsLayersIdRoot = aValue;
}
bool IsLayersIdRoot() const {
return mIsLayersIdRoot;
}
+ void SetIsAutoDirRootContentRTL(bool aValue) {
+ mIsAutoDirRootContentRTL = aValue;
+ }
+ bool IsAutoDirRootContentRTL() const {
+ return mIsAutoDirRootContentRTL;
+ }
// Implemented out of line because the implementation needs gfxPrefs.h
// and we don't want to include that from FrameMetrics.h.
void SetUsesContainerScrolling(bool aValue);
bool UsesContainerScrolling() const {
return mUsesContainerScrolling;
}
void SetForceDisableApz(bool aForceDisable) {
mForceDisableApz = aForceDisable;
@@ -1007,16 +1015,27 @@ private:
// Whether or not this frame is for an element marked 'scrollgrab'.
bool mHasScrollgrab:1;
// Whether these framemetrics are for the root scroll frame (root element if
// we don't have a root scroll frame) for its layers id.
bool mIsLayersIdRoot:1;
+ // The AutoDirRootContent is the <body> element in an HTML document, or the
+ // root scrollframe if there is no body. This member variable indicates
+ // whether this element's content in the horizontal direction starts from
+ // right to left (e.g. it's true either if "writing-mode: vertical-rl", or
+ // "writing-mode: horizontal-tb; direction: rtl" in CSS).
+ // When we do auto-dir scrolling (@see mozilla::WheelDeltaAdjustmentStrategy
+ // or refer to bug 1358017 for details), setting a pref can make the code use
+ // the writing mode of this root element instead of the target scrollframe,
+ // and so we need to know if the writing mode is RTL or not.
+ bool mIsAutoDirRootContentRTL:1;
+
// 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;
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -2079,18 +2079,19 @@ AsyncPanZoomController::CanScroll(Scroll
MOZ_ASSERT_UNREACHABLE("Invalid value");
return false;
}
bool
AsyncPanZoomController::IsContentOfHonouredTargetRightToLeft(
bool aHonoursRoot) const
{
- // TODO The current implementation only honours the scrolling target, the
- // functionality of honouring root is going to be added in the next commit.
+ if (aHonoursRoot) {
+ return mScrollMetadata.IsAutoDirRootContentRTL();
+ }
RecursiveMutexAutoLock lock(mRecursiveMutex);
return mFrameMetrics.IsHorizontalContentRightToLeft();
}
bool
AsyncPanZoomController::AllowScrollHandoffInCurrentBlock() const
{
bool result = mInputQueue->AllowScrollHandoff();
@@ -4088,16 +4089,18 @@ void AsyncPanZoomController::NotifyLayer
mScrollMetadata.SetLineScrollAmount(aScrollMetadata.GetLineScrollAmount());
mScrollMetadata.SetPageScrollAmount(aScrollMetadata.GetPageScrollAmount());
mScrollMetadata.SetSnapInfo(ScrollSnapInfo(aScrollMetadata.GetSnapInfo()));
// 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.SetIsAutoDirRootContentRTL(
+ aScrollMetadata.IsAutoDirRootContentRTL());
mScrollMetadata.SetUsesContainerScrolling(aScrollMetadata.UsesContainerScrolling());
mFrameMetrics.SetIsScrollInfoLayer(aLayerMetrics.IsScrollInfoLayer());
mScrollMetadata.SetForceDisableApz(aScrollMetadata.IsApzForceDisabled());
mScrollMetadata.SetDisregardedDirection(aScrollMetadata.GetDisregardedDirection());
mScrollMetadata.SetOverscrollBehavior(aScrollMetadata.GetOverscrollBehavior());
if (scrollOffsetUpdated) {
APZC_LOG("%p updating scroll offset from %s to %s\n", this,
--- a/gfx/layers/ipc/LayersMessageUtils.h
+++ b/gfx/layers/ipc/LayersMessageUtils.h
@@ -277,16 +277,17 @@ struct ParamTraits<mozilla::layers::Scro
WriteParam(aMsg, aParam.mScrollParentId);
WriteParam(aMsg, aParam.mBackgroundColor);
WriteParam(aMsg, aParam.GetContentDescription());
WriteParam(aMsg, aParam.mLineScrollAmount);
WriteParam(aMsg, aParam.mPageScrollAmount);
WriteParam(aMsg, aParam.mScrollClip);
WriteParam(aMsg, aParam.mHasScrollgrab);
WriteParam(aMsg, aParam.mIsLayersIdRoot);
+ WriteParam(aMsg, aParam.mIsAutoDirRootContentRTL);
WriteParam(aMsg, aParam.mUsesContainerScrolling);
WriteParam(aMsg, aParam.mForceDisableApz);
WriteParam(aMsg, aParam.mDisregardedDirection);
WriteParam(aMsg, aParam.mOverscrollBehavior);
}
static bool ReadContentDescription(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
@@ -305,16 +306,18 @@ struct ParamTraits<mozilla::layers::Scro
ReadParam(aMsg, aIter, &aResult->mScrollParentId) &&
ReadParam(aMsg, aIter, &aResult->mBackgroundColor) &&
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::SetIsLayersIdRoot) &&
+ ReadBoolForBitfield(aMsg, aIter, aResult,
+ ¶mType::SetIsAutoDirRootContentRTL) &&
ReadBoolForBitfield(aMsg, aIter, aResult, ¶mType::SetUsesContainerScrolling) &&
ReadBoolForBitfield(aMsg, aIter, aResult, ¶mType::SetForceDisableApz) &&
ReadParam(aMsg, aIter, &aResult->mDisregardedDirection) &&
ReadParam(aMsg, aIter, &aResult->mOverscrollBehavior));
}
};
template<>
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -9336,26 +9336,60 @@ nsLayoutUtils::ComputeScrollMetadata(nsI
// 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);
metadata.SetScrollParentId(aScrollParentId);
+ nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
+ bool isRootScrollFrame = aScrollFrame == rootScrollFrame;
+ nsIDocument* document = presShell->GetDocument();
+
if (scrollId != FrameMetrics::NULL_SCROLL_ID && !presContext->GetParentPresContext()) {
- if ((aScrollFrame && (aScrollFrame == presShell->GetRootScrollFrame())) ||
- aContent == presShell->GetDocument()->GetDocumentElement()) {
+ if ((aScrollFrame && isRootScrollFrame)) {
metadata.SetIsLayersIdRoot(true);
+ } else {
+ MOZ_ASSERT(document, "A non-root-scroll frame must be in a document");
+ if (aContent == document->GetDocumentElement()) {
+ metadata.SetIsLayersIdRoot(true);
+ }
+ }
+ }
+
+ // Get whether the root content is RTL(E.g. it's true either if
+ // "writing-mode: vertical-rl", or if
+ // "writing-mode: horizontal-tb; direction: rtl;" in CSS).
+ // For the concept of this and the reason why we need to get this kind of
+ // information, see the definition of |mIsAutoDirRootContentRTL| in struct
+ // |ScrollMetadata|.
+ Element* bodyElement = document ? document->GetBodyElement() : nullptr;
+ nsIFrame* primaryFrame = bodyElement ? bodyElement->GetPrimaryFrame() :
+ rootScrollFrame;
+ if (!primaryFrame) {
+ primaryFrame = rootScrollFrame;
+ }
+ if (primaryFrame) {
+ WritingMode writingModeOfRootScrollFrame =
+ primaryFrame->GetWritingMode();
+ WritingMode::BlockDir blockDirOfRootScrollFrame =
+ writingModeOfRootScrollFrame.GetBlockDir();
+ WritingMode::InlineDir inlineDirOfRootScrollFrame =
+ writingModeOfRootScrollFrame.GetInlineDir();
+ if (blockDirOfRootScrollFrame == WritingMode::BlockDir::eBlockRL ||
+ (blockDirOfRootScrollFrame == WritingMode::BlockDir::eBlockTB &&
+ inlineDirOfRootScrollFrame == WritingMode::InlineDir::eInlineRTL)) {
+ metadata.SetIsAutoDirRootContentRTL(true);
}
}
// Only the root scrollable frame for a given presShell should pick up
// the presShell's resolution. All the other frames are 1.0.
- if (aScrollFrame == presShell->GetRootScrollFrame()) {
+ if (isRootScrollFrame) {
metrics.SetPresShellResolution(presShell->GetResolution());
} else {
metrics.SetPresShellResolution(1.0f);
}
// The cumulative resolution is the resolution at which the scroll frame's
// content is actually rendered. It includes the pres shell resolutions of
// all the pres shells from here up to the root, as well as any css-driven
// resolution. We don't need to compute it as it's already stored in the
@@ -9404,17 +9438,16 @@ nsLayoutUtils::ComputeScrollMetadata(nsI
// For the root scroll frame of the root content document (RCD-RSF), the above calculation
// will yield the size of the viewport frame as the composition bounds, which
// doesn't actually correspond to what is visible when
// nsIDOMWindowUtils::setCSSViewport has been called to modify the visible area of
// the prescontext that the viewport frame is reflowed into. In that case if our
// document has a widget then the widget's bounds will correspond to what is
// visible. If we don't have a widget the root view's bounds correspond to what
// would be visible because they don't get modified by setCSSViewport.
- bool isRootScrollFrame = aScrollFrame == presShell->GetRootScrollFrame();
bool isRootContentDocRootScrollFrame = isRootScrollFrame
&& presContext->IsRootContentDocument();
if (isRootContentDocRootScrollFrame) {
UpdateCompositionBoundsForRCDRSF(frameBounds, presContext, true);
}
nsMargin sizes = ScrollbarAreaToExcludeFromCompositionBoundsFor(aScrollFrame);
// Scrollbars are not subject to resolution scaling, so LD pixels = layer pixels for them.