From 480ee775c90aff94b9c9230359179762bc8a9bc4 Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Tue, 28 Apr 2020 01:36:34 +0000 Subject: [PATCH] Bug 1556556 - Apply the visual-to-layout transform during display list building and display list based hit testing. r=kats,mattwoodrow Differential Revision: https://phabricator.services.mozilla.com/D68728 --- layout/generic/nsGfxScrollFrame.cpp | 17 ++++++++++- layout/painting/nsDisplayList.cpp | 45 +++++++++++++++++++++++------ layout/painting/nsDisplayList.h | 14 ++++++--- 3 files changed, 62 insertions(+), 14 deletions(-) diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 5bc1ae8b0c6c..8ad5bd2724b0 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -44,6 +44,7 @@ #include "mozilla/Preferences.h" #include "mozilla/PresShell.h" #include "mozilla/ScrollbarPreferences.h" +#include "mozilla/ViewportUtils.h" #include "mozilla/LookAndFeel.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/Event.h" @@ -3667,8 +3668,22 @@ void ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, scrolledRectClipState.SetClippedToDisplayPort(); } + nsRect visibleRectForChildren = visibleRect; + nsRect dirtyRectForChildren = dirtyRect; + + // If we are entering the RCD-RSF, we are crossing the async zoom + // container boundary, and need to convert from visual to layout + // coordinates. + if (willBuildAsyncZoomContainer && aBuilder->IsForEventDelivery()) { + MOZ_ASSERT(ViewportUtils::IsZoomedContentRoot(mScrolledFrame)); + visibleRectForChildren = ViewportUtils::VisualToLayout( + visibleRectForChildren, mOuter->PresShell()); + dirtyRectForChildren = ViewportUtils::VisualToLayout( + dirtyRectForChildren, mOuter->PresShell()); + } + nsDisplayListBuilder::AutoBuildingDisplayList building( - aBuilder, mOuter, visibleRect, dirtyRect); + aBuilder, mOuter, visibleRectForChildren, dirtyRectForChildren); mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, set); diff --git a/layout/painting/nsDisplayList.cpp b/layout/painting/nsDisplayList.cpp index 8faa172ed28c..ae83b178fecc 100644 --- a/layout/painting/nsDisplayList.cpp +++ b/layout/painting/nsDisplayList.cpp @@ -34,6 +34,7 @@ #include "mozilla/StaticPrefs_gfx.h" #include "mozilla/StaticPrefs_layers.h" #include "mozilla/StaticPrefs_layout.h" +#include "mozilla/ViewportUtils.h" #include "nsCSSRendering.h" #include "nsCSSRenderingGradients.h" #include "nsRegion.h" @@ -101,6 +102,7 @@ #include "nsFocusManager.h" #include "ClientLayerManager.h" #include "mozilla/layers/AnimationHelper.h" +#include "mozilla/layers/InputAPZContext.h" #include "mozilla/layers/RenderRootStateManager.h" #include "mozilla/layers/StackingContextHelper.h" #include "mozilla/layers/TreeTraversal.h" @@ -1838,8 +1840,29 @@ void nsDisplayListBuilder::MarkFramesForDisplayList( const DisplayItemClipChain* combinedClipChain = mClipState.GetCurrentCombinedClipChain(this); const ActiveScrolledRoot* asr = mCurrentActiveScrolledRoot; + nsRect visibleRect = GetVisibleRect(); + nsRect dirtyRect = GetDirtyRect(); + + // If we are entering content that is fixed to the RCD-RSF, we are + // crossing the async zoom container boundary, and need to convert from + // visual to layout coordinates. + if (ViewportFrame* viewportFrame = do_QueryFrame(aDirtyFrame)) { + if (IsForEventDelivery() && ShouldBuildAsyncZoomContainer() && + viewportFrame->PresContext()->IsRootContentDocument()) { +#ifdef DEBUG + for (nsIFrame* f : aFrames) { + MOZ_ASSERT(ViewportUtils::IsZoomedContentRoot(f)); + } +#endif + visibleRect = ViewportUtils::VisualToLayout(visibleRect, + viewportFrame->PresShell()); + dirtyRect = ViewportUtils::VisualToLayout(dirtyRect, + viewportFrame->PresShell()); + } + } + OutOfFlowDisplayData* data = new OutOfFlowDisplayData( - clipChain, combinedClipChain, asr, GetVisibleRect(), GetDirtyRect()); + clipChain, combinedClipChain, asr, visibleRect, dirtyRect); aDirtyFrame->SetProperty( nsDisplayListBuilder::OutOfFlowDisplayDataProperty(), data); mFramesWithOOFData.AppendElement(aDirtyFrame); @@ -7148,14 +7171,6 @@ nsDisplayResolution::nsDisplayResolution(nsDisplayListBuilder* aBuilder, MOZ_COUNT_CTOR(nsDisplayResolution); } -void nsDisplayResolution::HitTest(nsDisplayListBuilder* aBuilder, - const nsRect& aRect, HitTestState* aState, - nsTArray* aOutFrames) { - PresShell* presShell = mFrame->PresShell(); - nsRect rect = aRect.RemoveResolution(presShell->GetResolution()); - mList.HitTest(aBuilder, rect, aState, aOutFrames); -} - already_AddRefed nsDisplayResolution::BuildLayer( nsDisplayListBuilder* aBuilder, LayerManager* aManager, const ContainerLayerParameters& aContainerParameters) { @@ -7890,6 +7905,18 @@ nsDisplayAsyncZoom::~nsDisplayAsyncZoom() { } #endif +void nsDisplayAsyncZoom::HitTest(nsDisplayListBuilder* aBuilder, + const nsRect& aRect, HitTestState* aState, + nsTArray* aOutFrames) { +#ifdef DEBUG + nsIScrollableFrame* scrollFrame = do_QueryFrame(mFrame); + MOZ_ASSERT(scrollFrame && ViewportUtils::IsZoomedContentRoot( + scrollFrame->GetScrolledFrame())); +#endif + nsRect rect = ViewportUtils::VisualToLayout(aRect, mFrame->PresShell()); + mList.HitTest(aBuilder, rect, aState, aOutFrames); +} + already_AddRefed nsDisplayAsyncZoom::BuildLayer( nsDisplayListBuilder* aBuilder, LayerManager* aManager, const ContainerLayerParameters& aContainerParameters) { diff --git a/layout/painting/nsDisplayList.h b/layout/painting/nsDisplayList.h index 2579b6967451..3ab431b8ee72 100644 --- a/layout/painting/nsDisplayList.h +++ b/layout/painting/nsDisplayList.h @@ -1517,6 +1517,12 @@ class nsDisplayListBuilder { const DisplayItemClipChain* mCombinedClipChain; // only necessary for the special case of top layer const ActiveScrolledRoot* mContainingBlockActiveScrolledRoot; + + // If this OutOfFlowDisplayData is associated with the ViewportFrame + // of a document that has a resolution (creating separate visual and + // layout viewports with their own coordinate spaces), these rects + // are in layout coordinates. Similarly, GetVisibleRectForFrame() in + // such a case returns a quantity in layout coordinates. nsRect mVisibleRect; nsRect mDirtyRect; @@ -6175,8 +6181,6 @@ class nsDisplayResolution : public nsDisplaySubDocument { NS_DISPLAY_DECL_NAME("Resolution", TYPE_RESOLUTION) - void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray* aOutFrames) override; already_AddRefed BuildLayer( nsDisplayListBuilder* aBuilder, LayerManager* aManager, const ContainerLayerParameters& aContainerParameters) override; @@ -6504,10 +6508,12 @@ class nsDisplayAsyncZoom : public nsDisplayOwnLayer { NS_DISPLAY_DECL_NAME("AsyncZoom", TYPE_ASYNC_ZOOM) - virtual already_AddRefed BuildLayer( + void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, + HitTestState* aState, nsTArray* aOutFrames) override; + already_AddRefed BuildLayer( nsDisplayListBuilder* aBuilder, LayerManager* aManager, const ContainerLayerParameters& aContainerParameters) override; - virtual LayerState GetLayerState( + LayerState GetLayerState( nsDisplayListBuilder* aBuilder, LayerManager* aManager, const ContainerLayerParameters& aParameters) override { return mozilla::LayerState::LAYER_ACTIVE_FORCE;