mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1210578. Part 3. Create DecideScrollableLayer that encapsulates all logic to create display ports and build scrollable layers. r=mstange
For root scroll frames we need information about the async scrolling (or lack thereof) of the scroll frame before we get to ScrollFrameHelper::BuildDisplayList for the scroll frame. We need it in nsLayoutUtils::PaintFrame and nsSubdocumentFrame::BuildDisplayList. So we factor out all the code responsible for async scrolling decisions into one function we can call from all three places.
This commit is contained in:
parent
efe42313c1
commit
365d409500
@ -3133,14 +3133,16 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
||||
nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
|
||||
bool usingDisplayPort = false;
|
||||
nsRect displayport;
|
||||
if (rootScrollFrame && !aFrame->GetParent() &&
|
||||
builder.IsPaintingToWindow() &&
|
||||
gfxPrefs::LayoutUseContainersForRootFrames()) {
|
||||
nsRect displayportBase(
|
||||
nsPoint(0,0),
|
||||
nsLayoutUtils::CalculateCompositionSizeForFrame(rootScrollFrame));
|
||||
usingDisplayPort = nsLayoutUtils::GetOrMaybeCreateDisplayPort(
|
||||
builder, rootScrollFrame, displayportBase, &displayport);
|
||||
if (rootScrollFrame && !aFrame->GetParent()) {
|
||||
nsIScrollableFrame* rootScrollableFrame = presShell->GetRootScrollFrameAsScrollable();
|
||||
MOZ_ASSERT(rootScrollableFrame);
|
||||
displayport = aFrame->GetVisualOverflowRectRelativeToSelf();
|
||||
usingDisplayPort = rootScrollableFrame->DecideScrollableLayer(&builder,
|
||||
&displayport, /* aAllowCreateDisplayPort = */ true);
|
||||
|
||||
if (!gfxPrefs::LayoutUseContainersForRootFrames()) {
|
||||
usingDisplayPort = false;
|
||||
}
|
||||
}
|
||||
|
||||
nsDisplayList hoistedScrollItemStorage;
|
||||
|
@ -61,6 +61,7 @@
|
||||
#include "nsPluginFrame.h"
|
||||
#include <mozilla/layers/AxisPhysicsModel.h>
|
||||
#include <mozilla/layers/AxisPhysicsMSDModel.h>
|
||||
#include "mozilla/unused.h"
|
||||
#include <algorithm>
|
||||
#include <cstdlib> // for std::abs(int/long)
|
||||
#include <cmath> // for std::abs(float/double)
|
||||
@ -2864,21 +2865,14 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
bool createLayersForScrollbars = mIsRoot &&
|
||||
mOuter->PresContext()->IsRootContentDocument();
|
||||
|
||||
bool usingDisplayPort = aBuilder->IsPaintingToWindow() &&
|
||||
nsLayoutUtils::GetDisplayPort(mOuter->GetContent());
|
||||
|
||||
if (aBuilder->GetIgnoreScrollFrame() == mOuter || IsIgnoringViewportClipping()) {
|
||||
bool usingDisplayPort = aBuilder->IsPaintingToWindow() &&
|
||||
nsLayoutUtils::GetDisplayPort(mOuter->GetContent());
|
||||
|
||||
// Root scrollframes have FrameMetrics and clipping on their container
|
||||
// layers, so don't apply clipping again.
|
||||
mAddClipRectToLayer = false;
|
||||
|
||||
if (usingDisplayPort) {
|
||||
// There is a display port for this frame, so we want to appear as having
|
||||
// active scrolling, so that animated geometry roots are assigned correctly.
|
||||
mWillBuildScrollableLayer = true;
|
||||
mIsScrollableLayerInRootContainer = true;
|
||||
}
|
||||
|
||||
// If we are a root scroll frame that has a display port we want to add
|
||||
// scrollbars, they will be children of the scrollable layer, but they get
|
||||
// adjusted by the APZC automatically.
|
||||
@ -2920,48 +2914,12 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
// dirty rect here.
|
||||
nsRect dirtyRect = aDirtyRect.Intersect(mScrollPort);
|
||||
|
||||
nsRect displayPort;
|
||||
if (aBuilder->IsPaintingToWindow()) {
|
||||
bool wasUsingDisplayPort = usingDisplayPort;
|
||||
unused << DecideScrollableLayer(aBuilder, &dirtyRect,
|
||||
/* aAllowCreateDisplayPort = */ !mIsRoot);
|
||||
|
||||
if (mIsRoot && gfxPrefs::LayoutUseContainersForRootFrames()) {
|
||||
// For a root frame in a container, just get the value of the existing
|
||||
// display port if any.
|
||||
usingDisplayPort = nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &displayPort);
|
||||
} else {
|
||||
// Override the value of the display port base rect, and possibly create a
|
||||
// display port if there isn't one already.
|
||||
nsRect displayportBase = dirtyRect;
|
||||
if (mIsRoot && mOuter->PresContext()->IsRootContentDocument()) {
|
||||
displayportBase =
|
||||
nsRect(nsPoint(0, 0), nsLayoutUtils::CalculateCompositionSizeForFrame(mOuter));
|
||||
}
|
||||
usingDisplayPort = nsLayoutUtils::GetOrMaybeCreateDisplayPort(
|
||||
*aBuilder, mOuter, displayportBase, &displayPort);
|
||||
}
|
||||
bool usingDisplayPort = aBuilder->IsPaintingToWindow() &&
|
||||
nsLayoutUtils::GetDisplayPort(mOuter->GetContent());
|
||||
|
||||
// Override the dirty rectangle if the displayport has been set.
|
||||
if (usingDisplayPort) {
|
||||
dirtyRect = displayPort;
|
||||
|
||||
// The cached animated geometry root for the display builder is out of
|
||||
// date if we just introduced a new animated geometry root.
|
||||
if (!wasUsingDisplayPort) {
|
||||
aBuilder->RecomputeCurrentAnimatedGeometryRoot();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Since making new layers is expensive, only use nsDisplayScrollLayer
|
||||
// if the area is scrollable and we're the content process (unless we're on
|
||||
// B2G, where we support async scrolling for scrollable elements in the
|
||||
// parent process as well).
|
||||
// When a displayport is being used, force building of a layer so that
|
||||
// CompositorParent can always find the scrollable layer for the root content
|
||||
// document.
|
||||
// If the element is marked 'scrollgrab', also force building of a layer
|
||||
// so that APZ can implement scroll grabbing.
|
||||
mWillBuildScrollableLayer = usingDisplayPort || nsContentUtils::HasScrollgrab(mOuter->GetContent());
|
||||
// Whether we might want to build a scrollable layer for this scroll frame
|
||||
// at some point in the future. This controls whether we add the information
|
||||
// to the layer tree (a scroll info layer if necessary, and add the right
|
||||
@ -3171,6 +3129,64 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
scrolledContent.MoveTo(aLists);
|
||||
}
|
||||
|
||||
bool
|
||||
ScrollFrameHelper::DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsRect* aDirtyRect,
|
||||
bool aAllowCreateDisplayPort)
|
||||
{
|
||||
bool usingDisplayPort = false;
|
||||
nsIContent* content = mOuter->GetContent();
|
||||
if (aBuilder->IsPaintingToWindow()) {
|
||||
bool wasUsingDisplayPort = nsLayoutUtils::GetDisplayPort(content);
|
||||
|
||||
nsRect displayportBase = *aDirtyRect;
|
||||
nsPresContext* pc = mOuter->PresContext();
|
||||
if (mIsRoot && (pc->IsRootContentDocument() || !pc->GetParentPresContext())) {
|
||||
displayportBase =
|
||||
nsRect(nsPoint(0, 0), nsLayoutUtils::CalculateCompositionSizeForFrame(mOuter));
|
||||
}
|
||||
|
||||
nsRect displayPort;
|
||||
if (aAllowCreateDisplayPort) {
|
||||
// Provide the value of the display port base rect, and possibly create a
|
||||
// display port if there isn't one already.
|
||||
usingDisplayPort = nsLayoutUtils::GetOrMaybeCreateDisplayPort(
|
||||
*aBuilder, mOuter, displayportBase, &displayPort);
|
||||
} else {
|
||||
// We should have already been called with aAllowCreateDisplayPort == true
|
||||
// which should have set a displayport base.
|
||||
MOZ_ASSERT(content->GetProperty(nsGkAtoms::DisplayPortBase));
|
||||
usingDisplayPort = nsLayoutUtils::GetDisplayPort(content, &displayPort);
|
||||
}
|
||||
|
||||
// Override the dirty rectangle if the displayport has been set.
|
||||
if (usingDisplayPort) {
|
||||
*aDirtyRect = displayPort;
|
||||
|
||||
// The cached animated geometry root for the display builder is out of
|
||||
// date if we just introduced a new animated geometry root.
|
||||
if (!wasUsingDisplayPort) {
|
||||
aBuilder->RecomputeCurrentAnimatedGeometryRoot();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Since making new layers is expensive, only create a scrollable layer
|
||||
// for some scroll frames.
|
||||
// When a displayport is being used, force building of a layer so that
|
||||
// the compositor can find the scrollable layer for async scrolling.
|
||||
// If the element is marked 'scrollgrab', also force building of a layer
|
||||
// so that APZ can implement scroll grabbing.
|
||||
mWillBuildScrollableLayer = usingDisplayPort || nsContentUtils::HasScrollgrab(content);
|
||||
|
||||
if (gfxPrefs::LayoutUseContainersForRootFrames() && mWillBuildScrollableLayer && mIsRoot) {
|
||||
mIsScrollableLayerInRootContainer = true;
|
||||
}
|
||||
|
||||
return mWillBuildScrollableLayer;
|
||||
}
|
||||
|
||||
|
||||
Maybe<DisplayItemClip>
|
||||
ScrollFrameHelper::ComputeScrollClip(bool aIsForCaret) const
|
||||
{
|
||||
|
@ -366,6 +366,10 @@ public:
|
||||
|
||||
bool UsesContainerScrolling() const;
|
||||
|
||||
bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsRect* aDirtyRect,
|
||||
bool aAllowCreateDisplayPort);
|
||||
|
||||
void ScheduleSyntheticMouseMove();
|
||||
static void ScrollActivityCallback(nsITimer *aTimer, void* anInstance);
|
||||
|
||||
@ -873,6 +877,11 @@ public:
|
||||
virtual bool UsesContainerScrolling() const override {
|
||||
return mHelper.UsesContainerScrolling();
|
||||
}
|
||||
virtual bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsRect* aDirtyRect,
|
||||
bool aAllowCreateDisplayPort) override {
|
||||
return mHelper.DecideScrollableLayer(aBuilder, aDirtyRect, aAllowCreateDisplayPort);
|
||||
}
|
||||
|
||||
// nsIStatefulFrame
|
||||
NS_IMETHOD SaveState(nsPresState** aState) override {
|
||||
@ -1351,6 +1360,12 @@ public:
|
||||
void SetZoomableByAPZ(bool aZoomable) override {
|
||||
mHelper.SetZoomableByAPZ(aZoomable);
|
||||
}
|
||||
virtual bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsRect* aDirtyRect,
|
||||
bool aAllowCreateDisplayPort) override {
|
||||
return mHelper.DecideScrollableLayer(aBuilder, aDirtyRect, aAllowCreateDisplayPort);
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
virtual nsresult GetFrameName(nsAString& aResult) const override;
|
||||
|
@ -455,6 +455,19 @@ public:
|
||||
virtual bool UsesContainerScrolling() const = 0;
|
||||
|
||||
virtual mozilla::Maybe<mozilla::DisplayItemClip> ComputeScrollClip(bool aIsForCaret) const = 0;
|
||||
|
||||
/**
|
||||
* Determine if we should build a scrollable layer for this scroll frame and
|
||||
* return the result. It will also record this result on the scroll frame.
|
||||
* Pass the dirty rect in aDirtyRect. On return it will be set to the
|
||||
* displayport if there is one (ie the dirty rect that should be used).
|
||||
* This function may create a display port where one did not exist before if
|
||||
* aAllowCreateDisplayPort is true. It is only allowed to be false if there
|
||||
* has been a call with it set to true before on the same paint.
|
||||
*/
|
||||
virtual bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsRect* aDirtyRect,
|
||||
bool aAllowCreateDisplayPort) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -416,18 +416,13 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
dirty = dirty.ScaleToOtherAppUnitsRoundOut(parentAPD, subdocAPD);
|
||||
|
||||
if (nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame()) {
|
||||
if (gfxPrefs::LayoutUseContainersForRootFrames()) {
|
||||
// for root content documents we want the base to be the composition bounds
|
||||
nsRect displayportBase = presContext->IsRootContentDocument() ?
|
||||
nsRect(nsPoint(0,0), nsLayoutUtils::CalculateCompositionSizeForFrame(rootScrollFrame)) :
|
||||
dirty.Intersect(nsRect(nsPoint(0,0), subdocRootFrame->GetSize()));
|
||||
nsRect displayPort;
|
||||
if (aBuilder->IsPaintingToWindow() &&
|
||||
nsLayoutUtils::GetOrMaybeCreateDisplayPort(
|
||||
*aBuilder, rootScrollFrame, displayportBase, &displayPort)) {
|
||||
haveDisplayPort = true;
|
||||
dirty = displayPort;
|
||||
}
|
||||
nsIScrollableFrame* rootScrollableFrame = presShell->GetRootScrollFrameAsScrollable();
|
||||
MOZ_ASSERT(rootScrollableFrame);
|
||||
haveDisplayPort = rootScrollableFrame->DecideScrollableLayer(aBuilder,
|
||||
&dirty, /* aAllowCreateDisplayPort = */ true);
|
||||
|
||||
if (!gfxPrefs::LayoutUseContainersForRootFrames()) {
|
||||
haveDisplayPort = false;
|
||||
}
|
||||
|
||||
ignoreViewportScrolling = presShell->IgnoringViewportScrolling();
|
||||
|
Loading…
Reference in New Issue
Block a user