Skip to content

Commit

Permalink
VT: Viewport resizes skip transition
Browse files Browse the repository at this point in the history
Bug: 1404957
Change-Id: I19d1a2fd6666f22c4d107baa79756835b02e1373
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4189934
Reviewed-by: Vladimir Levin <vmpstr@chromium.org>
Reviewed-by: Khushal Sagar <khushalsagar@chromium.org>
Commit-Queue: David Bokan <bokan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1096452}
  • Loading branch information
bokand authored and Chromium LUCI CQ committed Jan 24, 2023
1 parent 5da23fa commit 8868108
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 0 deletions.
Expand Up @@ -526,6 +526,9 @@ void ViewTransition::ProcessCurrentState() {
MakeUnwrappingCrossThreadHandle(this)))));

if (document_->GetFrame()->IsLocalRoot()) {
// We need to ensure commits aren't deferred since we rely on commits
// to send directives to the compositor and initiate pause of
// rendering after one frame.
document_->GetPage()->GetChromeClient().StopDeferringCommits(
*document_->GetFrame(),
cc::PaintHoldingCommitTrigger::kViewTransition);
Expand Down
Expand Up @@ -187,6 +187,7 @@ ViewTransitionStyleTracker::ViewTransitionStyleTracker(

// TODO(khushalsagar): We should keep track of the snapshot viewport rect
// size to handle changes in its bounds.
// https://crbug.com/1404957.
continue;
}

Expand Down Expand Up @@ -492,6 +493,9 @@ bool ViewTransitionStyleTracker::Capture() {
set_element_sequence_id_ = 0;
pending_transition_element_names_.clear();

DCHECK(!snapshot_root_size_at_capture_.has_value());
snapshot_root_size_at_capture_ = GetSnapshotRootSize();

return true;
}

Expand Down Expand Up @@ -806,6 +810,10 @@ bool ViewTransitionStyleTracker::RunPostPrePaintSteps() {
needs_style_invalidation = true;
}

if (SnapshotRootDidChangeSize()) {
return false;
}

for (auto& entry : element_data_map_) {
auto& element_data = entry.value;
if (!element_data->target_element)
Expand Down Expand Up @@ -1495,4 +1503,25 @@ PhysicalRect ViewTransitionStyleTracker::ComputeVisualOverflowRect(
return result;
}

bool ViewTransitionStyleTracker::SnapshotRootDidChangeSize() const {
if (!snapshot_root_size_at_capture_.has_value()) {
return false;
}

gfx::Size current_size = GetSnapshotRootSize();

// Allow 1px of diff since the snapshot root can be adjusted by
// viewport-resizing UI (e.g. the virtual keyboard insets the viewport but
// then outsets the viewport rect to get the snapshot root). These
// adjustments can be off by a pixel due to different pixel snapping.
if (std::abs(snapshot_root_size_at_capture_->width() -
current_size.width()) <= 1 &&
std::abs(snapshot_root_size_at_capture_->height() -
current_size.height()) <= 1) {
return false;
}

return true;
}

} // namespace blink
Expand Up @@ -273,6 +273,8 @@ class ViewTransitionStyleTracker
LayoutBoxModelObject& box,
LayoutBoxModelObject* ancestor = nullptr);

bool SnapshotRootDidChangeSize() const;

Member<Document> document_;

// Indicates which step during the transition we're currently at.
Expand All @@ -288,6 +290,15 @@ class ViewTransitionStyleTracker
// transition.
int captured_name_count_ = 0;

// Tracks the size of the snapshot root rect that was used to generate
// snapshots. If the snapshot root changes size at any point in the
// transition the transition will be aborted. For SPA transitions, this will
// be empty until the kCapturing phase. For a cross-document transition, this
// will be initialized from the cached state at creation but is currently
// unset.
// TODO(bokan): Implement for cross-document transitions. crbug.com/1404957.
absl::optional<gfx::Size> snapshot_root_size_at_capture_;

// Map of the CSS |view-transition-name| property to state for that tag.
HeapHashMap<AtomicString, Member<ElementData>> element_data_map_;

Expand Down
@@ -0,0 +1,76 @@
<!DOCTYPE html>
<html>
<head>
<title>View transitions: Resizing viewport skips the transition</title>
<link rel="help" href="https://github.com/WICG/view-transitions">
<link rel="author" href="mailto:bokan@chromium.org">

<script src="/common/rendering-utils.js"></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>

<script>
function waitForAtLeastOneFrame(win) {
return new Promise(resolve => {
win.requestAnimationFrame(() => {
win.requestAnimationFrame(() => {
resolve();
});
});
});
}

let popupWin;
promise_test(async t => {
assert_implements(document.startViewTransition, "Missing document.startViewTransition");

return new Promise(async (resolve, reject) => {
await waitForAtLeastOneFrame(window);

// Open a popup window that we'll use to start a transition
await test_driver.bless('Open a popup in a new window', () => {
popupWin = window.open('about:blank', 'popup', 'width=300,height=300');
});
let popupDoc = popupWin.document;
popupDoc.documentElement.innerHTML = `
<style>
html {background-color: red;}
html.new {background-color: limegreen;}
/* Set a no-op animation to show the old snapshot indefinitely. */
html::view-transition-group(*) {animation-duration: 10s;}
html::view-transition-new(*) {animation: unset;opacity: 0;}
html::view-transition-old(*) {animation-duration: 10s;opacity: 1;}
</style>`;

// Start a transition inside the popup.
let transition = popupDoc.startViewTransition(() => {
popupDoc.documentElement.classList.add('new');
});

let finishResolved = false;
transition.finished.then(() => {
finishResolved = true;
});

// Wait for the transition to start animating.
await transition.ready;
await waitForAtLeastOneFrame(popupWin);
await waitForAtLeastOneFrame(popupWin);

// Resize the popup window.
popupWin.resizeTo(popupWin.innerWidth/2, popupWin.innerHeight/2);

await waitForAtLeastOneFrame(popupWin);

// `finish` should have resolved as resizing the transition after capture
// should cause it to skip.
assert_true(finishResolved, "Transition must be finished by the window resize");
resolve();
});
});
</script>
</head>
</html>

0 comments on commit 8868108

Please sign in to comment.