Commit bf232410 authored by David Bokan's avatar David Bokan Committed by Commit Bot

[BlinkGenPropertyTrees] Implement pos:fixed URL bar adjustment

This CL implements the "viewport bounds delta" for position: fixed
elements. When the URL bar is hidden, the renderer is only resized
when the user finishes scrolling. This means that while the scroll
is on-going and the URL bar is hiding, the renderer is actually
smaller than the visible area - we're revealing new content outside
the renderer's bounds.

Since position: fixed elements are positioned relative to the top-
left corner of a layer, a bottom-fixed element would appear to
detach from the bottom of the screen and move upwards as the URL
bar hides. CC uses some slight-of-hand to prevent this by adding a
"viewport bounds delta" to the scrolling and clipping bounds of the
viewport layers. This allows the newly revealed content to be seen
and keeps bottom-fixed elements static until the renderer itself is
resized and the bounds delta can be cleared.

This CL does the following things:

1) Update Blink to set the correct paint property tree state on
bottom-fixed objects so that the bounds delta is correctly applied
to them.

2) Modify the compositor to apply the bounds delta to the property
trees directly, rather than using layers which may no longer exist
in BGPT mode

3) Explicitly clamp the scroll offset on pending tree activation.
LayerTreeHostImplTest, ClampingAfterActivation was failing after
the early return was added to UpdateViewportContainerSizes. We
were relying on the viewport scroll anchor to clamp the scroll
offsets. Better to do this explicitly.

The marked test is currently crashing but tests this behavior. I've
confirmed that ignoring the crash causes the test to fail as
expected and applying this patch fixes it.

TEST=virtual/android/url-bar/bottom-fixed-adjusted-when-showing-url-bar.html

Bug: 850135
Cq-Include-Trybots: luci.chromium.try:linux-blink-gen-property-trees;luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_layout_tests_slimming_paint_v2;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I3a2da2648b47c2ccc0baf2876da12c228213dbe6
Reviewed-on: https://chromium-review.googlesource.com/1173441
Commit-Queue: David Bokan <bokan@chromium.org>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#583398}
parent 1e9a4629
......@@ -273,6 +273,8 @@ class CC_EXPORT LayerImpl {
// Viewport bounds delta are only used for viewport layers and account for
// changes in the viewport layers from browser controls and page scale
// factors. These deltas are only set on the active tree.
// TODO(bokan): These methods should be unneeded now that LTHI sets these
// directly on the property trees.
void SetViewportBoundsDelta(const gfx::Vector2dF& bounds_delta);
gfx::Vector2dF ViewportBoundsDelta() const;
......@@ -530,6 +532,8 @@ class CC_EXPORT LayerImpl {
bool hit_testable_without_draws_content_ : 1;
bool is_resized_by_browser_controls_ : 1;
// TODO(bokan): This can likely be removed after blink-gen-property-trees
// is shipped. https://crbug.com/836884.
static_assert(LAST_VIEWPORT_LAYER_TYPE < (1u << 3),
"enough bits for ViewportLayerType (viewport_layer_type_)");
uint8_t viewport_layer_type_ : 3; // ViewportLayerType
......
......@@ -65,6 +65,7 @@
#include "cc/tiles/picture_layer_tiling.h"
#include "cc/tiles/raster_tile_priority_queue.h"
#include "cc/tiles/software_image_decode_cache.h"
#include "cc/trees/clip_node.h"
#include "cc/trees/damage_tracker.h"
#include "cc/trees/debug_rect_history.h"
#include "cc/trees/draw_property_utils.h"
......@@ -2449,17 +2450,9 @@ void LayerTreeHostImpl::DidNotProduceFrame(const viz::BeginFrameAck& ack) {
}
void LayerTreeHostImpl::UpdateViewportContainerSizes() {
// TODO(bokan): Make URL-bar bounds deltas work with Blink-generated property
// trees. https://crbug.com/850135.
if (!InnerViewportScrollNode())
return;
LayerImpl* inner_container = active_tree_->InnerViewportContainerLayer();
LayerImpl* outer_container = active_tree_->OuterViewportContainerLayer();
if (!inner_container)
return;
ViewportAnchor anchor(InnerViewportScrollNode(), OuterViewportScrollLayer(),
active_tree_.get());
......@@ -2481,20 +2474,57 @@ void LayerTreeHostImpl::UpdateViewportContainerSizes() {
// Adjust the viewport layers by shrinking/expanding the container to account
// for changes in the size (e.g. browser controls) since the last resize from
// Blink.
gfx::Vector2dF amount_to_expand(0.f, delta_from_top_controls);
inner_container->SetViewportBoundsDelta(amount_to_expand);
if (outer_container && !outer_container->BoundsForScrolling().IsEmpty()) {
// Adjust the outer viewport container as well, since adjusting only the
// inner may cause its bounds to exceed those of the outer, causing scroll
// clamping.
gfx::Vector2dF amount_to_expand_scaled = gfx::ScaleVector2d(
amount_to_expand, 1.f / active_tree_->min_page_scale_factor());
outer_container->SetViewportBoundsDelta(amount_to_expand_scaled);
InnerViewportScrollLayer()->SetViewportBoundsDelta(amount_to_expand_scaled);
auto* property_trees = active_tree_->property_trees();
gfx::Vector2dF inner_bounds_delta(0.f, delta_from_top_controls);
if (property_trees->inner_viewport_container_bounds_delta() ==
inner_bounds_delta)
return;
property_trees->SetInnerViewportContainerBoundsDelta(inner_bounds_delta);
ClipNode* inner_clip_node = property_trees->clip_tree.Node(
InnerViewportScrollLayer()->clip_tree_index());
inner_clip_node->clip.set_height(
InnerViewportScrollNode()->container_bounds.height() +
inner_bounds_delta.y());
// Adjust the outer viewport container as well, since adjusting only the
// inner may cause its bounds to exceed those of the outer, causing scroll
// clamping.
if (OuterViewportScrollNode()) {
gfx::Vector2dF outer_bounds_delta = gfx::ScaleVector2d(
inner_bounds_delta, 1.f / active_tree_->min_page_scale_factor());
property_trees->SetOuterViewportContainerBoundsDelta(outer_bounds_delta);
property_trees->SetInnerViewportScrollBoundsDelta(outer_bounds_delta);
ClipNode* outer_clip_node = property_trees->clip_tree.Node(
OuterViewportScrollLayer()->clip_tree_index());
outer_clip_node->clip.set_height(
OuterViewportScrollNode()->container_bounds.height() +
outer_bounds_delta.y());
anchor.ResetViewportToAnchoredPosition();
}
property_trees->clip_tree.set_needs_update(true);
property_trees->full_tree_damaged = true;
active_tree_->set_needs_update_draw_properties();
// Viewport scrollbar positions are determined using the viewport bounds
// delta.
active_tree_->SetScrollbarGeometriesNeedUpdate();
active_tree_->set_needs_update_draw_properties();
// For pre-BlinkGenPropertyTrees mode, we need to ensure the layers are
// appropriately updated.
if (!settings().use_layer_lists) {
if (OuterViewportContainerLayer())
OuterViewportContainerLayer()->NoteLayerPropertyChanged();
if (InnerViewportScrollLayer())
InnerViewportScrollLayer()->NoteLayerPropertyChanged();
if (OuterViewportScrollLayer())
OuterViewportScrollLayer()->NoteLayerPropertyChanged();
}
}
void LayerTreeHostImpl::SynchronouslyInitializeAllTiles() {
......@@ -2778,6 +2808,16 @@ void LayerTreeHostImpl::ActivateSyncTree() {
}
UpdateViewportContainerSizes();
if (InnerViewportScrollNode()) {
active_tree_->property_trees()->scroll_tree.ClampScrollToMaxScrollOffset(
InnerViewportScrollNode(), active_tree_.get());
}
if (OuterViewportScrollNode()) {
active_tree_->property_trees()->scroll_tree.ClampScrollToMaxScrollOffset(
OuterViewportScrollNode(), active_tree_.get());
}
active_tree_->DidBecomeActive();
client_->RenewTreePriority();
......
......@@ -154,16 +154,23 @@ crbug.com/861824 virtual/threaded/fast/animationworklet/animation-worklet-inside
# These scrollbar tests should pass.
Bug(none) virtual/prefer_compositing_to_lcd_text/scrollbars/ [ Pass ]
crbug.com/836912 compositing/rtl/rtl-absolute-overflow.html [ Failure ]
crbug.com/836912 compositing/rtl/rtl-and-writing-mode-scrolling.html [ Failure ]
crbug.com/836912 compositing/rtl/rtl-fixed-overflow.html [ Failure ]
crbug.com/836912 compositing/rtl/rtl-iframe-absolute-overflow.html [ Failure ]
crbug.com/836912 compositing/rtl/rtl-iframe-fixed-overflow.html [ Failure ]
crbug.com/836912 compositing/rtl/rtl-overflow-invalidation.html [ Failure ]
crbug.com/836912 compositing/scrollbars/nested-overlay-scrollbars.html [ Failure ]
crbug.com/836912 compositing/squashing/vertical-writing-mode-squashed.html [ Failure ]
crbug.com/836890 compositing/rtl/rtl-absolute-overflow.html [ Failure ]
crbug.com/836890 compositing/rtl/rtl-and-writing-mode-scrolling.html [ Failure ]
crbug.com/836890 compositing/rtl/rtl-fixed-overflow.html [ Failure ]
crbug.com/836890 compositing/rtl/rtl-iframe-absolute-overflow.html [ Failure ]
crbug.com/836890 compositing/rtl/rtl-iframe-fixed-overflow.html [ Failure ]
crbug.com/836890 compositing/rtl/rtl-overflow-invalidation.html [ Failure ]
crbug.com/836890 compositing/rtl/rtl-absolute-overflow-scrolled.html [ Failure ]
crbug.com/836890 fast/dom/rtl-scroll-to-leftmost-and-resize.html [ Failure ]
crbug.com/836890 fast/events/wheel/wheelevent-in-horizontal-scrollbar-in-rtl.html [ Failure ]
crbug.com/836890 fast/events/wheel/wheelevent-in-vertical-scrollbar-in-rtl.html [ Failure ]
crbug.com/836890 paint/invalidation/scroll/document-flipped-blocks-writing-mode-scroll.html [ Failure ]
crbug.com/836890 virtual/user-activation-v2/fast/events/wheel/wheelevent-in-horizontal-scrollbar-in-rtl.html [ Failure ]
crbug.com/836890 virtual/user-activation-v2/fast/events/wheel/wheelevent-in-vertical-scrollbar-in-rtl.html [ Failure ]
crbug.com/836890 compositing/squashing/vertical-writing-mode-squashed.html [ Failure ]
crbug.com/836890 paint/overflow/composited-scroll-vertical-rl.html [ Failure ]
crbug.com/836912 compositing/squashing/no-squashing-into-another-clip-layer.html [ Pass Failure ]
crbug.com/836912 paint/overflow/composited-scroll-vertical-rl.html [ Failure ]
crbug.com/836912 compositing/scrollbars/nested-overlay-scrollbars.html [ Failure ]
# These scrolling tests should pass.
Bug(none) virtual/threaded/ [ Pass ]
......
......@@ -339,6 +339,11 @@ void FragmentPaintPropertyTreeBuilder::UpdatePaintOffsetTranslation(
paint_offset_translation->Y());
state.flattens_inherited_transform =
context_.current.should_flatten_inherited_transform;
state.affected_by_outer_viewport_bounds_delta =
object_.Style()->GetPosition() == EPosition::kFixed &&
!object_.Style()->Bottom().IsAuto();
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled())
state.rendering_context_id = context_.current.rendering_context_id;
......
......@@ -105,6 +105,10 @@ void PropertyTreeManager::SetupRootClipNode() {
DCHECK_EQ(clip_node.id, kSecondaryRootNodeId);
clip_node.clip_type = cc::ClipNode::ClipType::APPLIES_LOCAL_CLIP;
// TODO(bokan): This needs to come from the Visual Viewport which will
// correctly account for the URL bar. In fact, the visual viewport property
// tree builder should probably be the one to create the property tree state
// and have this created in the same way as other layers.
clip_node.clip = gfx::RectF(
gfx::SizeF(root_layer_->layer_tree_host()->device_viewport_size()));
clip_node.transform_id = kRealRootNodeId;
......@@ -179,6 +183,11 @@ int PropertyTreeManager::EnsureCompositorTransformNode(
transform_node->FlattensInheritedTransform();
compositor_node.sorting_context_id = transform_node->RenderingContextId();
if (transform_node->IsAffectedByOuterViewportBoundsDelta()) {
compositor_node.moved_by_outer_viewport_bounds_delta_y = true;
GetTransformTree().AddNodeAffectedByOuterViewportBoundsDelta(id);
}
CompositorElementId compositor_element_id =
transform_node->GetCompositorElementId();
if (compositor_element_id) {
......
......@@ -49,6 +49,7 @@ class PLATFORM_EXPORT TransformPaintPropertyNode
CompositingReasons direct_compositing_reasons = CompositingReason::kNone;
CompositorElementId compositor_element_id;
scoped_refptr<const ScrollPaintPropertyNode> scroll;
bool affected_by_outer_viewport_bounds_delta = false;
bool operator==(const State& o) const {
return matrix == o.matrix && origin == o.origin &&
......@@ -57,7 +58,9 @@ class PLATFORM_EXPORT TransformPaintPropertyNode
rendering_context_id == o.rendering_context_id &&
direct_compositing_reasons == o.direct_compositing_reasons &&
compositor_element_id == o.compositor_element_id &&
scroll == o.scroll;
scroll == o.scroll &&
affected_by_outer_viewport_bounds_delta ==
o.affected_by_outer_viewport_bounds_delta;
}
};
......@@ -97,6 +100,13 @@ class PLATFORM_EXPORT TransformPaintPropertyNode
return state_.scroll.get();
}
// If true, this node is translated by the viewport bounds delta, which is
// used to keep bottom-fixed elements appear fixed to the bottom of the
// screen in the presence of URL bar movement.
bool IsAffectedByOuterViewportBoundsDelta() const {
return state_.affected_by_outer_viewport_bounds_delta;
}
// If this is a scroll offset translation (i.e., has an associated scroll
// node), returns this. Otherwise, returns the transform node that this node
// scrolls with respect to. This can require a full ancestor traversal.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment