зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
dace885161
Коммит
34ba90e714
|
@ -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;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче