Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Libraries/LibWeb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,7 @@ set(SOURCES
Painting/ResolvedCSSFilter.cpp
Painting/ResizeHandle.cpp
Painting/Scrollbar.cpp
Painting/ScrollSnap.cpp
Painting/ScrollState.cpp
Painting/SVGMasking.cpp
Painting/ViewportPaintable.cpp
Expand Down
19 changes: 19 additions & 0 deletions Libraries/LibWeb/CSS/ComputedValues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ static void register_style_group_field_descriptors()
add(misc_reset, PropertyID::ViewTransitionName, 0, GROUP_FIELD_REQUIRE_KEYWORD, to_underlying(Keyword::None), nullptr);
add(misc_reset, PropertyID::TouchAction, 0, GROUP_FIELD_REQUIRE_INITIAL_VALUE, 0, nullptr);
add(misc_reset, PropertyID::ScrollBehavior, offsetof(MiscReset, scroll_behavior), GROUP_FIELD_ENUM_KEYWORD, 0, &keyword_code_table<keyword_to_scroll_behavior>());
add(misc_reset, PropertyID::ScrollSnapAlign, 0, GROUP_FIELD_REQUIRE_INITIAL_VALUE, 0, nullptr);
add(misc_reset, PropertyID::ScrollSnapStop, offsetof(MiscReset, scroll_snap_stop), GROUP_FIELD_ENUM_KEYWORD, 0, &keyword_code_table<keyword_to_scroll_snap_stop>());
add(misc_reset, PropertyID::ScrollSnapType, 0, GROUP_FIELD_REQUIRE_INITIAL_VALUE, 0, nullptr);
add(misc_reset, PropertyID::ScrollbarGutter, 0, GROUP_FIELD_REQUIRE_INITIAL_VALUE, 0, nullptr);
add(misc_reset, PropertyID::ScrollbarWidth, offsetof(MiscReset, scrollbar_width), GROUP_FIELD_ENUM_KEYWORD, 0, &keyword_code_table<keyword_to_scrollbar_width>());
add(misc_reset, PropertyID::ShapeImageThreshold, offsetof(MiscReset, shape_image_threshold), GROUP_FIELD_RESOLVED_F64, 0, nullptr);
Expand Down Expand Up @@ -1083,6 +1086,22 @@ TouchActionData ComputedValues::MiscResetValues::touch_action_value() const
};
}

ScrollSnapAlignData ComputedValues::MiscResetValues::scroll_snap_align_value() const
{
return {
.block_alignment = static_cast<ScrollSnapAlign>(scroll_snap_align_block),
.inline_alignment = static_cast<ScrollSnapAlign>(scroll_snap_align_inline),
};
}

ScrollSnapType ComputedValues::MiscResetValues::scroll_snap_type_value() const
{
return {
.axis = static_cast<ScrollSnapAxis>(scroll_snap_axis),
.strictness = static_cast<ScrollSnapStrictness>(scroll_snap_strictness),
};
}

ShapeOutsideData ComputedValues::MiscResetValues::shape_outside_value() const
{
ShapeOutsideData result;
Expand Down
22 changes: 22 additions & 0 deletions Libraries/LibWeb/CSS/ComputedValues.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,20 @@ struct ScrollbarColorData {
bool operator==(ScrollbarColorData const&) const = default;
};

struct ScrollSnapType {
ScrollSnapAxis axis { ScrollSnapAxis::Both };
ScrollSnapStrictness strictness { ScrollSnapStrictness::None };

bool operator==(ScrollSnapType const&) const = default;
};

struct ScrollSnapAlignData {
ScrollSnapAlign block_alignment { ScrollSnapAlign::None };
ScrollSnapAlign inline_alignment { ScrollSnapAlign::None };

bool operator==(ScrollSnapAlignData const&) const = default;
};

struct TextIndentData {
LengthPercentage length_percentage;
bool each_line { false };
Expand Down Expand Up @@ -563,6 +577,9 @@ class InitialValues {
static int math_depth() { return 0; }

static ScrollBehavior scroll_behavior() { return ScrollBehavior::Auto; }
static ScrollSnapAlignData scroll_snap_align() { return {}; }
static ScrollSnapStop scroll_snap_stop() { return ScrollSnapStop::Normal; }
static ScrollSnapType scroll_snap_type() { return {}; }
static ScrollbarColorData scrollbar_color()
{
return ScrollbarColorData {
Expand Down Expand Up @@ -1628,6 +1645,9 @@ class WEB_API ComputedValues final : public RefCounted<ComputedValues> {
int math_depth() const { return m_inherited.font->math_depth; }

ScrollBehavior scroll_behavior() const { return static_cast<ScrollBehavior>(m_noninherited.misc->scroll_behavior); }
ScrollSnapAlignData scroll_snap_align() const { return m_noninherited.misc->scroll_snap_align_value(); }
ScrollSnapStop scroll_snap_stop() const { return static_cast<ScrollSnapStop>(m_noninherited.misc->scroll_snap_stop); }
ScrollSnapType scroll_snap_type() const { return m_noninherited.misc->scroll_snap_type_value(); }
ScrollbarColorData scrollbar_color() const { return m_inherited.ui->scrollbar_color_value(); }
ScrollbarGutter scrollbar_gutter() const { return static_cast<ScrollbarGutter>(m_noninherited.misc->scrollbar_gutter); }
ScrollbarWidth scrollbar_width() const { return static_cast<ScrollbarWidth>(m_noninherited.misc->scrollbar_width); }
Expand Down Expand Up @@ -2335,6 +2355,8 @@ class WEB_API ComputedValues final : public RefCounted<ComputedValues> {
Position object_position_value() const;
Optional<Utf16FlyString> view_transition_name_value() const;
TouchActionData touch_action_value() const;
ScrollSnapAlignData scroll_snap_align_value() const;
ScrollSnapType scroll_snap_type_value() const;
ShapeOutsideData shape_outside_value() const;
WillChange will_change_value() const;

Expand Down
22 changes: 22 additions & 0 deletions Libraries/LibWeb/CSS/Enums.json
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,28 @@
"auto",
"smooth"
],
"scroll-snap-align": [
"none",
"start",
"end",
"center"
],
"scroll-snap-axis": [
"x",
"y",
"block",
"inline",
"both"
],
"scroll-snap-stop": [
"normal",
"always"
],
"scroll-snap-strictness": [
"none",
"proximity",
"mandatory"
],
"scrollbar-gutter": [
"auto",
"stable",
Expand Down
2 changes: 2 additions & 0 deletions Libraries/LibWeb/CSS/Keywords.json
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@
"maithili",
"malayalam-alpha",
"malayalam",
"mandatory",
"manipulation",
"manipuri",
"marathi",
Expand Down Expand Up @@ -547,6 +548,7 @@
"prophoto-rgb",
"proportional-nums",
"proportional-width",
"proximity",
"punjabi",
"push-button",
"r",
Expand Down
1 change: 1 addition & 0 deletions Libraries/LibWeb/CSS/Parser/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,7 @@ class Parser {
RefPtr<StyleValue const> parse_position_visibility_value(TokenStream<ComponentValue>&);
RefPtr<StyleValue const> parse_quotes_value(TokenStream<ComponentValue>&);
RefPtr<StyleValue const> parse_single_repeat_style_value(PropertyID, TokenStream<ComponentValue>&);
RefPtr<StyleValue const> parse_scroll_snap_type_value(TokenStream<ComponentValue>&);
RefPtr<StyleValue const> parse_scroll_timeline_value(TokenStream<ComponentValue>&);
RefPtr<StyleValue const> parse_scrollbar_color_value(TokenStream<ComponentValue>&);
RefPtr<StyleValue const> parse_scrollbar_gutter_value(TokenStream<ComponentValue>&);
Expand Down
27 changes: 27 additions & 0 deletions Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,8 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue const>> Parser::parse_css_value(Pr
return parse_all_as(tokens, [this](auto& tokens) { return parse_quotes_value(tokens); });
case PropertyID::Rotate:
return parse_all_as(tokens, [this](auto& tokens) { return parse_rotate_value(tokens); });
case PropertyID::ScrollSnapType:
return parse_all_as(tokens, [this](auto& tokens) { return parse_scroll_snap_type_value(tokens); });
case PropertyID::ScrollbarColor:
return parse_all_as(tokens, [this](auto& tokens) { return parse_scrollbar_color_value(tokens); });
case PropertyID::ScrollbarGutter:
Expand Down Expand Up @@ -4842,6 +4844,31 @@ RefPtr<StyleValue const> Parser::parse_scrollbar_gutter_value(TokenStream<Compon
return ScrollbarGutterStyleValue::create(gutter_value);
}

// https://drafts.csswg.org/css-scroll-snap-1/#scroll-snap-type
RefPtr<StyleValue const> Parser::parse_scroll_snap_type_value(TokenStream<ComponentValue>& tokens)
{
// none | [ x | y | block | inline | both ] [ mandatory | proximity ]?
auto transaction = tokens.begin_transaction();

if (auto none = parse_specific_keyword_value(tokens, { { Keyword::None } })) {
transaction.commit();
return none;
}

auto axis = parse_specific_keyword_value(tokens, { { Keyword::X, Keyword::Y, Keyword::Block, Keyword::Inline, Keyword::Both } });
if (!axis)
return nullptr;

auto strictness = parse_specific_keyword_value(tokens, { { Keyword::Mandatory, Keyword::Proximity } });
transaction.commit();

// Proximity is the default strictness, so the single-keyword form is the shortest serialization of such values.
if (!strictness || strictness->to_keyword() == Keyword::Proximity)
return axis;

return StyleValueList::create(StyleValueVector { axis.release_nonnull(), strictness.release_nonnull() }, StyleValueList::Separator::Space);
}

RefPtr<StyleValue const> Parser::parse_grid_track_placement_shorthand_value(PropertyID property_id, TokenStream<ComponentValue>& tokens)
{
auto start_property = (property_id == PropertyID::GridColumn) ? PropertyID::GridColumnStart : PropertyID::GridRowStart;
Expand Down
31 changes: 31 additions & 0 deletions Libraries/LibWeb/CSS/Properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -4303,6 +4303,37 @@
],
"percentages-resolve-to": "length"
},
"scroll-snap-align": {
"style-group": "MiscResetValues",
"affects-layout": false,
"animation-type": "discrete",
"inherited": false,
"initial": "none",
"max-values": 2,
"requires-computation": "never",
"valid-types": [
"scroll-snap-align"
]
},
"scroll-snap-stop": {
"style-group": "MiscResetValues",
"affects-layout": false,
"animation-type": "discrete",
"inherited": false,
"initial": "normal",
"requires-computation": "never",
"valid-types": [
"scroll-snap-stop"
]
},
"scroll-snap-type": {
"style-group": "MiscResetValues",
"affects-layout": false,
"animation-type": "discrete",
"inherited": false,
"initial": "none",
"requires-computation": "never"
},
"scroll-timeline": {
"affects-layout": false,
"initial": "none block",
Expand Down
12 changes: 12 additions & 0 deletions Libraries/LibWeb/CSS/StyleInvalidation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,18 @@ RequiredInvalidationAfterStyleChange compute_property_invalidation(CSS::Property
if (CSS::property_affects_scrollable_overflow(property_id))
invalidation.set_needs_scrollable_overflow_recalculation();

// https://drafts.csswg.org/css-scroll-snap-1/#re-snap
// NB: A scroll snap property change moves the snap positions of a snap container without necessarily changing
// layout, so snap containers re-evaluate their scroll position for these properties as they do after a
// layout change.
if (CSS::property_affects_scrollable_overflow(property_id)
|| AK::first_is_one_of(property_id,
CSS::PropertyID::ScrollSnapType, CSS::PropertyID::ScrollSnapAlign, CSS::PropertyID::ScrollSnapStop,
CSS::PropertyID::ScrollMarginTop, CSS::PropertyID::ScrollMarginRight, CSS::PropertyID::ScrollMarginBottom, CSS::PropertyID::ScrollMarginLeft,
CSS::PropertyID::ScrollPaddingTop, CSS::PropertyID::ScrollPaddingRight, CSS::PropertyID::ScrollPaddingBottom, CSS::PropertyID::ScrollPaddingLeft)) {
invalidation.needs_scroll_container_resnap = true;
}

if (CSS::property_affects_stacking_context(property_id)) {
// z-index changes always require rebuilding the stacking context tree because
// the value determines painting order within the tree, not just whether a
Expand Down
4 changes: 4 additions & 0 deletions Libraries/LibWeb/CSS/StyleInvalidation.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ struct RequiredInvalidationAfterStyleChange {
[[nodiscard]] bool needs_scrollable_overflow_recalculation() const { return m_needs_scrollable_overflow_recalculation && !needs_relayout(); }
[[nodiscard]] AccumulatedVisualContextInvalidation accumulated_visual_contexts() const { return m_accumulated_visual_contexts; }

// A scroll snap property changed, so snap containers must re-evaluate their scroll position and re-snap.
bool needs_scroll_container_resnap : 1 { false };
// The element's change affects rule matching for descendants, without necessarily changing inherited style.
bool recompute_descendant_styles : 1 { false };
// Names the inherited ComputedValues groups whose identities changed. Descendants can use the
Expand Down Expand Up @@ -98,6 +100,7 @@ struct RequiredInvalidationAfterStyleChange {
m_accumulated_visual_contexts = max(m_accumulated_visual_contexts, other.m_accumulated_visual_contexts);
m_rebuild_stacking_context_tree |= other.m_rebuild_stacking_context_tree;
m_needs_scrollable_overflow_recalculation |= other.m_needs_scrollable_overflow_recalculation;
needs_scroll_container_resnap |= other.needs_scroll_container_resnap;
recompute_descendant_styles |= other.recompute_descendant_styles;
m_inherited_style_groups_changed |= other.m_inherited_style_groups_changed;
changes_containing_block_establishment |= other.changes_containing_block_establishment;
Expand All @@ -110,6 +113,7 @@ struct RequiredInvalidationAfterStyleChange {
return m_level == InvalidationLevel::None
&& m_accumulated_visual_contexts == AccumulatedVisualContextInvalidation::None
&& !m_needs_scrollable_overflow_recalculation
&& !needs_scroll_container_resnap
&& !recompute_descendant_styles
&& !inherited_style_changed()
&& !changes_containing_block_establishment
Expand Down
3 changes: 3 additions & 0 deletions Libraries/LibWeb/CSS/UpdateStyle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ static void apply_element_style_invalidation_after_style_change(DOM::Element& el
if (invalidation.needs_scrollable_overflow_recalculation())
element.document().schedule_scrollable_overflow_recalculation(element);

if (invalidation.needs_scroll_container_resnap)
element.document().schedule_scroll_container_resnap();

if (invalidation.changes_containing_block_establishment)
element.document().partial_relayout_invalidation().record_escape(DOM::PartialRelayoutEscapeReason::ContainingBlockEstablishmentChangedByStyleChange);

Expand Down
22 changes: 19 additions & 3 deletions Libraries/LibWeb/Compositor/AsyncScrollTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,24 @@ Optional<AsyncScrollNodeID> AsyncScrollTree::scroll_node_id_for_stable_id(AsyncS
return {};
}

WheelHitTestResult AsyncScrollTree::hit_test_scroll_node_for_wheel(Gfx::FloatPoint position, Gfx::FloatPoint delta) const
WheelHitTestResult AsyncScrollTree::hit_test_scroll_node_for_wheel(Gfx::FloatPoint position, Gfx::FloatPoint delta, SnapContainerHandling snap_container_handling) const
{
auto scrolled_on_the_main_thread_instead = [&](WheelHitTestResult const& result) {
if (snap_container_handling == SnapContainerHandling::ScrollOnCompositor || !result.node_id.has_value())
return false;
auto const* node = scroll_node_for_id(*result.node_id);
if (!node)
return false;
return (node->snaps_scroll_position_horizontally && delta.x() != 0)
|| (node->snaps_scroll_position_vertically && delta.y() != 0);
};
auto hit_test_result_for_wheel_scroll_of_node = [&](AsyncScrollNodeID node_id) {
auto result = hit_test_result_for_scroll_node(node_id, delta);
if (scrolled_on_the_main_thread_instead(result))
return WheelHitTestResult { {}, true };
return result;
};

if (!m_visual_context_tree)
return {};

Expand Down Expand Up @@ -377,7 +393,7 @@ WheelHitTestResult AsyncScrollTree::hit_test_scroll_node_for_wheel(Gfx::FloatPoi
continue;
if (!target.target_node_id.has_value())
return {};
return hit_test_result_for_scroll_node(*target.target_node_id, delta);
return hit_test_result_for_wheel_scroll_of_node(*target.target_node_id);
}

auto viewport_node_id = viewport_scroll_node_id();
Expand All @@ -386,7 +402,7 @@ WheelHitTestResult AsyncScrollTree::hit_test_scroll_node_for_wheel(Gfx::FloatPoi
auto const* viewport_node = scroll_node_for_id(*viewport_node_id);
if (!viewport_node || !viewport_node->scrollport_rect.to_type<float>().contains(position))
return {};
return hit_test_result_for_scroll_node(*viewport_node_id, delta);
return hit_test_result_for_wheel_scroll_of_node(*viewport_node_id);
}

bool AsyncScrollTree::scroll_node_is_viewport(AsyncScrollNodeID node_id) const
Expand Down
2 changes: 1 addition & 1 deletion Libraries/LibWeb/Compositor/AsyncScrollTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class WEB_API AsyncScrollTree {
Optional<Gfx::FloatPoint> scroll_offset_for_node(AsyncScrollNodeID, Painting::ScrollStateSnapshot const&) const;
Optional<AsyncScrollNodeID> viewport_scroll_node_id() const;
Optional<AsyncScrollNodeID> scroll_node_id_for_stable_id(AsyncScrollNodeStableID) const;
WheelHitTestResult hit_test_scroll_node_for_wheel(Gfx::FloatPoint position, Gfx::FloatPoint delta) const;
WheelHitTestResult hit_test_scroll_node_for_wheel(Gfx::FloatPoint position, Gfx::FloatPoint delta, SnapContainerHandling) const;
bool scroll_node_is_viewport(AsyncScrollNodeID) const;
Vector<AsyncScrollOffset> apply_scroll_delta(AsyncScrollNodeID, Gfx::FloatPoint delta, Painting::ScrollStateSnapshot&);
Optional<Gfx::FloatPoint> set_scroll_offset(AsyncScrollNodeID, Gfx::FloatPoint, Painting::ScrollStateSnapshot&);
Expand Down
Loading
Loading