Bug 1618432 - Move the root horizontal scrollbar in response to the dynamic toolbar transitions. r=botond

Differential Revision: https://phabricator.services.mozilla.com/D64726

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Hiroyuki Ikezoe 2020-03-03 05:33:54 +00:00
Родитель dace885161
Коммит 34ba90e714
9 изменённых файлов: 122 добавлений и 8 удалений

Просмотреть файл

@ -151,6 +151,12 @@ struct APZCTreeManager::TreeBuildingState {
// position animation id (which indicates that they need to be sampled for
// WebRender on the sampler thread).
std::vector<HitTestingTreeNode*> mFixedPositionNodesWithAnimationId;
// This is populated with all the HitTestingTreeNodes that are scrollbar
// containers for the root viewport and have a scrollthumb animation id
// (which indicates that they need to be sampled for WebRender on the sampler
// thread).
std::vector<HitTestingTreeNode*> mRootScrollbars;
};
class APZCTreeManager::CheckerboardFlushObserver : public nsIObserver {
@ -469,9 +475,15 @@ APZCTreeManager::UpdateHitTestingTreeImpl(const ScrollNode& aRoot,
// Note also that when webrender is enabled, a "valid" animation id
// is always nonzero, so we don't need to worry about handling the
// case where WR is enabled and the animation id is zero.
if (node->IsScrollThumbNode() && node->GetScrollbarAnimationId()) {
state.mScrollThumbs.push_back(node);
if (node->GetScrollbarAnimationId()) {
if (node->IsScrollThumbNode()) {
state.mScrollThumbs.push_back(node);
} else if (node->IsScrollbarContainerNode()) {
// Only scrollbar containers for the root have an animation id.
state.mRootScrollbars.push_back(node);
}
}
// GetFixedPositionAnimationId is only set when webrender is enabled.
if (node->GetFixedPositionAnimationId().isSome()) {
state.mFixedPositionNodesWithAnimationId.push_back(node);
@ -622,6 +634,16 @@ APZCTreeManager::UpdateHitTestingTreeImpl(const ScrollNode& aRoot,
target->IsAncestorOf(thumb));
}
mRootScrollbarInfo.clear();
// For non-webrender, and platforms without a dynamic toolbar,
// state.mRootScrollbarsWithAnimationId will be empty so this will be a
// no-op.
for (const HitTestingTreeNode* scrollbar : state.mRootScrollbars) {
MOZ_ASSERT(scrollbar->IsScrollbarContainerNode());
mRootScrollbarInfo.emplace_back(*(scrollbar->GetScrollbarAnimationId()),
scrollbar->GetScrollbarDirection());
}
mFixedPositionInfo.clear();
// For non-webrender, state.mFixedPositionNodesWithAnimationId will be empty
// so this will be a no-op.
@ -785,6 +807,23 @@ void APZCTreeManager::SampleForWebRender(wr::TransactionWrapper& aTxn,
wr::ToWrTransformProperty(info.mThumbAnimationId, transform));
}
// Move the root scrollbar in response to the dynamic toolbar transition.
for (const RootScrollbarInfo& info : mRootScrollbarInfo) {
// We only care about the horizontal scrollbar.
if (info.mScrollDirection == ScrollDirection::eHorizontal) {
ScreenPoint translation =
AsyncCompositionManager::ComputeFixedMarginsOffset(
mCompositorFixedLayerMargins, SideBits::eBottom, ScreenMargin());
LayerToParentLayerMatrix4x4 transform =
LayerToParentLayerMatrix4x4::Translation(ViewAs<ParentLayerPixel>(
translation, PixelCastJustification::ScreenIsParentLayerForRoot));
transforms.AppendElement(
wr::ToWrTransformProperty(info.mScrollbarAnimationId, transform));
}
}
for (const FixedPositionInfo& info : mFixedPositionInfo) {
ScreenPoint translation =
AsyncCompositionManager::ComputeFixedMarginsOffset(

Просмотреть файл

@ -793,7 +793,8 @@ class APZCTreeManager : public IAPZCTreeManager, public APZInputBridge {
*/
bool mUsingAsyncZoomContainer;
/** A lock that protects mApzcMap, mScrollThumbInfo, and mFixedPositionInfo.
/** A lock that protects mApzcMap, mScrollThumbInfo, mRootScrollbarInfo, and
* mFixedPositionInfo.
*/
mutable mozilla::Mutex mMapLock;
/**
@ -845,6 +846,32 @@ class APZCTreeManager : public IAPZCTreeManager, public APZInputBridge {
*/
std::vector<ScrollThumbInfo> mScrollThumbInfo;
/**
* A helper structure to store all the information needed to compute the
* async transform for a scrollthumb on the sampler thread.
*/
struct RootScrollbarInfo {
uint64_t mScrollbarAnimationId;
ScrollDirection mScrollDirection;
RootScrollbarInfo(const uint64_t& aScrollbarAnimationId,
const ScrollDirection aScrollDirection)
: mScrollbarAnimationId(aScrollbarAnimationId),
mScrollDirection(aScrollDirection) {}
};
/**
* If this APZCTreeManager is being used with WebRender, this vector gets
* populated during a layers update. It holds a package of information needed
* to compute and set the async transforms on root scrollbars. This
* information is extracted from the HitTestingTreeNodes for the WebRender
* case because accessing the HitTestingTreeNodes requires holding the tree
* lock which we cannot do on the WR sampler thread. mRootScrollbarInfo,
* however, can be accessed while just holding the mMapLock which is safe to
* do on the sampler thread.
* mMapLock must be acquired while accessing or modifying mRootScrollbarInfo.
*/
std::vector<RootScrollbarInfo> mRootScrollbarInfo;
/**
* A helper structure to store all the information needed to compute the
* async transform for a fixed position element on the sampler thread.

Просмотреть файл

@ -117,6 +117,11 @@ bool HitTestingTreeNode::IsScrollbarNode() const {
return mScrollbarData.mScrollbarLayerType != layers::ScrollbarLayerType::None;
}
bool HitTestingTreeNode::IsScrollbarContainerNode() const {
return mScrollbarData.mScrollbarLayerType ==
layers::ScrollbarLayerType::Container;
}
ScrollDirection HitTestingTreeNode::GetScrollbarDirection() const {
MOZ_ASSERT(IsScrollbarNode());
MOZ_ASSERT(mScrollbarData.mDirection.isSome());

Просмотреть файл

@ -116,6 +116,7 @@ class HitTestingTreeNode {
const ScrollbarData& aScrollbarData);
bool MatchesScrollDragMetrics(const AsyncDragMetrics& aDragMetrics) const;
bool IsScrollbarNode() const; // Scroll thumb or scrollbar container layer.
bool IsScrollbarContainerNode() const; // Scrollbar container layer.
// This can only be called if IsScrollbarNode() is true
ScrollDirection GetScrollbarDirection() const;
bool IsScrollThumbNode() const; // Scroll thumb container layer.

Просмотреть файл

@ -74,6 +74,11 @@ gfx::CoordTyped<TargetUnits> ViewAs(const gfx::CoordTyped<SourceUnits>& aCoord,
return gfx::CoordTyped<TargetUnits>(aCoord.value);
}
template <class TargetUnits, class SourceUnits>
gfx::IntCoordTyped<TargetUnits> ViewAs(
const gfx::IntCoordTyped<SourceUnits>& aCoord, PixelCastJustification) {
return gfx::IntCoordTyped<TargetUnits>(aCoord.value);
}
template <class TargetUnits, class SourceUnits>
gfx::SizeTyped<TargetUnits> ViewAs(const gfx::SizeTyped<SourceUnits>& aSize,
PixelCastJustification) {
return gfx::SizeTyped<TargetUnits>(aSize.width, aSize.height);

Просмотреть файл

@ -3165,7 +3165,8 @@ void ScrollFrameHelper::AppendScrollPartsTo(nsDisplayListBuilder* aBuilder,
// viewport scrollbars. They would create layerization problems. This wouldn't
// normally be an issue but themes can add overflow areas to scrollbar parts.
if (mIsRoot) {
nsRect scrollPartsClip(aBuilder->ToReferenceFrame(mOuter), TrueOuterSize());
nsRect scrollPartsClip(aBuilder->ToReferenceFrame(mOuter),
TrueOuterSize(aBuilder));
clipState.ClipContentDescendants(scrollPartsClip);
}
@ -5770,11 +5771,26 @@ class MOZ_RAII AutoMinimumScaleSizeChangeDetector final {
bool mPreviousIsUsingMinimumScaleSize;
};
nsSize ScrollFrameHelper::TrueOuterSize() const {
nsSize ScrollFrameHelper::TrueOuterSize(nsDisplayListBuilder* aBuilder) const {
if (RefPtr<MobileViewportManager> manager =
mOuter->PresShell()->GetMobileViewportManager()) {
LayoutDeviceIntSize displaySize = manager->DisplaySize();
MOZ_ASSERT(aBuilder);
// In case of WebRender, we expand the outer size to include the dynamic
// toolbar area here.
// In case of non WebRender, we expand the size dynamically in
// MoveScrollbarForLayerMargin in AsyncCompositionManager.cpp.
LayerManager* layerManager = aBuilder->GetWidgetLayerManager();
if (layerManager &&
layerManager->GetBackendType() == layers::LayersBackend::LAYERS_WR) {
displaySize.height += ViewAs<LayoutDevicePixel>(
mOuter->PresContext()->GetDynamicToolbarMaxHeight(),
PixelCastJustification::LayoutDeviceIsScreenForBounds);
}
return LayoutDeviceSize::ToAppUnits(
manager->DisplaySize(), mOuter->PresContext()->AppUnitsPerDevPixel());
displaySize, mOuter->PresContext()->AppUnitsPerDevPixel());
}
return mOuter->GetSize();
}

Просмотреть файл

@ -518,7 +518,7 @@ class ScrollFrameHelper : public nsIReflowCallback {
// This is mOuter->GetSize(), except when mOuter has been sized to reflect
// a virtual (layout) viewport in which case this returns the outer size
// used to size the physical (visual) viewport.
nsSize TrueOuterSize() const;
nsSize TrueOuterSize(nsDisplayListBuilder* aBuilder) const;
already_AddRefed<Element> MakeScrollbar(dom::NodeInfo* aNodeInfo,
bool aVertical,

Просмотреть файл

@ -6917,6 +6917,17 @@ bool nsDisplayOwnLayer::IsScrollbarContainer() const {
layers::ScrollbarLayerType::Container;
}
bool nsDisplayOwnLayer::IsRootScrollbarContainerWithDynamicToolbar() const {
if (!IsScrollbarContainer()) {
return false;
}
return mFrame->PresContext()->IsRootContentDocumentCrossProcess() &&
mFrame->PresContext()->HasDynamicToolbar() &&
mScrollbarData.mTargetViewId ==
nsLayoutUtils::ScrollIdForRootScrollFrame(mFrame->PresContext());
}
bool nsDisplayOwnLayer::IsZoomingLayer() const {
return GetType() == DisplayItemType::TYPE_ASYNC_ZOOM;
}
@ -6952,7 +6963,8 @@ bool nsDisplayOwnLayer::CreateWebRenderCommands(
Maybe<wr::WrAnimationProperty> prop;
bool needsProp =
aManager->LayerManager()->AsyncPanZoomEnabled() &&
(IsScrollThumbLayer() || IsZoomingLayer() || IsFixedPositionLayer());
(IsScrollThumbLayer() || IsZoomingLayer() || IsFixedPositionLayer() ||
IsRootScrollbarContainerWithDynamicToolbar());
if (needsProp) {
// APZ is enabled and this is a scroll thumb or zooming layer, so we need
@ -7010,7 +7022,15 @@ bool nsDisplayOwnLayer::UpdateScrollData(
return true;
}
MOZ_ASSERT(IsScrollbarContainer() || IsScrollThumbLayer());
aLayerData->SetScrollbarData(mScrollbarData);
if (IsRootScrollbarContainerWithDynamicToolbar()) {
aLayerData->SetScrollbarAnimationId(mWrAnimationId);
return true;
}
if (IsScrollThumbLayer()) {
aLayerData->SetScrollbarAnimationId(mWrAnimationId);
LayoutDeviceRect bounds = LayoutDeviceIntRect::FromAppUnits(

Просмотреть файл

@ -6115,6 +6115,7 @@ class nsDisplayOwnLayer : public nsDisplayWrapList {
nsDisplayOwnLayerFlags GetFlags() { return mFlags; }
bool IsScrollThumbLayer() const;
bool IsScrollbarContainer() const;
bool IsRootScrollbarContainerWithDynamicToolbar() const;
bool IsZoomingLayer() const;
bool IsFixedPositionLayer() const;