Skip to content

Commit

Permalink
vt: Snapshot rect is containing block for ::view-transition
Browse files Browse the repository at this point in the history
The ::view-transition is positioned behind viewport-insetting UI such as
the mobile URL bar, RTL/left-side vertical scrollbars, and virtual
keyboards. The ::view-transition needs to have its size and position set
to match the "snapshot root rect"[0].

Currently this is achieved by directly setting the size and location on
the ::view-transition's style in the UA stylesheet. However, this comes
with several drawbacks:

 * Requires the main thread to perform an update to change the position.
   The mobile URL bar can animate in on the compositor thread without a
   Blink update.
 * Makes it difficult for authors to style ::view-transition themselves.
   E.g. to shift the transition they'd have to use getComputedStyle and
   add their own value, which could be overwritten by the UA.
 * Is visible to authors via getComputedStyle which could complicate
   making changes in this area in the future.

w3c/csswg-drafts#8070 resolved and specified
that the containing block of `::view-transition` should be the
snapshot root rect.

This CL removes replaces the styles on ::view-transition with
`position:fixed; inset: 0` and special cases the containing block for
the ::view-transition pseudo element to match the geometry of the
snapshot root rect.

[0] https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/renderer/core/view_transition/README.md#viewport-sizes

Bug: 1383980
Change-Id: Ie05de201dd3775717d4e231d08299471d68a2de4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4166263
Reviewed-by: Vladimir Levin <vmpstr@chromium.org>
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
Commit-Queue: David Bokan <bokan@chromium.org>
Reviewed-by: Khushal Sagar <khushalsagar@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1096264}
  • Loading branch information
bokand authored and Chromium LUCI CQ committed Jan 24, 2023
1 parent 7ecce5b commit 9ede207
Show file tree
Hide file tree
Showing 23 changed files with 348 additions and 291 deletions.
7 changes: 1 addition & 6 deletions third_party/blink/renderer/core/css/transition.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,7 @@

html::view-transition {
position: fixed;
top: 0;
left: 0;

/* Size will be set dynamically to correctly account for UI such as
virtual-keyboards */

inset: 0;
pointer-events: none;
}

Expand Down
1 change: 1 addition & 0 deletions third_party/blink/renderer/core/dom/document.cc
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@
#include "third_party/blink/renderer/core/timing/render_blocking_metrics_reporter.h"
#include "third_party/blink/renderer/core/timing/soft_navigation_heuristics.h"
#include "third_party/blink/renderer/core/trustedtypes/trusted_html.h"
#include "third_party/blink/renderer/core/view_transition/view_transition_supplement.h"
#include "third_party/blink/renderer/core/view_transition/view_transition_utils.h"
#include "third_party/blink/renderer/core/xml/parser/xml_document_parser.h"
#include "third_party/blink/renderer/core/xml_names.h"
Expand Down
1 change: 1 addition & 0 deletions third_party/blink/renderer/core/dom/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
#include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/core/trustedtypes/trusted_script.h"
#include "third_party/blink/renderer/core/view_transition/view_transition_supplement.h"
#include "third_party/blink/renderer/core/view_transition/view_transition_utils.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
Expand Down
4 changes: 2 additions & 2 deletions third_party/blink/renderer/core/layout/build.gni
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,6 @@ blink_core_sources_layout = [
"layout_custom_scrollbar_part.h",
"layout_deprecated_flexible_box.cc",
"layout_deprecated_flexible_box.h",
"layout_view_transition_content.cc",
"layout_view_transition_content.h",
"layout_embedded_content.cc",
"layout_embedded_content.h",
"layout_embedded_object.cc",
Expand Down Expand Up @@ -256,6 +254,8 @@ blink_core_sources_layout = [
"layout_video.h",
"layout_view.cc",
"layout_view.h",
"layout_view_transition_content.cc",
"layout_view_transition_content.h",
"layout_word_break.cc",
"layout_word_break.h",
"line/abstract_inline_text_box.cc",
Expand Down
9 changes: 4 additions & 5 deletions third_party/blink/renderer/core/layout/layout_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -602,14 +602,13 @@ PhysicalRect LayoutView::ViewRect() const {

// This adjustment should always be an expansion of the current
// viewport.
DCHECK_GE(transition->GetSnapshotViewportRect().width(),
DCHECK_GE(transition->GetSnapshotRootSize().width(),
frame_view_->Size().width());
DCHECK_GE(transition->GetSnapshotViewportRect().height(),
DCHECK_GE(transition->GetSnapshotRootSize().height(),
frame_view_->Size().height());

return PhysicalRect(
PhysicalOffset(),
PhysicalSize(transition->GetSnapshotViewportRect().size()));
return PhysicalRect(PhysicalOffset(),
PhysicalSize(transition->GetSnapshotRootSize()));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "third_party/blink/renderer/core/layout/anchor_scroll_data.h"
#include "third_party/blink/renderer/core/layout/deferred_shaping.h"
#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_flexible_box.h"
Expand All @@ -33,6 +34,7 @@
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/view_transition/view_transition_utils.h"
#include "third_party/blink/renderer/platform/heap/collection_support/clear_collection_scope.h"

namespace blink {
Expand Down Expand Up @@ -504,6 +506,34 @@ NGOutOfFlowLayoutPart::GetContainingBlockInfo(
container_builder_->FragmentBlockSize()});
}

// The ::view-transition element is special in that its containing block is
// the "snapshot root" rect, rather than a viewport or parent box:
// https://drafts.csswg.org/css-view-transitions-1/#selectordef-view-transition.
DCHECK(candidate.box);
if (ViewTransitionUtils::IsViewTransitionRoot(*candidate.box)) {
DCHECK(container_object->IsLayoutView());
const ViewTransition* transition =
ViewTransitionUtils::GetActiveTransition(candidate.box->GetDocument());
DCHECK(transition);

PhysicalRect physical_snapshot_root_in_frame(
PhysicalOffset(transition->GetFrameToSnapshotRootOffset()),
PhysicalSize(transition->GetSnapshotRootSize()));

WritingDirectionMode writing_direction =
ConstraintSpace().GetWritingDirection();
LogicalSize outer_size = container_builder_->Size();
WritingModeConverter converter(writing_direction, outer_size);

NGOutOfFlowLayoutPart::ContainingBlockInfo containing_block_for_snapshot;
containing_block_for_snapshot.rect =
converter.ToLogical(physical_snapshot_root_in_frame);

containing_block_for_snapshot.writing_direction = writing_direction;

return containing_block_for_snapshot;
}

return node_style.GetPosition() == EPosition::kAbsolute
? default_containing_block_info_for_absolute_
: default_containing_block_info_for_fixed_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,7 @@ gfx::Size PaintLayerScrollableArea::PixelSnappedContentsSize(
if (auto* transition = ViewTransitionUtils::GetActiveTransition(
GetLayoutBox()->GetDocument());
transition && transition->IsRootTransitioning()) {
PhysicalSize container_size(transition->GetSnapshotViewportRect().size());
PhysicalSize container_size(transition->GetSnapshotRootSize());
size.width = std::max(container_size.width, size.width);
size.height = std::max(container_size.height, size.height);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2905,20 +2905,21 @@ void FragmentPaintPropertyTreeBuilder::UpdatePaintOffset() {
// up and left to be at the origin "as-if all viewport-insetting UI were
// hidden". This is done so that the transition container is stable across
// navigations where the state of such UI can change (e.g. URL bar hidden ->
// shown). Offset painting of all other content so that it paints at the
// fixed viewport origin rather than behind the UI. Non-root transitions
// paint at their layer's origin and the layer is positioned with this offset
// included.
// shown). Offset painting of all other content so that it appears at its
// original location on the screen. Non-root transitions paint at their
// layer's origin and the layer is positioned with this offset included.
Document& document = object_.GetDocument();
ViewTransition* transition =
ViewTransitionUtils::GetActiveTransition(document);
PseudoElement* view_transition_pseudo =
ViewTransitionUtils::GetRootPseudo(document);

// We may have a transition but not yet have setup the pseudo element tree.
// This can happen in view-transition-on-navigation where a transition is
// created waiting for rendering to unblock but pre-paint can still be
// triggered in this state.
DCHECK(!view_transition_pseudo || transition);

if (view_transition_pseudo && transition->IsRootTransitioning()) {
DCHECK(document.documentElement());
DCHECK(view_transition_pseudo->GetLayoutObject());
Expand All @@ -2929,8 +2930,12 @@ void FragmentPaintPropertyTreeBuilder::UpdatePaintOffset() {
bool is_view_transition_pseudo =
object_.GetNode() == view_transition_pseudo;
if (is_child_of_root && !is_view_transition_pseudo) {
// Frame scrollbars belong to the frame so page content (children of the
// LayoutView) already has a paint offset from any left-side vertical
// scrollbar. Thus, offset by snapshot-root-to-frame (rather than to
// fixed-viewport) so we don't apply the scrollbar offset a second time.
PhysicalOffset offset =
PhysicalOffset(transition->GetRootSnapshotPaintOffset());
-PhysicalOffset(transition->GetFrameToSnapshotRootOffset());
context_.current.paint_offset += offset;
context_.absolute_position.paint_offset += offset;
context_.fixed_position.paint_offset += offset;
Expand Down
26 changes: 13 additions & 13 deletions third_party/blink/renderer/core/view_transition/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ transition to a document shrunken by the URL bar. Other examples of UI widgets
like this are the virtual-keyboard and root scrollbars.

Viewport widgets inset the "fixed viewport" so to avoid a moving coordinate
space we introduce the concept of a "snapshot viewport". The snapshot viewport
is invariant with respect to whether viewport widgets are shown or not, neither
space we introduce the concept of a "snapshot root" rect. The snapshot root is
invariant with respect to whether viewport widgets are shown or not, neither
its position nor its size change. When all widgets are hidden, it is equal to
the fixed viewport.

Expand All @@ -132,7 +132,7 @@ the fixed viewport.
│ │ │ │ │ │
│ │ │ │ │ │
│ <PAGE CONTENT> │ │ Fixed Viewport │ │ │
│ │ │ │ │ Snapshot Viewport
│ │ │ │ │ Snapshot Root
│ │ │ │ │ │
│ │ │ │ │ │
├┬────────────────────┬┤ └───────────────────────┘ │ │
Expand All @@ -142,18 +142,18 @@ the fixed viewport.
│┼────────────────────┼│ │ │
└──────────────────────┘ └────────────────────┘
```
_The snapshot and fixed viewports when the mobile URL bar and virtual keyboard
are shown._
_The snapshot root and fixed viewport when the mobile URL bar and virtual
keyboard are shown._

The root ::view-transition pseudo is shifted up and left so that its origin is
at the snapshot viewport origin. This is a no-op if no viewport widgets are
hidden. If the widgets are showing this causes ::view-transition to be
positioned at a negative offset relative to the fixed viewport (i.e. it's origin
is underneath the mobile URL bar). This creates a stable coordinate space during
the transition. Transition elements' viewport transforms account for this and
are computed relative to the snapshot viewport origin.

The root snapshot is sized to the snapshot viewport's size, which may be larger
at the snapshot root origin. This is a no-op if viewport widgets aren't showing.
If the widgets are showing this causes ::view-transition to be positioned at a
negative offset relative to the fixed viewport (i.e. it's origin is underneath
the mobile URL bar). This creates a stable coordinate space during the
transition. Transition element's viewport transforms account for this and are
computed relative to the snapshot root origin.

The root snapshot is sized to the snapshot root's size, which may be larger
than the current fixed viewport. Painting is offset within the snapshot so that
page content is rendered at the correct location (i.e. the snapshot will paint
the background color in the region overlaid by the URL bar).
Expand Down
1 change: 1 addition & 0 deletions third_party/blink/renderer/core/view_transition/build.gni
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ blink_core_sources_view_transition = [
"view_transition_style_tracker.h",
"view_transition_supplement.cc",
"view_transition_supplement.h",
"view_transition_utils.cc",
"view_transition_utils.h",
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -915,18 +915,18 @@ void ViewTransition::WillCommitCompositorFrame() {
PauseRendering();
}

gfx::Rect ViewTransition::GetSnapshotViewportRect() const {
gfx::Size ViewTransition::GetSnapshotRootSize() const {
if (!style_tracker_)
return gfx::Rect();
return gfx::Size();

return style_tracker_->GetSnapshotViewportRect();
return style_tracker_->GetSnapshotRootSize();
}

gfx::Vector2d ViewTransition::GetRootSnapshotPaintOffset() const {
gfx::Vector2d ViewTransition::GetFrameToSnapshotRootOffset() const {
if (!style_tracker_)
return gfx::Vector2d();

return style_tracker_->GetRootSnapshotPaintOffset();
return style_tracker_->GetFrameToSnapshotRootOffset();
}

void ViewTransition::PauseRendering() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ class CORE_EXPORT ViewTransition : public ScriptWrappable,

// In physical pixels. See comments on equivalent methods in
// ViewTransitionStyleTracker for info.
gfx::Rect GetSnapshotViewportRect() const;
gfx::Vector2d GetRootSnapshotPaintOffset() const;
gfx::Size GetSnapshotRootSize() const;
gfx::Vector2d GetFrameToSnapshotRootOffset() const;

bool IsDone() const { return IsTerminalState(state_); }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
namespace blink {
namespace {

const char* kViewTransitionTagName = "html::view-transition";
const char* kGroupTagName = "html::view-transition-group";
const char* kImagePairTagName = "html::view-transition-image-pair";
const char* kNewImageTagName = "html::view-transition-new";
Expand Down Expand Up @@ -152,24 +151,4 @@ void ViewTransitionStyleBuilder::AddContainerStyles(
AddContainerStyles(tag, rule_builder.ReleaseString());
}

void ViewTransitionStyleBuilder::AddRootStyles(
const gfx::RectF& snapshot_viewport_rect_css) {
builder_.Append(kViewTransitionTagName);
builder_.Append("{ ");
builder_.AppendFormat(
R"CSS(
width: %.3fpx;
height: %.3fpx;
)CSS",
snapshot_viewport_rect_css.width(), snapshot_viewport_rect_css.height());
if (!snapshot_viewport_rect_css.OffsetFromOrigin().IsZero()) {
builder_.AppendFormat(
R"CSS(
transform: translate(%.3fpx, %.3fpx);
)CSS",
snapshot_viewport_rect_css.x(), snapshot_viewport_rect_css.y());
}
builder_.Append(" }");
}

} // namespace blink
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ class ViewTransitionStyleBuilder {
const ContainerProperties& properties,
WritingMode writing_mode);

void AddRootStyles(const gfx::RectF& snapshot_viewport_rect_css);

String Build();

private:
Expand Down

0 comments on commit 9ede207

Please sign in to comment.