blob: 001fddbcc06456a46152ba76a7e32c3facb7735d [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/container_query_scroll_snapshot.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/paint/object_paint_properties.h"
namespace blink {
ContainerQueryScrollSnapshot::ContainerQueryScrollSnapshot(Element& container)
: ScrollSnapshotClient(container.GetDocument().GetFrame()),
container_(container) {}
bool ContainerQueryScrollSnapshot::UpdateStuckState() {
ContainerStuckPhysical stuck_horizontal = ContainerStuckPhysical::kNo;
ContainerStuckPhysical stuck_vertical = ContainerStuckPhysical::kNo;
LayoutBoxModelObject* layout_object =
DynamicTo<LayoutBoxModelObject>(container_->GetLayoutObject());
if (layout_object && layout_object->IsStickyPositioned()) {
PhysicalOffset sticky_offset = layout_object->StickyPositionOffset();
if (sticky_offset.left > 0) {
stuck_horizontal = ContainerStuckPhysical::kLeft;
} else if (sticky_offset.left < 0) {
stuck_horizontal = ContainerStuckPhysical::kRight;
}
if (sticky_offset.top > 0) {
stuck_vertical = ContainerStuckPhysical::kTop;
} else if (sticky_offset.top < 0) {
stuck_vertical = ContainerStuckPhysical::kBottom;
}
}
std::swap(stuck_horizontal_, stuck_horizontal);
std::swap(stuck_vertical_, stuck_vertical);
if (stuck_horizontal_ != stuck_horizontal ||
stuck_vertical_ != stuck_vertical) {
// TODO(crbug.com/1445189): The kLocalStyleChange is not necessary for the
// container itself, but it is a way to reach reach ApplyScrollSnapshot() in
// Element::RecalcOwnStyle() for the next lifecycle update.
container_->SetNeedsStyleRecalc(kLocalStyleChange,
StyleChangeReasonForTracing::Create(
style_change_reason::kScrollTimeline));
return true;
}
return false;
}
void ContainerQueryScrollSnapshot::UpdateSnapshot() {
UpdateStuckState();
}
bool ContainerQueryScrollSnapshot::ValidateSnapshot() {
if (UpdateStuckState()) {
return false;
}
return true;
}
bool ContainerQueryScrollSnapshot::ShouldScheduleNextService() {
return false;
}
void ContainerQueryScrollSnapshot::Trace(Visitor* visitor) const {
visitor->Trace(container_);
ScrollSnapshotClient::Trace(visitor);
}
} // namespace blink