Bug 1404181 - Part 15: Compute scrollbar thumb AGR state in advance, rather than setting it during building. r?mstange
MozReview-Commit-ID: D9eQy8f2kw
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2111,30 +2111,16 @@ nsLayoutUtils::IsFixedPosFrameInDisplayP
nsIFrame* parent = aFrame->GetParent();
if (!parent || parent->GetParent() ||
aFrame->StyleDisplay()->mPosition != NS_STYLE_POSITION_FIXED) {
return false;
}
return ViewportHasDisplayPort(aFrame->PresContext());
}
-NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(ScrollbarThumbLayerized, bool)
-
-/* static */ void
-nsLayoutUtils::SetScrollbarThumbLayerization(nsIFrame* aThumbFrame, bool aLayerize)
-{
- aThumbFrame->SetProperty(ScrollbarThumbLayerized(), aLayerize);
-}
-
-bool
-nsLayoutUtils::IsScrollbarThumbLayerized(nsIFrame* aThumbFrame)
-{
- return aThumbFrame->GetProperty(ScrollbarThumbLayerized());
-}
-
// static
nsIScrollableFrame*
nsLayoutUtils::GetNearestScrollableFrameForDirection(nsIFrame* aFrame,
Direction aDirection)
{
NS_ASSERTION(aFrame, "GetNearestScrollableFrameForDirection expects a non-null frame");
for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
nsIScrollableFrame* scrollableFrame = do_QueryFrame(f);
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -595,28 +595,16 @@ public:
* Return true if aFrame is a fixed-pos frame and is a child of a viewport
* which has a displayport. These frames get special treatment from the compositor.
* aDisplayPort, if non-null, is set to the display port rectangle (relative to
* the viewport).
*/
static bool IsFixedPosFrameInDisplayPort(const nsIFrame* aFrame);
/**
- * Store whether aThumbFrame wants its own layer. This sets a property on
- * the frame.
- */
- static void SetScrollbarThumbLayerization(nsIFrame* aThumbFrame, bool aLayerize);
-
- /**
- * Returns whether aThumbFrame wants its own layer due to having called
- * SetScrollbarThumbLayerization.
- */
- static bool IsScrollbarThumbLayerized(nsIFrame* aThumbFrame);
-
- /**
* GetScrollableFrameFor returns the scrollable frame for a scrolled frame
*/
static nsIScrollableFrame* GetScrollableFrameFor(const nsIFrame *aScrolledFrame);
/**
* GetNearestScrollableFrameForDirection locates the first ancestor of
* aFrame (or aFrame itself) that is scrollable with overflow:scroll or
* overflow:auto in the given direction and where either the scrollbar for
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -891,16 +891,19 @@ public:
}
NS_IMETHOD PostScrolledAreaEventForCurrentArea() override {
mHelper.PostScrolledAreaEvent();
return NS_OK;
}
virtual bool IsScrollingActive(nsDisplayListBuilder* aBuilder) override {
return mHelper.IsScrollingActive(aBuilder);
}
+ virtual bool IsMaybeScrollingActive() const override {
+ return mHelper.IsMaybeScrollingActive();
+ }
virtual bool MayBeAsynchronouslyScrolled() override {
return mHelper.MayBeAsynchronouslyScrolled();
}
virtual bool IsProcessingAsyncScroll() override {
return mHelper.IsProcessingAsyncScroll();
}
virtual void ResetScrollPositionForLayerPixelAlignment() override {
mHelper.ResetScrollPositionForLayerPixelAlignment();
@@ -1329,16 +1332,19 @@ public:
}
NS_IMETHOD PostScrolledAreaEventForCurrentArea() override {
mHelper.PostScrolledAreaEvent();
return NS_OK;
}
virtual bool IsScrollingActive(nsDisplayListBuilder* aBuilder) override {
return mHelper.IsScrollingActive(aBuilder);
}
+ virtual bool IsMaybeScrollingActive() const override {
+ return mHelper.IsMaybeScrollingActive();
+ }
virtual bool MayBeAsynchronouslyScrolled() override {
return mHelper.MayBeAsynchronouslyScrolled();
}
virtual bool IsProcessingAsyncScroll() override {
return mHelper.IsProcessingAsyncScroll();
}
virtual void ResetScrollPositionForLayerPixelAlignment() override {
mHelper.ResetScrollPositionForLayerPixelAlignment();
--- a/layout/generic/nsIScrollableFrame.h
+++ b/layout/generic/nsIScrollableFrame.h
@@ -312,16 +312,22 @@ public:
/**
* Returns true if this scrollframe is being "actively scrolled".
* This basically means that we should allocate resources in the
* expectation that scrolling is going to happen.
*/
virtual bool IsScrollingActive(nsDisplayListBuilder* aBuilder) = 0;
/**
+ * Same as the above except doesn't take into account will-change budget,
+ * which means that it can be called during display list building.
+ */
+ virtual bool IsMaybeScrollingActive() const = 0;
+
+ /**
* Returns true if this scroll frame might be scrolled
* asynchronously by the compositor.
*/
virtual bool MayBeAsynchronouslyScrolled() = 0;
/**
* Returns true if the scrollframe is currently processing an async
* or smooth scroll.
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -78,16 +78,17 @@
#include "mozilla/GeckoRestyleManager.h"
#include "nsCaret.h"
#include "nsISelection.h"
#include "nsDOMTokenList.h"
#include "mozilla/RuleNodeCacheConditions.h"
#include "nsCSSProps.h"
#include "nsPluginFrame.h"
#include "nsSVGMaskFrame.h"
+#include "nsSliderFrame.h"
#include "nsTableCellFrame.h"
#include "nsTableColFrame.h"
#include "ClientLayerManager.h"
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/layers/WebRenderLayerManager.h"
#include "mozilla/layers/WebRenderMessages.h"
#include "mozilla/layers/WebRenderScrollData.h"
@@ -1648,17 +1649,18 @@ nsDisplayListBuilder::IsAnimatedGeometry
// for background-attachment:fixed elements.
return AGR_YES;
}
// Treat the slider thumb as being as an active scrolled root when it wants
// its own layer so that it can move without repainting.
if (parentType == LayoutFrameType::Slider) {
- if (nsLayoutUtils::IsScrollbarThumbLayerized(aFrame)) {
+ nsIScrollableFrame* sf = static_cast<nsSliderFrame*>(parent)->GetScrollFrame();
+ if (sf && sf->IsMaybeScrollingActive()) {
return AGR_YES;
}
result = AGR_MAYBE;
}
if (aFrame->StyleDisplay()->mPosition == NS_STYLE_POSITION_STICKY) {
if (IsStickyFrameActive(this, aFrame, parent)) {
return AGR_YES;
--- a/layout/xul/nsSliderFrame.cpp
+++ b/layout/xul/nsSliderFrame.cpp
@@ -374,17 +374,16 @@ nsSliderFrame::BuildDisplayListForChildr
// We do this here and not in the thumb's nsBoxFrame::BuildDisplayList so
// that the event region that gets created for the thumb is included in
// the nsDisplayOwnLayer contents.
uint32_t flags = aBuilder->GetCurrentScrollbarFlags();
mozilla::layers::FrameMetrics::ViewID scrollTargetId =
aBuilder->GetCurrentScrollbarTarget();
bool thumbGetsLayer = (scrollTargetId != layers::FrameMetrics::NULL_SCROLL_ID);
- nsLayoutUtils::SetScrollbarThumbLayerization(thumb, thumbGetsLayer);
if (thumbGetsLayer) {
MOZ_ASSERT((flags & nsDisplayOwnLayer::HORIZONTAL_SCROLLBAR) ||
(flags & nsDisplayOwnLayer::VERTICAL_SCROLLBAR));
bool isHorizontal = (flags & nsDisplayOwnLayer::HORIZONTAL_SCROLLBAR);
ScrollDirection scrollDirection = isHorizontal
? ScrollDirection::HORIZONTAL
: ScrollDirection::VERTICAL;
@@ -1067,16 +1066,32 @@ ScrollFrameWillBuildScrollInfoLayer(nsIF
if (UsesSVGEffects(current)) {
return true;
}
current = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(current);
}
return false;
}
+nsIScrollableFrame* nsSliderFrame::GetScrollFrame()
+{
+ nsIFrame* scrollbarBox = GetScrollbar();
+ if (!scrollbarBox) {
+ return nullptr;
+ }
+
+ nsContainerFrame* scrollFrame = scrollbarBox->GetParent();
+ if (!scrollFrame) {
+ return nullptr;
+ }
+
+ nsIScrollableFrame* scrollFrameAsScrollable = do_QueryFrame(scrollFrame);
+ return scrollFrameAsScrollable;
+}
+
void
nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent)
{
if (!aEvent->mFlags.mHandledByAPZ) {
return;
}
if (!gfxPlatform::GetPlatform()->SupportsApzDragInput()) {
--- a/layout/xul/nsSliderFrame.h
+++ b/layout/xul/nsSliderFrame.h
@@ -132,16 +132,19 @@ public:
// scrolled frame.
float GetThumbRatio() const;
// Notify the slider frame than an async scrollbar drag requested in
// StartAPZDrag() was rejected by APZ, and the slider frame should
// fall back to main-thread dragging.
void AsyncScrollbarDragRejected();
+ // Returns the associated scrollframe that contains this slider if any.
+ nsIScrollableFrame* GetScrollFrame();
+
bool OnlySystemGroupDispatch(mozilla::EventMessage aMessage) const override;
private:
bool GetScrollToClick();
nsIFrame* GetScrollbar();
bool ShouldScrollForEvent(mozilla::WidgetGUIEvent* aEvent);
bool ShouldScrollToClickForEvent(mozilla::WidgetGUIEvent* aEvent);