Skip to content

Commit

Permalink
Support parsing of @container state(snapped)
Browse files Browse the repository at this point in the history
- Support parsing of @container selectors with snapped queries.
- Add MediaValues for the snapped state, but never set to anything but
  kNone.
- FindContainer takes snapped queries into account.
- Re-use same depends-on flag for both snapped and stuck state queries.
  That means invalidation for sticky container changes will invalidate
  snap-query-dependent descendants and vice versa.

Bug: 1475231
Change-Id: If2b934aa8574e8eea932d0de8221eb98d19fb833
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4810069
Reviewed-by: Anders Hartvoll Ruud <andruud@chromium.org>
Commit-Queue: Rune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1188266}
  • Loading branch information
Rune Lillesveen authored and Chromium LUCI CQ committed Aug 25, 2023
1 parent de5c068 commit c7781f2
Show file tree
Hide file tree
Showing 26 changed files with 312 additions and 69 deletions.
2 changes: 1 addition & 1 deletion third_party/blink/renderer/core/css/build.gni
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ blink_core_sources_css = [
"container_query_scroll_snapshot.h",
"container_selector.cc",
"container_selector.h",
"container_stuck.h",
"container_state.h",
"style_containment_scope.cc",
"style_containment_scope.h",
"style_containment_scope_tree.cc",
Expand Down
14 changes: 7 additions & 7 deletions third_party/blink/renderer/core/css/container_query_evaluator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ bool ContainerQueryEvaluator::EvalAndAdd(
const ContainerSelector& selector = query.Selector();
bool selects_size = selector.SelectsSizeContainers();
bool selects_style = selector.SelectsStyleContainers();
bool selects_sticky = selector.SelectsStickyContainers();
if (!selects_size && !selects_style && !selects_sticky) {
bool selects_state = selector.SelectsStateContainers();
if (!selects_size && !selects_style && !selects_state) {
return false;
}

Expand All @@ -149,8 +149,8 @@ bool ContainerQueryEvaluator::EvalAndAdd(
if (selects_style) {
match_result.SetDependsOnStyleContainerQueries();
}
if (selects_sticky) {
match_result.SetDependsOnStickyContainerQueries();
if (selects_state) {
match_result.SetDependsOnStateContainerQueries();
}

Element* starting_element =
Expand Down Expand Up @@ -250,9 +250,9 @@ bool ContainerQueryEvaluator::EvalAndAdd(const ContainerQuery& query,
if (!depends_on_style_) {
depends_on_style_ = query.Selector().SelectsStyleContainers();
}
if (!depends_on_sticky_) {
depends_on_sticky_ = query.Selector().SelectsStickyContainers();
if (depends_on_sticky_ && !snapshot_) {
if (!depends_on_state_) {
depends_on_state_ = query.Selector().SelectsStateContainers();
if (depends_on_state_ && !snapshot_) {
CHECK(media_query_evaluator_);
Element* container_element =
media_query_evaluator_->GetMediaValues().ContainerElement();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/container_selector.h"
#include "third_party/blink/renderer/core/css/container_stuck.h"
#include "third_party/blink/renderer/core/css/container_state.h"
#include "third_party/blink/renderer/core/css/media_query_evaluator.h"
#include "third_party/blink/renderer/core/css/media_query_exp.h"
#include "third_party/blink/renderer/core/css/style_recalc_change.h"
Expand Down Expand Up @@ -156,7 +156,7 @@ class CORE_EXPORT ContainerQueryEvaluator final
bool referenced_by_unit_ = false;
bool font_dirty_ = false;
bool depends_on_style_ = false;
bool depends_on_sticky_ = false;
bool depends_on_state_ = false;
};

} // namespace blink
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,50 @@ TEST_F(ContainerQueryEvaluatorTest, FindStickyContainer) {
sticky_size);
}

TEST_F(ContainerQueryEvaluatorTest, FindSnapContainer) {
SetBodyInnerHTML(R"HTML(
<div style="container-type: sticky snap">
<div style="container-name:outer;container-type: snap">
<div style="container-name:outer">
<div style="container-type: snap">
<div>
<div></div>
</div>
</div>
</div>
</div>
</div>
)HTML");

UpdateAllLifecyclePhasesForTest();

Element* sticky_snap = GetDocument().body()->firstElementChild();
Element* outer_snap = sticky_snap->firstElementChild();
Element* outer = outer_snap->firstElementChild();
Element* inner_snap = outer->firstElementChild();
Element* inner = inner_snap->firstElementChild();

EXPECT_EQ(ContainerQueryEvaluator::FindContainer(
inner,
ParseContainer("state(snapped: inline) and style(--foo: bar)")
->Selector(),
&GetDocument()),
inner_snap);
EXPECT_EQ(
ContainerQueryEvaluator::FindContainer(
inner,
ParseContainer("outer state(snapped: block) and style(--foo: bar)")
->Selector(),
&GetDocument()),
outer_snap);
EXPECT_EQ(ContainerQueryEvaluator::FindContainer(
inner,
ParseContainer("state((snapped: none) and (stuck: bottom))")
->Selector(),
&GetDocument()),
sticky_snap);
}

TEST_F(ContainerQueryEvaluatorTest, ScopedCaching) {
GetDocument()
.documentElement()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CONTAINER_QUERY_SCROLL_SNAPSHOT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CONTAINER_QUERY_SCROLL_SNAPSHOT_H_

#include "third_party/blink/renderer/core/css/container_stuck.h"
#include "third_party/blink/renderer/core/css/container_state.h"
#include "third_party/blink/renderer/core/scroll/scroll_snapshot_client.h"
#include "third_party/blink/renderer/platform/heap/member.h"

Expand Down
8 changes: 7 additions & 1 deletion third_party/blink/renderer/core/css/container_selector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,12 @@ ContainerSelector::ContainerSelector(AtomicString name,
if (feature_flags & MediaQueryExpNode::kFeatureStyle) {
has_style_query_ = true;
}
if (feature_flags & MediaQueryExpNode::kFeatureState) {
if (feature_flags & MediaQueryExpNode::kFeatureSticky) {
has_sticky_query_ = true;
}
if (feature_flags & MediaQueryExpNode::kFeatureSnap) {
has_snap_query_ = true;
}
if (feature_flags & MediaQueryExpNode::kFeatureUnknown) {
has_unknown_feature_ = true;
}
Expand Down Expand Up @@ -61,6 +64,9 @@ unsigned ContainerSelector::Type(WritingMode writing_mode) const {
if (has_sticky_query_) {
type |= kContainerTypeSticky;
}
if (has_snap_query_) {
type |= kContainerTypeSnap;
}
return type;
}

Expand Down
8 changes: 7 additions & 1 deletion third_party/blink/renderer/core/css/container_selector.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ class CORE_EXPORT ContainerSelector {
return (name_ == o.name_) && (physical_axes_ == o.physical_axes_) &&
(logical_axes_ == o.logical_axes_) &&
(has_style_query_ == o.has_style_query_) &&
(has_sticky_query_ == o.has_sticky_query_);
(has_sticky_query_ == o.has_sticky_query_) &&
(has_snap_query_ == o.has_snap_query_);
}
bool operator!=(const ContainerSelector& o) const { return !(*this == o); }

Expand All @@ -65,6 +66,10 @@ class CORE_EXPORT ContainerSelector {

bool SelectsStyleContainers() const { return has_style_query_; }
bool SelectsStickyContainers() const { return has_sticky_query_; }
bool SelectsSnapContainers() const { return has_snap_query_; }
bool SelectsStateContainers() const {
return SelectsStickyContainers() || SelectsSnapContainers();
}
bool HasUnknownFeature() const { return has_unknown_feature_; }

PhysicalAxes GetPhysicalAxes() const { return physical_axes_; }
Expand All @@ -76,6 +81,7 @@ class CORE_EXPORT ContainerSelector {
LogicalAxes logical_axes_{kLogicalAxisNone};
bool has_style_query_{false};
bool has_sticky_query_{false};
bool has_snap_query_{false};
bool has_unknown_feature_{false};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CONTAINER_STUCK_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CONTAINER_STUCK_H_
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CONTAINER_STATE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CONTAINER_STATE_H_

namespace blink {

// Enum classes that represents whether a sticky positioned element is stuck to
// a scroll container edge for a given axis. Used for evaluating stuck state
Expand Down Expand Up @@ -36,4 +38,16 @@ inline ContainerStuckLogical Flip(ContainerStuckLogical stuck) {
}
}

#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CONTAINER_STUCK_H_
// Flags that represent whether a scroll-snapped query container is snapped to
// its scroll container in a given direction.
enum class ContainerSnapped {
kNone = 0,
kBlock = 1 << 0,
kInline = 1 << 1,
};

using ContainerSnappedFlags = unsigned;

} // namespace blink

#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CONTAINER_STATE_H_
6 changes: 6 additions & 0 deletions third_party/blink/renderer/core/css/css_container_values.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class CORE_EXPORT CSSContainerValues : public MediaValuesDynamic {
}
ContainerStuckLogical StuckInline() const override;
ContainerStuckLogical StuckBlock() const override;
ContainerSnappedFlags SnappedFlags() const override { return snapped_; }

private:
// The current computed style for the container.
Expand All @@ -70,6 +71,11 @@ class CORE_EXPORT CSSContainerValues : public MediaValuesDynamic {
ContainerStuckPhysical stuck_horizontal_ = ContainerStuckPhysical::kNo;
// Whether a sticky container is vertically stuck and against which edge.
ContainerStuckPhysical stuck_vertical_ = ContainerStuckPhysical::kNo;
// Union of flags for whether a scroll-snapped container is snapped in block
// or inline directions.
// TODO(crbug.com/1475231): Need to update this from the scroll snapshot.
ContainerSnappedFlags snapped_ =
static_cast<ContainerSnappedFlags>(ContainerSnapped::kNone);
// Container font sizes for resolving relative lengths.
CSSToLengthConversionData::FontSizes font_sizes_;
// LineHeightSize of the container element.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ void ElementRuleCollector::CollectMatchingRulesForListInternal(
result_.SetDependsOnStyleContainerQueries();
}
if (selects_sticky) {
result_.SetDependsOnStickyContainerQueries();
result_.SetDependsOnStateContainerQueries();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"device-posture",
"horizontal-viewport-segments",
"vertical-viewport-segments",
"snapped",
"stuck",
"inverted-colors",
],
Expand Down
22 changes: 20 additions & 2 deletions third_party/blink/renderer/core/css/media_query_evaluator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1459,8 +1459,7 @@ static bool StuckMediaFeatureEval(const MediaQueryExpValue& value,
MediaQueryOperator op,
const MediaValues& media_values) {
if (!value.IsValid()) {
return media_values.StuckHorizontal() != ContainerStuckPhysical::kNo ||
media_values.StuckVertical() != ContainerStuckPhysical::kNo;
return media_values.Stuck();
}

switch (value.Id()) {
Expand Down Expand Up @@ -1489,6 +1488,25 @@ static bool StuckMediaFeatureEval(const MediaQueryExpValue& value,
}
}

static bool SnappedMediaFeatureEval(const MediaQueryExpValue& value,
MediaQueryOperator op,
const MediaValues& media_values) {
if (!value.IsValid()) {
return media_values.Snapped();
}
switch (value.Id()) {
case CSSValueID::kNone:
return media_values.Snapped();
case CSSValueID::kBlock:
return media_values.SnappedBlock();
case CSSValueID::kInline:
return media_values.SnappedInline();
default:
NOTREACHED();
return false;
}
}

static bool InvertedColorsMediaFeatureEval(const MediaQueryExpValue& value,
MediaQueryOperator,
const MediaValues& media_values) {
Expand Down
49 changes: 31 additions & 18 deletions third_party/blink/renderer/core/css/media_query_exp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "third_party/blink/renderer/core/css/css_math_function_value.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/media_feature_names.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_impl.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
Expand Down Expand Up @@ -183,6 +184,19 @@ static inline bool FeatureWithValidIdent(const String& media_feature,
}
}

if (RuntimeEnabledFeatures::CSSSnapContainerQueriesEnabled()) {
if (media_feature == media_feature_names::kSnappedMediaFeature) {
switch (ident) {
case CSSValueID::kNone:
case CSSValueID::kBlock:
case CSSValueID::kInline:
return true;
default:
return false;
}
}
}

return false;
}

Expand Down Expand Up @@ -786,22 +800,24 @@ void MediaQueryFeatureExpNode::CollectExpressions(

MediaQueryExpNode::FeatureFlags MediaQueryFeatureExpNode::CollectFeatureFlags()
const {
FeatureFlags flags = 0;

if (exp_.IsWidthDependent()) {
flags |= kFeatureWidth;
}
if (exp_.IsHeightDependent()) {
flags |= kFeatureHeight;
}
if (exp_.IsInlineSizeDependent()) {
flags |= kFeatureInlineSize;
}
if (exp_.IsBlockSizeDependent()) {
flags |= kFeatureBlockSize;
if (exp_.MediaFeature() == media_feature_names::kStuckMediaFeature) {
return kFeatureSticky;
} else if (exp_.MediaFeature() == media_feature_names::kSnappedMediaFeature) {
return kFeatureSnap;
} else if (exp_.IsInlineSizeDependent()) {
return kFeatureInlineSize;
} else if (exp_.IsBlockSizeDependent()) {
return kFeatureBlockSize;
} else {
FeatureFlags flags = 0;
if (exp_.IsWidthDependent()) {
flags |= kFeatureWidth;
}
if (exp_.IsHeightDependent()) {
flags |= kFeatureHeight;
}
return flags;
}

return flags;
}

void MediaQueryFeatureExpNode::Trace(Visitor* visitor) const {
Expand Down Expand Up @@ -843,9 +859,6 @@ MediaQueryExpNode::FeatureFlags MediaQueryFunctionExpNode::CollectFeatureFlags()
if (name_ == AtomicString("style")) {
flags |= kFeatureStyle;
}
if (name_ == AtomicString("state")) {
flags |= kFeatureState;
}
return flags;
}

Expand Down
3 changes: 2 additions & 1 deletion third_party/blink/renderer/core/css/media_query_exp.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,8 @@ class CORE_EXPORT MediaQueryExpNode
kFeatureInlineSize = 1 << 4,
kFeatureBlockSize = 1 << 5,
kFeatureStyle = 1 << 6,
kFeatureState = 1 << 7,
kFeatureSticky = 1 << 7,
kFeatureSnap = 1 << 8,
};

using FeatureFlags = unsigned;
Expand Down

0 comments on commit c7781f2

Please sign in to comment.