Commit 93b6e358 authored by Chris Harrelson's avatar Chris Harrelson Committed by Commit Bot

[Display Locking] Stop delivering resize observations for locked elements.

When a locked element becomes unlocked, it will compare its size before
locking with the one after unlocking.

Bug:964055

Change-Id: Ic9c32a68411e2ad5d7c9aaec4aeeb424cace044f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1860597
Commit-Queue: Chris Harrelson <chrishtr@chromium.org>
Reviewed-by: default avatarvmpstr <vmpstr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#706574}
parent 87de6626
...@@ -471,6 +471,9 @@ void DisplayLockContext::StartCommit() { ...@@ -471,6 +471,9 @@ void DisplayLockContext::StartCommit() {
layout_object->SetNeedsLayoutAndPrefWidthsRecalc( layout_object->SetNeedsLayoutAndPrefWidthsRecalc(
layout_invalidation_reason::kDisplayLock); layout_invalidation_reason::kDisplayLock);
if (auto* view = layout_object->GetFrameView())
view->SetNeedsForcedResizeObservations();
} }
void DisplayLockContext::StartUpdateIfNeeded() { void DisplayLockContext::StartUpdateIfNeeded() {
......
...@@ -2093,6 +2093,12 @@ void LocalFrameView::ScheduleVisualUpdateForPaintInvalidationIfNeeded() { ...@@ -2093,6 +2093,12 @@ void LocalFrameView::ScheduleVisualUpdateForPaintInvalidationIfNeeded() {
// phase of this cycle. // phase of this cycle.
} }
void LocalFrameView::SetNeedsForcedResizeObservations() {
if (auto* controller =
GetFrame().GetDocument()->GetResizeObserverController())
controller->SetNeedsForcedResizeObservations();
}
void LocalFrameView::NotifyResizeObservers() { void LocalFrameView::NotifyResizeObservers() {
TRACE_EVENT0("blink,benchmark", "LocalFrameView::NotifyResizeObservers"); TRACE_EVENT0("blink,benchmark", "LocalFrameView::NotifyResizeObservers");
// Controller exists only if ResizeObserver was created. // Controller exists only if ResizeObserver was created.
......
...@@ -686,6 +686,10 @@ class CORE_EXPORT LocalFrameView final ...@@ -686,6 +686,10 @@ class CORE_EXPORT LocalFrameView final
void RegisterForLifecycleNotifications(LifecycleNotificationObserver*); void RegisterForLifecycleNotifications(LifecycleNotificationObserver*);
void UnregisterFromLifecycleNotifications(LifecycleNotificationObserver*); void UnregisterFromLifecycleNotifications(LifecycleNotificationObserver*);
// Sets whether all ResizeObservers should check all their ResizeObservations
// for a resize. This is needed when exiting a display lock.
void SetNeedsForcedResizeObservations();
protected: protected:
void FrameRectsChanged(const IntRect&) override; void FrameRectsChanged(const IntRect&) override;
void SelfVisibleChanged() override; void SelfVisibleChanged() override;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/resize_observer/resize_observation.h" #include "third_party/blink/renderer/core/resize_observer/resize_observation.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/layout/layout_box.h" #include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer.h" #include "third_party/blink/renderer/core/resize_observer/resize_observer.h"
#include "third_party/blink/renderer/core/svg/svg_element.h" #include "third_party/blink/renderer/core/svg/svg_element.h"
...@@ -21,11 +22,26 @@ ResizeObservation::ResizeObservation(Element* target, ResizeObserver* observer) ...@@ -21,11 +22,26 @@ ResizeObservation::ResizeObservation(Element* target, ResizeObserver* observer)
} }
bool ResizeObservation::ObservationSizeOutOfSync() { bool ResizeObservation::ObservationSizeOutOfSync() {
return element_size_changed_ && observation_size_ != ComputeTargetSize(); if (!element_size_changed_ || observation_size_ == ComputeTargetSize())
return false;
// Skip resize observations on locked elements.
if (UNLIKELY(
DisplayLockUtilities::IsInLockedSubtreeCrossingFrames(*target_))) {
return false;
}
return true;
} }
void ResizeObservation::SetObservationSize(const LayoutSize& observation_size) { void ResizeObservation::SetObservationSize(const LayoutSize& observation_size) {
observation_size_ = observation_size; observation_size_ = observation_size;
// Don't clear the dirty bit while locked. This allows us to make sure to
// compare sizes when becoming unlocked.
if (UNLIKELY(DisplayLockUtilities::IsInLockedSubtreeCrossingFrames(*target_)))
return;
element_size_changed_ = false; element_size_changed_ = false;
} }
......
...@@ -27,6 +27,14 @@ size_t ResizeObserverController::GatherObservations(size_t deeper_than) { ...@@ -27,6 +27,14 @@ size_t ResizeObserverController::GatherObservations(size_t deeper_than) {
return shallowest; return shallowest;
} }
void ResizeObserverController::SetNeedsForcedResizeObservations() {
for (auto& observer : observers_) {
// Set ElementSizeChanged as a way of forcing the observer to check all
// observations.
observer->ElementSizeChanged();
}
}
bool ResizeObserverController::SkippedObservations() { bool ResizeObserverController::SkippedObservations() {
for (auto& observer : observers_) { for (auto& observer : observers_) {
if (observer->SkippedObservations()) if (observer->SkippedObservations())
......
...@@ -37,6 +37,8 @@ class ResizeObserverController final ...@@ -37,6 +37,8 @@ class ResizeObserverController final
void ClearObservations(); void ClearObservations();
void ObserverChanged() { observers_changed_ = true; } void ObserverChanged() { observers_changed_ = true; }
void SetNeedsForcedResizeObservations();
void Trace(blink::Visitor*); void Trace(blink::Visitor*);
// For testing only. // For testing only.
......
<!doctype HTML>
<html>
<meta charset="utf8">
<title>Display Locking: locked attribute</title>
<link rel="author" title="Chris Harrelson" href="mailto:chrishtr@chromium.org">
<link rel="help" href="https://github.com/WICG/display-locking">
<div id="container">
<div id="resize" style="width: 50px; height: 50px">
</div>
</div>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/utils.js"></script>
<script>
async_test((t) => {
let didCallback = false;
async function runTest() {
let resizeCallback = function (entries) {
didCallback = true;
}
let resizeObserver = new ResizeObserver(resizeCallback);
resizeObserver.observe(resize);
requestAnimationFrame(step2);
}
async function step2() {
assert_equals(true, didCallback, 'Resize observation should happen in first frame after registering');
didCallback = false;
const container = document.getElementById("container");
await setInvisible(container);
// Change the size of #resize. This should cause a resize observation, but
// only when the element becomes unlocked.
resize.style.width = '100px';
requestAnimationFrame(step3);
}
async function step3() {
assert_equals(false, didCallback,
'ResizeObsever should not run during updateRendering while also invisible');
await container.updateRendering();
requestAnimationFrame(step4);
}
async function step4() {
assert_equals(false, didCallback,
'ResizeObsever should not run while invisible');
await setVisible(container);
requestAnimationFrame(step5);
}
async function step5() {
assert_equals(true, didCallback,
'ResizeObsevers should now run once becoming visible');
t.done();
}
window.onload = function() {
requestAnimationFrame(() => requestAnimationFrame(runTest));
};
}, "ResizeObserver skipped while locked");
</script>
</html>
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