Commit 2cc471f8 authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Chromium LUCI CQ

Clip layout shift tracking rect by visual viewport rect

When mobile viewport is enabled, we have two viewports: the visual
(inner) viewport and the layout (outer) viewport. The clip of the
visible viewport is not in the paint property tree, so we need to
apply the clip separately. The clip was mistakenly removed in
crrev.com/824480.

Also fix a bug before crrev.com/824480: the current scroll offset
of the visual viewport was not considered when applying the visual
viewport clip, which caused invisible shifts reported and visible
shifts not reported.

Bug: 1141739
Change-Id: I425718b1fdfb2689a7f2948c561101d0b476eb7f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2593180
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: default avatarSteve Kobes <skobes@chromium.org>
Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#837853}
parent 0d5712a4
......@@ -12,8 +12,16 @@ the case.
[Source code for this change](https://chromium-review.googlesource.com/c/chromium/src/+/2591367)
### Ignore layout shift under opacity:0
[Source code for this change](https://chromium-review.googlesource.com/c/chromium/src/+/2591907)
### Clip layout shift rect by visual viewport
On user agents supporting mobile viewport, the actual visual viewport may be
smaller than the layout viewport. Now layout shifts out of the visual viewport
are ignored.
[Source code for this change](https://chromium-review.googlesource.com/c/chromium/src/+/2593180)
## How does this affect a site's metrics?
All of these changes only affect sites with specific types of content. Here are
......@@ -29,6 +37,12 @@ their Cumulative Layout Shift scores.
Sites using opacity:0 to hide layout changes should see a decrease in their
Cumulative Layout Shift scores.
### Clip layout shift rect by visual viewport
Sites may see a decrease in their Cumulative Layout Shift scores on user agents
supporting mobile viewport when the visual viewport is smaller than the layout
viewport.
## When were users affected?
Chrome 89 is currently scheduled to be released the week of March 2, 2021.
......@@ -5,6 +5,7 @@ This is a list of changes to [Cumulative Layout Shift](https://web.dev/cls).
* Chrome 89
* Metric definition improvement: [Ignore layout shift when visibility:hidden becomes visible](2020_12_cls.md)
* Metric definition improvement: [Ignore layout shift under opacity:0](2020_12_cls.md)
* Metric definition improvement: [Clip layout shift rect by visual viewport](2020_12_cls.md)
* Chrome 88
* Metric definition improvement: [Cumulative layout shift properly detects shifts of fixed position elements](2020_11_cls.md)
* Metric definition improvement: [Cumulative layout shift properly detects shifts of descendents of a sticky element](2020_11_cls.md)
......
......@@ -141,7 +141,7 @@ LayoutShiftTracker::LayoutShiftTracker(LocalFrameView* frame_view)
// This eliminates noise from the private Page object created by
// SVGImage::DataChanged.
is_active_(
!frame_view_->GetFrame().GetChromeClient().IsSVGImageChromeClient()),
!frame_view->GetFrame().GetChromeClient().IsSVGImageChromeClient()),
score_(0.0),
weighted_score_(0.0),
timer_(frame_view->GetFrame().GetTaskRunner(TaskType::kInternalDefault),
......@@ -225,6 +225,11 @@ void LayoutShiftTracker::ObjectShifted(
object.View()->FirstFragment().LocalBorderBoxProperties();
FloatClipRect clip_rect =
GeometryMapper::LocalToAncestorClipRect(property_tree_state, root_state);
if (frame_view_->GetFrame().IsMainFrame()) {
// Apply the visual viewport clip.
clip_rect.Intersect(FloatClipRect(
frame_view_->GetPage()->GetVisualViewport().VisibleRect()));
}
// If the clip region is empty, then the resulting layout shift isn't visible
// in the viewport so ignore it.
......
......@@ -6,6 +6,7 @@
#include "third_party/blink/public/common/input/web_mouse_event.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/svg_names.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
......@@ -585,4 +586,41 @@ TEST_F(LayoutShiftTrackerTest, NestedFixedPos) {
EXPECT_FLOAT_EQ(0, GetLayoutShiftTracker().Score());
}
TEST_F(LayoutShiftTrackerTest, ClipByVisualViewport) {
SetHtmlInnerHTML(R"HTML(
<meta name="viewport" content="width=200, initial-scale=2">
<style>
#target {
position: absolute;
top: 0;
left: 150px;
width: 200px;
height: 200px;
}
</style>
<div id=target></div>
)HTML");
GetDocument().GetPage()->GetVisualViewport().SetSize(IntSize(200, 500));
GetDocument().GetPage()->GetVisualViewport().SetLocation(FloatPoint(0, 100));
UpdateAllLifecyclePhasesForTest();
// The visual viewport.
EXPECT_EQ(IntRect(0, 100, 200, 500),
GetDocument().View()->GetScrollableArea()->VisibleContentRect());
// The layout viewport .
EXPECT_EQ(IntRect(0, 0, 800, 600),
GetDocument().View()->LayoutViewport()->VisibleContentRect());
EXPECT_FLOAT_EQ(0, GetLayoutShiftTracker().Score());
GetDocument().getElementById("target")->setAttribute(html_names::kStyleAttr,
"top: 100px");
UpdateAllLifecyclePhasesForTest();
// 50.0: visible width
// 100.0 + 100.0: visible height + vertical shift
// 200.0 * 500.0: visual viewport area
// 100.0 / 500.0: shift distance fraction
EXPECT_FLOAT_EQ(50.0 * (100.0 + 100.0) / (200.0 * 500.0) * (100.0 / 500.0),
GetLayoutShiftTracker().Score());
}
} // namespace blink
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