Bug 1349750 - Add an 'is async-draggable' flag to ScrollThumbData. r=kats
This flag is set to false if there are any conditions that only the main
thread knows about that prevent the thumb from being async-dragged.
MozReview-Commit-ID: Gl7f7bY0QnA
--- a/gfx/layers/LayerAttributes.h
+++ b/gfx/layers/LayerAttributes.h
@@ -17,36 +17,42 @@ template <typename T> struct ParamTraits
namespace mozilla {
namespace layers {
// Data stored for scroll thumb container layers.
struct ScrollThumbData {
ScrollThumbData()
: mDirection(ScrollDirection::NONE)
, mThumbRatio(0.0f)
+ , mIsAsyncDraggable(false)
{}
ScrollThumbData(ScrollDirection aDirection,
float aThumbRatio,
- CSSCoord aThumbLength)
+ CSSCoord aThumbLength,
+ bool aIsAsyncDraggable)
: mDirection(aDirection)
, mThumbRatio(aThumbRatio)
, mThumbLength(aThumbLength)
+ , mIsAsyncDraggable(aIsAsyncDraggable)
{}
ScrollDirection mDirection;
// The scrollbar thumb ratio is the ratio of the thumb position (in the CSS
// pixels of the scrollframe's parent's space) to the scroll position (in the
// CSS pixels of the scrollframe's space).
float mThumbRatio;
CSSCoord mThumbLength;
+ // Whether the scrollbar thumb can be dragged asynchronously.
+ bool mIsAsyncDraggable;
bool operator==(const ScrollThumbData& aOther) const {
return mDirection == aOther.mDirection &&
mThumbRatio == aOther.mThumbRatio &&
- mThumbLength == aOther.mThumbLength;
+ mThumbLength == aOther.mThumbLength &&
+ mIsAsyncDraggable == aOther.mIsAsyncDraggable;
}
bool operator!=(const ScrollThumbData& aOther) const {
return !(*this == aOther);
}
};
// Infrequently changing layer attributes that require no special
// serialization work.
--- a/layout/xul/nsSliderFrame.cpp
+++ b/layout/xul/nsSliderFrame.cpp
@@ -327,16 +327,31 @@ nsSliderFrame::BuildDisplayList(nsDispla
aLists.Outlines()->AppendNewToTop(new (aBuilder)
nsDisplayEventReceiver(aBuilder, this));
return;
}
nsBoxFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
}
+static bool
+UsesCustomScrollbarMediator(nsIFrame* scrollbarBox) {
+ if (nsScrollbarFrame* scrollbarFrame = do_QueryFrame(scrollbarBox)) {
+ if (nsIScrollbarMediator* mediator = scrollbarFrame->GetScrollbarMediator()) {
+ nsIScrollableFrame* scrollFrame = do_QueryFrame(mediator);
+ // The scrollbar mediator is not the scroll frame.
+ // That means this scroll frame has a custom scrollbar mediator.
+ if (!scrollFrame) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
void
nsSliderFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
// if we are too small to have a thumb don't paint it.
nsIFrame* thumb = nsBox::GetChildXULBox(this);
@@ -371,16 +386,19 @@ nsSliderFrame::BuildDisplayListForChildr
bool isHorizontal = (flags & nsDisplayOwnLayer::HORIZONTAL_SCROLLBAR);
ScrollDirection scrollDirection = isHorizontal
? ScrollDirection::HORIZONTAL
: ScrollDirection::VERTICAL;
const float appUnitsPerCss = float(AppUnitsPerCSSPixel());
CSSCoord thumbLength = NSAppUnitsToFloatPixels(
isHorizontal ? thumbRect.width : thumbRect.height, appUnitsPerCss);
+ nsIFrame* scrollbarBox = GetScrollbar();
+ bool isAsyncDraggable = !UsesCustomScrollbarMediator(scrollbarBox);
+
nsDisplayListBuilder::AutoContainerASRTracker contASRTracker(aBuilder);
nsDisplayListCollection tempLists;
nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, tempLists);
// This is a bit of a hack. Collect up all descendant display items
// and merge them into a single Content() list.
nsDisplayList masterList;
masterList.AppendToTop(tempLists.BorderBackground());
@@ -394,17 +412,18 @@ nsSliderFrame::BuildDisplayListForChildr
const ActiveScrolledRoot* ownLayerASR = contASRTracker.GetContainerASR();
DisplayListClipState::AutoSaveRestore ownLayerClipState(aBuilder);
ownLayerClipState.ClearUpToASR(ownLayerASR);
aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayOwnLayer(aBuilder, this, &masterList, ownLayerASR,
flags, scrollTargetId,
ScrollThumbData{scrollDirection,
GetThumbRatio(),
- thumbLength}));
+ thumbLength,
+ isAsyncDraggable}));
return;
}
}
nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists);
}
@@ -1031,29 +1050,20 @@ nsSliderFrame::StartAPZDrag(WidgetGUIEve
}
// APZ dragging requires the scrollbar to be layerized, which doesn't
// happen for scroll info layers.
if (ScrollFrameWillBuildScrollInfoLayer(scrollFrame)) {
return;
}
- nsScrollbarFrame* scrollbarFrame = do_QueryFrame(scrollbarBox);
- if (!scrollbarFrame) {
+ // Custom scrollbar mediators are not supported in the APZ codepath.
+ if (UsesCustomScrollbarMediator(scrollbarBox)) {
return;
}
- if (nsIScrollbarMediator* mediator = scrollbarFrame->GetScrollbarMediator()) {
- nsIScrollableFrame* scrollFrame = do_QueryFrame(mediator);
- // The scrollbar mediator is not the scroll frame.
- // That means this scroll frame has a custom scrollbar mediator.
- // That's not supported in the APZ codepath.
- if (!scrollFrame) {
- return;
- }
- }
bool isHorizontal = IsXULHorizontal();
mozilla::layers::FrameMetrics::ViewID scrollTargetId;
bool hasID = nsLayoutUtils::FindIDFor(scrollableContent, &scrollTargetId);
bool hasAPZView = hasID && (scrollTargetId != layers::FrameMetrics::NULL_SCROLL_ID);
if (!hasAPZView) {