diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index 45bebf7d94e2..621156b9ab4e 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -619,7 +619,7 @@ static bool PrepareForSetTargetAPZCNotification( if (!guidIsValid) { return false; } - if (DisplayPortUtils::HasDisplayPort(dpElement)) { + if (DisplayPortUtils::HasNonMinimalDisplayPort(dpElement)) { // If the element has a displayport but it hasn't been painted yet, // we want the caller to wait for the paint to happen, but we don't // need to set the displayport here since it's already been set. diff --git a/layout/base/DisplayPortUtils.cpp b/layout/base/DisplayPortUtils.cpp index 694b4479e012..b1cb21e30103 100644 --- a/layout/base/DisplayPortUtils.cpp +++ b/layout/base/DisplayPortUtils.cpp @@ -630,6 +630,11 @@ void DisplayPortUtils::MarkDisplayPortAsPainted(nsIContent* aContent) { } } +bool DisplayPortUtils::HasNonMinimalDisplayPort(nsIContent* aContent) { + return HasDisplayPort(aContent) && + !aContent->GetProperty(nsGkAtoms::MinimalDisplayPort); +} + /* static */ bool DisplayPortUtils::GetDisplayPortForVisibilityTesting(nsIContent* aContent, nsRect* aResult) { @@ -943,7 +948,7 @@ bool DisplayPortUtils::MaybeCreateDisplayPort(nsDisplayListBuilder* aBuilder, return false; } - bool haveDisplayPort = HasDisplayPort(content); + bool haveDisplayPort = HasNonMinimalDisplayPort(content); // We perform an optimization where we ensure that at least one // async-scrollable frame (i.e. one that WantsAsyncScroll()) has a @@ -966,7 +971,7 @@ bool DisplayPortUtils::MaybeCreateDisplayPort(nsDisplayListBuilder* aBuilder, CalculateAndSetDisplayPortMargins(scrollableFrame, aRepaintMode); #ifdef DEBUG - haveDisplayPort = HasDisplayPort(content); + haveDisplayPort = HasNonMinimalDisplayPort(content); MOZ_ASSERT(haveDisplayPort, "should have a displayport after having just set it"); #endif @@ -996,7 +1001,7 @@ void DisplayPortUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors( MOZ_ASSERT(scrollAncestor->WantAsyncScroll() || frame->PresShell()->GetRootScrollFrame() == frame); if (nsLayoutUtils::AsyncPanZoomEnabled(frame) && - !HasDisplayPort(frame->GetContent())) { + (!HasNonMinimalDisplayPort(frame->GetContent()))) { SetDisplayPortMargins(frame->GetContent(), frame->PresShell(), DisplayPortMargins::Empty(frame->GetContent()), ClearMinimalDisplayPortProperty::Yes, 0, diff --git a/layout/base/DisplayPortUtils.h b/layout/base/DisplayPortUtils.h index 0cc307d27219..185375025416 100644 --- a/layout/base/DisplayPortUtils.h +++ b/layout/base/DisplayPortUtils.h @@ -180,6 +180,11 @@ class DisplayPortUtils { static bool FrameHasDisplayPort(nsIFrame* aFrame, const nsIFrame* aScrolledFrame = nullptr); + /** + * Check whether the given element has a non-minimal displayport. + */ + static bool HasNonMinimalDisplayPort(nsIContent* aContent); + /** * Check if the given element has a margins based displayport but is missing a * displayport base rect that it needs to properly compute a displayport rect. diff --git a/layout/base/GeckoMVMContext.cpp b/layout/base/GeckoMVMContext.cpp index 43a382638521..042d351f213a 100644 --- a/layout/base/GeckoMVMContext.cpp +++ b/layout/base/GeckoMVMContext.cpp @@ -169,7 +169,8 @@ void GeckoMVMContext::PostVisualViewportResizeEventByDynamicToolbar() { void GeckoMVMContext::UpdateDisplayPortMargins() { MOZ_ASSERT(mPresShell); if (nsIFrame* root = mPresShell->GetRootScrollFrame()) { - bool hasDisplayPort = DisplayPortUtils::HasDisplayPort(root->GetContent()); + nsIContent* content = root->GetContent(); + bool hasDisplayPort = DisplayPortUtils::HasNonMinimalDisplayPort(content); bool hasResolution = mPresShell->GetResolution() != 1.0f; if (!hasDisplayPort && !hasResolution) { // We only want to update the displayport if there is one already, or @@ -184,8 +185,7 @@ void GeckoMVMContext::UpdateDisplayPortMargins() { // because non-toplevel documents have no limit on their size. MOZ_ASSERT( mPresShell->GetPresContext()->IsRootContentDocumentCrossProcess()); - DisplayPortUtils::SetDisplayPortBaseIfNotSet(root->GetContent(), - displayportBase); + DisplayPortUtils::SetDisplayPortBaseIfNotSet(content, displayportBase); nsIScrollableFrame* scrollable = do_QueryFrame(root); DisplayPortUtils::CalculateAndSetDisplayPortMargins( scrollable, DisplayPortUtils::RepaintMode::Repaint); diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 96fafb39e9e0..532b2999952f 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -3294,7 +3294,7 @@ nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, presShell->GetRootScrollFrame())) { if (dom::Element* element = presShell->GetDocument()->GetDocumentElement()) { - if (!DisplayPortUtils::HasDisplayPort(element)) { + if (!DisplayPortUtils::HasNonMinimalDisplayPort(element)) { APZCCallbackHelper::InitializeRootDisplayport(presShell); } } diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 885cf33660b5..e532d714905f 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -3004,6 +3004,7 @@ void ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, bool schedulePaint = true; if (nsLayoutUtils::AsyncPanZoomEnabled(mOuter) && !nsLayoutUtils::ShouldDisableApzForElement(content) && + !content->GetProperty(nsGkAtoms::MinimalDisplayPort) && StaticPrefs::apz_paint_skipping_enabled()) { // If APZ is enabled with paint-skipping, there are certain conditions in // which we can skip paints: @@ -4703,11 +4704,12 @@ void ScrollFrameHelper::ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, AppendScrollUpdate( ScrollPositionUpdate::NewPureRelativeScroll(aOrigin, aMode, delta)); - if (!DisplayPortUtils::HasDisplayPort(mOuter->GetContent())) { + nsIContent* content = mOuter->GetContent(); + if (!DisplayPortUtils::HasNonMinimalDisplayPort(content)) { if (MOZ_LOG_TEST(sDisplayportLog, LogLevel::Debug)) { mozilla::layers::ScrollableLayerGuid::ViewID viewID = mozilla::layers::ScrollableLayerGuid::NULL_SCROLL_ID; - nsLayoutUtils::FindIDFor(mOuter->GetContent(), &viewID); + nsLayoutUtils::FindIDFor(content, &viewID); MOZ_LOG( sDisplayportLog, LogLevel::Debug, ("ScrollBy setting displayport on scrollId=%" PRIu64 "\n", viewID)); @@ -5975,6 +5977,20 @@ bool ScrollFrameHelper::IsScrollingActive( nsContentUtils::HasScrollgrab(content); } +bool ScrollFrameHelper::IsScrollingActiveNotMinimalDisplayPort( + nsDisplayListBuilder* aBuilder) const { + const nsStyleDisplay* disp = mOuter->StyleDisplay(); + if (disp->mWillChange.bits & StyleWillChangeBits::SCROLL && + aBuilder->IsInWillChangeBudget(mOuter, GetVisualViewportSize())) { + return true; + } + + nsIContent* content = mOuter->GetContent(); + return mHasBeenScrolledRecently || IsAlwaysActive() || + DisplayPortUtils::HasNonMinimalDisplayPort(content) || + nsContentUtils::HasScrollgrab(content); +} + /** * Reflow the scroll area if it needs it and return its size. Also determine if * the reflow will cause any of the scrollbars to need to be reflowed. @@ -7797,7 +7813,8 @@ void ScrollFrameHelper::ApzSmoothScrollTo(const nsPoint& aDestination, AppendScrollUpdate( ScrollPositionUpdate::NewSmoothScroll(aOrigin, aDestination)); - if (!DisplayPortUtils::HasDisplayPort(mOuter->GetContent())) { + nsIContent* content = mOuter->GetContent(); + if (!DisplayPortUtils::HasNonMinimalDisplayPort(content)) { // If this frame doesn't have a displayport then there won't be an // APZC instance for it and so there won't be anything to process // this smooth scroll request. We should set a displayport on this @@ -7805,7 +7822,7 @@ void ScrollFrameHelper::ApzSmoothScrollTo(const nsPoint& aDestination, if (MOZ_LOG_TEST(sDisplayportLog, LogLevel::Debug)) { mozilla::layers::ScrollableLayerGuid::ViewID viewID = mozilla::layers::ScrollableLayerGuid::NULL_SCROLL_ID; - nsLayoutUtils::FindIDFor(mOuter->GetContent(), &viewID); + nsLayoutUtils::FindIDFor(content, &viewID); MOZ_LOG( sDisplayportLog, LogLevel::Debug, ("ApzSmoothScrollTo setting displayport on scrollId=%" PRIu64 "\n", diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 5db3a9dace70..52e47059300f 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -378,6 +378,8 @@ class ScrollFrameHelper : public nsIReflowCallback { public: bool IsScrollbarOnRight() const; bool IsScrollingActive(nsDisplayListBuilder* aBuilder) const; + bool IsScrollingActiveNotMinimalDisplayPort( + nsDisplayListBuilder* aBuilder) const; bool IsMaybeAsynchronouslyScrolled() const { // If this is true, then we'll build an ASR, and that's what we want // to know I think. @@ -1042,6 +1044,10 @@ class nsHTMLScrollFrame : public nsContainerFrame, bool IsScrollingActive(nsDisplayListBuilder* aBuilder) final { return mHelper.IsScrollingActive(aBuilder); } + bool IsScrollingActiveNotMinimalDisplayPort( + nsDisplayListBuilder* aBuilder) final { + return mHelper.IsScrollingActiveNotMinimalDisplayPort(aBuilder); + } bool IsMaybeScrollingActive() const final { return mHelper.IsMaybeScrollingActive(); } @@ -1525,6 +1531,10 @@ class nsXULScrollFrame final : public nsBoxFrame, bool IsScrollingActive(nsDisplayListBuilder* aBuilder) final { return mHelper.IsScrollingActive(aBuilder); } + bool IsScrollingActiveNotMinimalDisplayPort( + nsDisplayListBuilder* aBuilder) final { + return mHelper.IsScrollingActiveNotMinimalDisplayPort(aBuilder); + } bool IsMaybeScrollingActive() const final { return mHelper.IsMaybeScrollingActive(); } diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index 18c0581b60c4..e862a9c688be 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -381,6 +381,13 @@ class nsIScrollableFrame : public nsIScrollbarMediator { */ virtual bool IsScrollingActive(nsDisplayListBuilder* aBuilder) = 0; + /** + * The same as IsScrollingActive but minimal display ports are not considered + * active. + */ + virtual bool IsScrollingActiveNotMinimalDisplayPort( + nsDisplayListBuilder* aBuilder) = 0; + /** * Returns true if this scroll frame might be scrolled * asynchronously by the compositor. diff --git a/layout/painting/ActiveLayerTracker.cpp b/layout/painting/ActiveLayerTracker.cpp index 4000ee9191c5..729ec344fc2a 100644 --- a/layout/painting/ActiveLayerTracker.cpp +++ b/layout/painting/ActiveLayerTracker.cpp @@ -418,7 +418,9 @@ static bool CheckScrollInducedActivity( nsIScrollableFrame* scrollFrame = do_QueryFrame(aLayerActivity->mAnimatingScrollHandlerFrame.GetFrame()); - if (scrollFrame && (!aBuilder || scrollFrame->IsScrollingActive(aBuilder))) { + if (scrollFrame && + (!aBuilder || + scrollFrame->IsScrollingActiveNotMinimalDisplayPort(aBuilder))) { return true; } diff --git a/layout/xul/nsSliderFrame.cpp b/layout/xul/nsSliderFrame.cpp index e22415340d58..0b8404b88ec5 100644 --- a/layout/xul/nsSliderFrame.cpp +++ b/layout/xul/nsSliderFrame.cpp @@ -1122,7 +1122,7 @@ void nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent) { return; } - if (!DisplayPortUtils::HasDisplayPort(scrollableContent)) { + if (!DisplayPortUtils::HasNonMinimalDisplayPort(scrollableContent)) { return; }